From b5798e1e6cf15da4eb33647190e127b53410c620 Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Tue, 02 Jul 2013 14:49:06 -0400 Subject: [PATCH] Improvements to handling internal accounts (anonymous, federation user) --- src/main/java/com/gitblit/GitBlit.java | 88 +++++++++++++++++++++++++++++++++++++------- 1 files changed, 74 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java index 6fd168a..b6f7de4 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; @@ -724,6 +725,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[]) @@ -748,10 +761,7 @@ 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(); } } } @@ -838,6 +848,7 @@ if (principal != null) { String username = principal.getName(); if (!StringUtils.isEmpty(username)) { + boolean internalAccount = isInternalAccount(username); UserModel user = getUserModel(username); if (user != null) { // existing user @@ -845,7 +856,8 @@ logger.debug(MessageFormat.format("{0} authenticated by servlet container principal from {1}", user.username, httpRequest.getRemoteAddr())); return user; - } else if (settings.getBoolean(Keys.realm.container.autoCreateAccounts, true)) { + } 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; @@ -855,7 +867,7 @@ logger.debug(MessageFormat.format("{0} authenticated and created by servlet container principal from {1}", user.username, httpRequest.getRemoteAddr())); return user; - } else { + } else if (!internalAccount) { logger.warn(MessageFormat.format("Failed to find UserModel for {0}, attempted servlet container authentication from {1}", principal.getName(), httpRequest.getRemoteAddr())); } @@ -1023,6 +1035,13 @@ } 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; } /** @@ -1474,7 +1493,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; } @@ -1944,6 +1966,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); @@ -1999,7 +2022,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)); @@ -2408,6 +2431,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); @@ -2416,11 +2440,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); } } @@ -2469,6 +2494,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); @@ -2920,8 +2946,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 @@ -3402,9 +3427,8 @@ configureJGit(); configureFanout(); configureGitDaemon(); - - CommitCache.instance().setCacheDays(settings.getInteger(Keys.web.activityCacheDays, 14)); - + configureCommitCache(); + ContainerUtils.CVE_2007_0450.test(); } @@ -3514,6 +3538,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