From aa1361d04cfe09f90e7d8bece90c00dd6e4185bb Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Thu, 03 Jul 2014 16:57:47 -0400 Subject: [PATCH] Replace Dagger with Guice 4.0 beta and update Guava to 16.0.1 --- src/main/java/com/gitblit/GitBlit.java | 266 +++++++++++++++++++++++++++++++--------------------- 1 files changed, 159 insertions(+), 107 deletions(-) diff --git a/src/main/java/com/gitblit/GitBlit.java b/src/main/java/com/gitblit/GitBlit.java index fa681ac..df2f502 100644 --- a/src/main/java/com/gitblit/GitBlit.java +++ b/src/main/java/com/gitblit/GitBlit.java @@ -17,12 +17,18 @@ import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; +import java.util.Set; -import javax.inject.Singleton; +import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; import com.gitblit.Constants.AccessPermission; +import com.gitblit.Constants.Transport; import com.gitblit.manager.GitblitManager; import com.gitblit.manager.IAuthenticationManager; import com.gitblit.manager.IFederationManager; @@ -37,17 +43,13 @@ import com.gitblit.models.RepositoryModel; import com.gitblit.models.RepositoryUrl; import com.gitblit.models.UserModel; -import com.gitblit.tickets.BranchTicketService; -import com.gitblit.tickets.FileTicketService; import com.gitblit.tickets.ITicketService; import com.gitblit.tickets.NullTicketService; -import com.gitblit.tickets.RedisTicketService; import com.gitblit.transport.ssh.IPublicKeyManager; import com.gitblit.utils.StringUtils; - -import dagger.Module; -import dagger.ObjectGraph; -import dagger.Provides; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; /** * GitBlit is the aggregate manager for the Gitblit webapp. It provides all @@ -58,12 +60,13 @@ */ public class GitBlit extends GitblitManager { - private final ObjectGraph injector; + private final Injector injector; private final ServicesManager servicesManager; private ITicketService ticketService; + @Inject public GitBlit( IRuntimeManager runtimeManager, IPluginManager pluginManager, @@ -85,7 +88,7 @@ projectManager, federationManager); - this.injector = ObjectGraph.create(getModules()); + this.injector = Guice.createInjector(getModules()); this.servicesManager = new ServicesManager(this); } @@ -107,8 +110,54 @@ return this; } - protected Object [] getModules() { - return new Object [] { new GitBlitModule()}; + @Override + public boolean isServingRepositories() { + return servicesManager.isServingRepositories(); + } + + @Override + public boolean isServingHTTP() { + return servicesManager.isServingHTTP(); + } + + @Override + public boolean isServingGIT() { + return servicesManager.isServingGIT(); + } + + @Override + public boolean isServingSSH() { + return servicesManager.isServingSSH(); + } + + protected AbstractModule [] getModules() { + return new AbstractModule [] { new GitBlitModule()}; + } + + protected boolean acceptPush(Transport byTransport) { + if (byTransport == null) { + logger.info("Unknown transport, push rejected!"); + return false; + } + + Set<Transport> transports = new HashSet<Transport>(); + for (String value : getSettings().getStrings(Keys.git.acceptedPushTransports)) { + Transport transport = Transport.fromString(value); + if (transport == null) { + logger.info(String.format("Ignoring unknown registered transport %s", value)); + continue; + } + + transports.add(transport); + } + + if (transports.isEmpty()) { + // no transports are explicitly specified, all are acceptable + return true; + } + + // verify that the transport is permitted + return transports.contains(byTransport); } /** @@ -132,6 +181,12 @@ if (settings.getBoolean(Keys.git.enableGitServlet, true)) { AccessPermission permission = user.getRepositoryPermission(repository).permission; if (permission.exceeds(AccessPermission.NONE)) { + Transport transport = Transport.fromString(request.getScheme()); + if (permission.atLeast(AccessPermission.PUSH) && !acceptPush(transport)) { + // downgrade the repo permission for this transport + // because it is not an acceptable PUSH transport + permission = AccessPermission.CLONE; + } list.add(new RepositoryUrl(getRepositoryUrl(request, username, repository), permission)); } } @@ -141,6 +196,12 @@ if (!StringUtils.isEmpty(sshDaemonUrl)) { AccessPermission permission = user.getRepositoryPermission(repository).permission; if (permission.exceeds(AccessPermission.NONE)) { + if (permission.atLeast(AccessPermission.PUSH) && !acceptPush(Transport.SSH)) { + // downgrade the repo permission for this transport + // because it is not an acceptable PUSH transport + permission = AccessPermission.CLONE; + } + list.add(new RepositoryUrl(sshDaemonUrl, permission)); } } @@ -150,6 +211,11 @@ if (!StringUtils.isEmpty(gitDaemonUrl)) { AccessPermission permission = servicesManager.getGitDaemonAccessPermission(user, repository); if (permission.exceeds(AccessPermission.NONE)) { + if (permission.atLeast(AccessPermission.PUSH) && !acceptPush(Transport.GIT)) { + // downgrade the repo permission for this transport + // because it is not an acceptable PUSH transport + permission = AccessPermission.CLONE; + } list.add(new RepositoryUrl(gitDaemonUrl, permission)); } } @@ -168,6 +234,52 @@ list.add(new RepositoryUrl(MessageFormat.format(url, repository.name), null)); } } + + // sort transports by highest permission and then by transport security + Collections.sort(list, new Comparator<RepositoryUrl>() { + + @Override + public int compare(RepositoryUrl o1, RepositoryUrl o2) { + if (!o1.isExternal() && o2.isExternal()) { + // prefer Gitblit over external + return -1; + } else if (o1.isExternal() && !o2.isExternal()) { + // prefer Gitblit over external + return 1; + } else if (o1.isExternal() && o2.isExternal()) { + // sort by Transport ordinal + return o1.transport.compareTo(o2.transport); + } else if (o1.permission.exceeds(o2.permission)) { + // prefer highest permission + return -1; + } else if (o2.permission.exceeds(o1.permission)) { + // prefer highest permission + return 1; + } + + // prefer more secure transports + return o1.transport.compareTo(o2.transport); + } + }); + + // consider the user's transport preference + RepositoryUrl preferredUrl = null; + Transport preferredTransport = user.getPreferences().getTransport(); + if (preferredTransport != null) { + Iterator<RepositoryUrl> itr = list.iterator(); + while (itr.hasNext()) { + RepositoryUrl url = itr.next(); + if (url.transport.equals(preferredTransport)) { + itr.remove(); + preferredUrl = url; + break; + } + } + } + if (preferredUrl != null) { + list.add(0, preferredUrl); + } + return list; } @@ -191,6 +303,24 @@ } /** + * Delete the user and all associated public ssh keys. + */ + @Override + public boolean deleteUser(String username) { + UserModel user = userManager.getUserModel(username); + return deleteUserModel(user); + } + + @Override + public boolean deleteUserModel(UserModel model) { + boolean success = userManager.deleteUserModel(model); + if (success) { + getPublicKeyManager().removeAllKeys(model.username); + } + return success; + } + + /** * Delete the repository and all associated tickets. */ @Override @@ -203,7 +333,7 @@ public boolean deleteRepositoryModel(RepositoryModel model) { boolean success = repositoryManager.deleteRepositoryModel(model); if (success && ticketService != null) { - return ticketService.deleteAll(model); + ticketService.deleteAll(model); } return success; } @@ -225,7 +355,7 @@ } try { Class<? extends ITicketService> serviceClass = (Class<? extends ITicketService>) Class.forName(clazz); - ticketService = injector.get(serviceClass).start(); + ticketService = injector.getInstance(serviceClass).start(); if (ticketService instanceof NullTicketService) { logger.warn("No ticket service configured."); } else if (ticketService.isReady()) { @@ -235,109 +365,31 @@ } } catch (Exception e) { logger.error("failed to create ticket service " + clazz, e); - ticketService = injector.get(NullTicketService.class).start(); + ticketService = injector.getInstance(NullTicketService.class).start(); } } /** - * A nested Dagger graph is used for constructor dependency injection of + * A nested Guice Module is used for constructor dependency injection of * complex classes. * * @author James Moger * */ - @Module( - library = true, - injects = { - IStoredSettings.class, + class GitBlitModule extends AbstractModule { - // core managers - IRuntimeManager.class, - INotificationManager.class, - IUserManager.class, - IAuthenticationManager.class, - IRepositoryManager.class, - IProjectManager.class, - IFederationManager.class, - - // the monolithic manager - IGitblit.class, - - // ticket services - NullTicketService.class, - FileTicketService.class, - BranchTicketService.class, - RedisTicketService.class - } - ) - class GitBlitModule { - - @Provides @Singleton IStoredSettings provideSettings() { - return settings; - } - - @Provides @Singleton IRuntimeManager provideRuntimeManager() { - return runtimeManager; - } - - @Provides @Singleton INotificationManager provideNotificationManager() { - return notificationManager; - } - - @Provides @Singleton IUserManager provideUserManager() { - return userManager; - } - - @Provides @Singleton IAuthenticationManager provideAuthenticationManager() { - return authenticationManager; - } - - @Provides @Singleton IRepositoryManager provideRepositoryManager() { - return repositoryManager; - } - - @Provides @Singleton IProjectManager provideProjectManager() { - return projectManager; - } - - @Provides @Singleton IFederationManager provideFederationManager() { - return federationManager; - } - - @Provides @Singleton IGitblit provideGitblit() { - return GitBlit.this; - } - - @Provides @Singleton NullTicketService provideNullTicketService() { - return new NullTicketService( - runtimeManager, - notificationManager, - userManager, - repositoryManager); - } - - @Provides @Singleton FileTicketService provideFileTicketService() { - return new FileTicketService( - runtimeManager, - notificationManager, - userManager, - repositoryManager); - } - - @Provides @Singleton BranchTicketService provideBranchTicketService() { - return new BranchTicketService( - runtimeManager, - notificationManager, - userManager, - repositoryManager); - } - - @Provides @Singleton RedisTicketService provideRedisTicketService() { - return new RedisTicketService( - runtimeManager, - notificationManager, - userManager, - repositoryManager); + @Override + protected void configure() { + bind(IStoredSettings.class).toInstance(settings); + bind(IRuntimeManager.class).toInstance(runtimeManager); + bind(IPluginManager.class).toInstance(pluginManager); + bind(INotificationManager.class).toInstance(notificationManager); + bind(IUserManager.class).toInstance(userManager); + bind(IAuthenticationManager.class).toInstance(authenticationManager); + bind(IRepositoryManager.class).toInstance(repositoryManager); + bind(IProjectManager.class).toInstance(projectManager); + bind(IFederationManager.class).toInstance(federationManager); + bind(IGitblit.class).toInstance(GitBlit.this); } } } -- Gitblit v1.9.1