From 2c616775b21ab4cd76ff170dfd5e818c9c3b79fb Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Tue, 02 Jul 2013 15:08:28 -0400
Subject: [PATCH] Fixed git servlet unit test
---
src/main/java/com/gitblit/GitBlit.java | 163 +++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 142 insertions(+), 21 deletions(-)
diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java
index df17edd..1fd52f1 100644
--- a/src/main/java/com/gitblit/GitBlit.java
+++ b/src/main/java/com/gitblit/GitBlit.java
@@ -102,6 +102,7 @@
import com.gitblit.models.GitClientApplication;
import com.gitblit.models.Metric;
import com.gitblit.models.ProjectModel;
+import com.gitblit.models.RefModel;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.RepositoryUrl;
@@ -114,6 +115,7 @@
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.Base64;
import com.gitblit.utils.ByteFormat;
+import com.gitblit.utils.CommitCache;
import com.gitblit.utils.ContainerUtils;
import com.gitblit.utils.DeepCopier;
import com.gitblit.utils.FederationUtils;
@@ -273,6 +275,15 @@
self().timezone = TimeZone.getTimeZone(tzid);
}
return self().timezone;
+ }
+
+ /**
+ * Returns the active settings.
+ *
+ * @return the active settings
+ */
+ public static IStoredSettings getSettings() {
+ return self().settings;
}
/**
@@ -509,7 +520,7 @@
if (user == null) {
user = UserModel.ANONYMOUS;
}
- String username = UserModel.ANONYMOUS.equals(user) ? "" : user.username;
+ String username = encodeUsername(UserModel.ANONYMOUS.equals(user) ? "" : user.username);
List<RepositoryUrl> list = new ArrayList<RepositoryUrl>();
// http/https url
@@ -681,7 +692,15 @@
* @return true if the user service supports credential changes
*/
public boolean supportsCredentialChanges(UserModel user) {
- return (user != null && user.isLocalAccount()) || userService.supportsCredentialChanges();
+ if (user == null) {
+ return false;
+ } else if (!Constants.EXTERNAL_ACCOUNT.equals(user.password)) {
+ // credentials likely maintained by Gitblit
+ return userService.supportsCredentialChanges();
+ } else {
+ // credentials are externally maintained
+ return false;
+ }
}
/**
@@ -715,6 +734,18 @@
}
/**
+ * Returns true if the username represents an internal account
+ *
+ * @param username
+ * @return true if the specified username represents an internal account
+ */
+ protected boolean isInternalAccount(String username) {
+ return !StringUtils.isEmpty(username)
+ && (username.equalsIgnoreCase(Constants.FEDERATION_USER)
+ || username.equalsIgnoreCase(UserModel.ANONYMOUS.username));
+ }
+
+ /**
* Authenticate a user based on a username and password.
*
* @see IUserService.authenticate(String, char[])
@@ -727,6 +758,7 @@
// can not authenticate empty username
return null;
}
+ String usernameDecoded = decodeUsername(username);
String pw = new String(password);
if (StringUtils.isEmpty(pw)) {
// can not authenticate empty password
@@ -735,13 +767,10 @@
// check to see if this is the federation user
if (canFederate()) {
- if (username.equalsIgnoreCase(Constants.FEDERATION_USER)) {
+ if (usernameDecoded.equalsIgnoreCase(Constants.FEDERATION_USER)) {
List<String> tokens = getFederationTokens();
if (tokens.contains(pw)) {
- // the federation user is an administrator
- UserModel federationUser = new UserModel(Constants.FEDERATION_USER);
- federationUser.canAdmin = true;
- return federationUser;
+ return getFederationUser();
}
}
}
@@ -750,7 +779,7 @@
if (userService == null) {
return null;
}
- return userService.authenticate(username, password);
+ return userService.authenticate(usernameDecoded, password);
}
/**
@@ -827,14 +856,27 @@
Principal principal = httpRequest.getUserPrincipal();
if (principal != null) {
String username = principal.getName();
- if (StringUtils.isEmpty(username)) {
+ if (!StringUtils.isEmpty(username)) {
+ boolean internalAccount = isInternalAccount(username);
UserModel user = getUserModel(username);
if (user != null) {
+ // existing user
flagWicketSession(AuthenticationType.CONTAINER);
logger.debug(MessageFormat.format("{0} authenticated by servlet container principal from {1}",
user.username, httpRequest.getRemoteAddr()));
return user;
- } else {
+ } else if (settings.getBoolean(Keys.realm.container.autoCreateAccounts, false)
+ && !internalAccount) {
+ // auto-create user from an authenticated container principal
+ user = new UserModel(username.toLowerCase());
+ user.displayName = username;
+ user.password = Constants.EXTERNAL_ACCOUNT;
+ userService.updateUserModel(user);
+ flagWicketSession(AuthenticationType.CONTAINER);
+ logger.debug(MessageFormat.format("{0} authenticated and created by servlet container principal from {1}",
+ user.username, httpRequest.getRemoteAddr()));
+ return user;
+ } else if (!internalAccount) {
logger.warn(MessageFormat.format("Failed to find UserModel for {0}, attempted servlet container authentication from {1}",
principal.getName(), httpRequest.getRemoteAddr()));
}
@@ -910,7 +952,10 @@
if (userService == null) {
return;
}
- if (userService.supportsCookies()) {
+ GitBlitWebSession session = GitBlitWebSession.get();
+ boolean standardLogin = session.authenticationType.isStandard();
+
+ if (userService.supportsCookies() && standardLogin) {
Cookie userCookie;
if (user == null) {
// clear cookie for logout
@@ -945,6 +990,26 @@
}
/**
+ * Encode the username for user in an url.
+ *
+ * @param name
+ * @return the encoded name
+ */
+ protected String encodeUsername(String name) {
+ return name.replace("@", "%40").replace(" ", "%20").replace("\\", "%5C");
+ }
+
+ /**
+ * Decode a username from an encoded url.
+ *
+ * @param name
+ * @return the decoded name
+ */
+ protected String decodeUsername(String name) {
+ return name.replace("%40", "@").replace("%20", " ").replace("%5C", "\\");
+ }
+
+ /**
* Returns the list of all users available to the login service.
*
* @see IUserService.getAllUsernames()
@@ -977,7 +1042,15 @@
if (StringUtils.isEmpty(username)) {
return false;
}
- return userService.deleteUser(username);
+ String usernameDecoded = decodeUsername(username);
+ return userService.deleteUser(usernameDecoded);
+ }
+
+ protected UserModel getFederationUser() {
+ // the federation user is an administrator
+ UserModel federationUser = new UserModel(Constants.FEDERATION_USER);
+ federationUser.canAdmin = true;
+ return federationUser;
}
/**
@@ -991,7 +1064,8 @@
if (StringUtils.isEmpty(username)) {
return null;
}
- UserModel user = userService.getUserModel(username);
+ String usernameDecoded = decodeUsername(username);
+ UserModel user = userService.getUserModel(usernameDecoded);
return user;
}
@@ -1428,7 +1502,10 @@
}
// return sorted copy of cached list
- List<String> list = new ArrayList<String>(repositoryListCache.keySet());
+ List<String> list = new ArrayList<String>();
+ for (RepositoryModel model : repositoryListCache.values()) {
+ list.add(model.name);
+ }
StringUtils.sortRepositorynames(list);
return list;
}
@@ -1898,6 +1975,7 @@
if (config != null) {
model.description = getConfig(config, "description", "");
+ model.originRepository = getConfig(config, "originRepository", null);
model.addOwners(ArrayUtils.fromString(getConfig(config, "owner", "")));
model.useTickets = getConfig(config, "useTickets", false);
model.useDocs = getConfig(config, "useDocs", false);
@@ -1953,7 +2031,7 @@
model.sparkleshareId = JGitUtils.getSparkleshareId(r);
r.close();
- if (model.origin != null && model.origin.startsWith("file://")) {
+ if (StringUtils.isEmpty(model.originRepository) && model.origin != null && model.origin.startsWith("file://")) {
// repository was cloned locally... perhaps as a fork
try {
File folder = new File(new URI(model.origin));
@@ -2362,6 +2440,7 @@
String origin = config.getString("remote", "origin", "url");
origin = origin.replace(repositoryName, repository.name);
config.setString("remote", "origin", "url", origin);
+ config.setString(Constants.CONFIG_GITBLIT, null, "originRepository", repository.name);
config.save();
} catch (Exception e) {
logger.error("Failed to update repository fork config for " + fork, e);
@@ -2370,11 +2449,12 @@
}
}
- // remove this repository from any origin model's fork list
+ // update this repository's origin's fork list
if (!StringUtils.isEmpty(repository.originRepository)) {
RepositoryModel origin = repositoryListCache.get(repository.originRepository);
if (origin != null && !ArrayUtils.isEmpty(origin.forks)) {
origin.forks.remove(repositoryName);
+ origin.forks.add(repository.name);
}
}
@@ -2423,6 +2503,7 @@
public void updateConfiguration(Repository r, RepositoryModel repository) {
StoredConfig config = r.getConfig();
config.setString(Constants.CONFIG_GITBLIT, null, "description", repository.description);
+ config.setString(Constants.CONFIG_GITBLIT, null, "originRepository", repository.originRepository);
config.setString(Constants.CONFIG_GITBLIT, null, "owner", ArrayUtils.toString(repository.owners));
config.setBoolean(Constants.CONFIG_GITBLIT, null, "useTickets", repository.useTickets);
config.setBoolean(Constants.CONFIG_GITBLIT, null, "useDocs", repository.useDocs);
@@ -2874,8 +2955,7 @@
String cloneUrl = sb.toString();
// Retrieve all available repositories
- UserModel user = new UserModel(Constants.FEDERATION_USER);
- user.canAdmin = true;
+ UserModel user = getFederationUser();
List<RepositoryModel> list = getRepositoryModels(user);
// create the [cloneurl, repositoryModel] map
@@ -3009,7 +3089,9 @@
if (repository != null) {
for (String teamname : userService.getTeamnamesForRepositoryRole(repository.name)) {
TeamModel team = userService.getTeamModel(teamname);
- scripts.addAll(team.preReceiveScripts);
+ if (!ArrayUtils.isEmpty(team.preReceiveScripts)) {
+ scripts.addAll(team.preReceiveScripts);
+ }
}
}
return new ArrayList<String>(scripts);
@@ -3059,7 +3141,9 @@
if (repository != null) {
for (String teamname : userService.getTeamnamesForRepositoryRole(repository.name)) {
TeamModel team = userService.getTeamModel(teamname);
- scripts.addAll(team.postReceiveScripts);
+ if (!ArrayUtils.isEmpty(team.postReceiveScripts)) {
+ scripts.addAll(team.postReceiveScripts);
+ }
}
}
return new ArrayList<String>(scripts);
@@ -3352,7 +3436,8 @@
configureJGit();
configureFanout();
configureGitDaemon();
-
+ configureCommitCache();
+
ContainerUtils.CVE_2007_0450.test();
}
@@ -3462,6 +3547,42 @@
}
}
+ protected void configureCommitCache() {
+ int daysToCache = settings.getInteger(Keys.web.activityCacheDays, 14);
+ if (daysToCache <= 0) {
+ logger.info("commit cache disabled");
+ } else {
+ long start = System.nanoTime();
+ long repoCount = 0;
+ long commitCount = 0;
+ logger.info(MessageFormat.format("preparing {0} day commit cache. please wait...", daysToCache));
+ CommitCache.instance().setCacheDays(daysToCache);
+ Date cutoff = CommitCache.instance().getCutoffDate();
+ for (String repositoryName : getRepositoryList()) {
+ RepositoryModel model = getRepositoryModel(repositoryName);
+ if (model.hasCommits && model.lastChange.after(cutoff)) {
+ repoCount++;
+ Repository repository = getRepository(repositoryName);
+ for (RefModel ref : JGitUtils.getLocalBranches(repository, true, -1)) {
+ if (!ref.getDate().after(cutoff)) {
+ // branch not recently updated
+ continue;
+ }
+ List<?> commits = CommitCache.instance().getCommits(repositoryName, repository, ref.getName());
+ if (commits.size() > 0) {
+ logger.info(MessageFormat.format(" cached {0} commits for {1}:{2}",
+ commits.size(), repositoryName, ref.getName()));
+ commitCount += commits.size();
+ }
+ }
+ repository.close();
+ }
+ }
+ logger.info(MessageFormat.format("built {0} day commit cache of {1} commits across {2} repositories in {3} msecs",
+ daysToCache, commitCount, repoCount, TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start)));
+ }
+ }
+
protected final Logger getLogger() {
return logger;
}
--
Gitblit v1.9.1