@@ -25,10 +25,7 @@ import java.util.List; | |||
import java.util.Set; | |||
import com.google.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; | |||
@@ -39,9 +36,7 @@ import com.gitblit.manager.IProjectManager; | |||
import com.gitblit.manager.IRepositoryManager; | |||
import com.gitblit.manager.IRuntimeManager; | |||
import com.gitblit.manager.IUserManager; | |||
import com.gitblit.manager.ServicesManager; | |||
import com.gitblit.models.RepositoryModel; | |||
import com.gitblit.models.RepositoryUrl; | |||
import com.gitblit.models.UserModel; | |||
import com.gitblit.tickets.ITicketService; | |||
import com.gitblit.tickets.NullTicketService; | |||
@@ -62,8 +57,6 @@ public class GitBlit extends GitblitManager { | |||
private final Injector injector; | |||
private final ServicesManager servicesManager; | |||
private ITicketService ticketService; | |||
@Inject | |||
@@ -89,15 +82,11 @@ public class GitBlit extends GitblitManager { | |||
federationManager); | |||
this.injector = Guice.createInjector(getModules()); | |||
this.servicesManager = new ServicesManager(this); | |||
} | |||
@Override | |||
public GitBlit start() { | |||
super.start(); | |||
logger.info("Starting services manager..."); | |||
servicesManager.start(); | |||
configureTicketService(); | |||
return this; | |||
} | |||
@@ -105,184 +94,14 @@ public class GitBlit extends GitblitManager { | |||
@Override | |||
public GitBlit stop() { | |||
super.stop(); | |||
servicesManager.stop(); | |||
ticketService.stop(); | |||
return this; | |||
} | |||
@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); | |||
} | |||
/** | |||
* Returns a list of repository URLs and the user access permission. | |||
* | |||
* @param request | |||
* @param user | |||
* @param repository | |||
* @return a list of repository urls | |||
*/ | |||
@Override | |||
public List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository) { | |||
if (user == null) { | |||
user = UserModel.ANONYMOUS; | |||
} | |||
String username = StringUtils.encodeUsername(UserModel.ANONYMOUS.equals(user) ? "" : user.username); | |||
List<RepositoryUrl> list = new ArrayList<RepositoryUrl>(); | |||
// http/https url | |||
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)); | |||
} | |||
} | |||
// ssh daemon url | |||
String sshDaemonUrl = servicesManager.getSshDaemonUrl(request, user, repository); | |||
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)); | |||
} | |||
} | |||
// git daemon url | |||
String gitDaemonUrl = servicesManager.getGitDaemonUrl(request, user, repository); | |||
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)); | |||
} | |||
} | |||
// add all other urls | |||
// {0} = repository | |||
// {1} = username | |||
for (String url : settings.getStrings(Keys.web.otherUrls)) { | |||
if (url.contains("{1}")) { | |||
// external url requires username, only add url IF we have one | |||
if (!StringUtils.isEmpty(username)) { | |||
list.add(new RepositoryUrl(MessageFormat.format(url, repository.name, username), null)); | |||
} | |||
} else { | |||
// external url does not require username | |||
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; | |||
} | |||
/** | |||
* Detect renames and reindex as appropriate. | |||
*/ |
@@ -31,18 +31,21 @@ import com.gitblit.manager.IPluginManager; | |||
import com.gitblit.manager.IProjectManager; | |||
import com.gitblit.manager.IRepositoryManager; | |||
import com.gitblit.manager.IRuntimeManager; | |||
import com.gitblit.manager.IServicesManager; | |||
import com.gitblit.manager.IUserManager; | |||
import com.gitblit.manager.NotificationManager; | |||
import com.gitblit.manager.PluginManager; | |||
import com.gitblit.manager.ProjectManager; | |||
import com.gitblit.manager.RepositoryManager; | |||
import com.gitblit.manager.RuntimeManager; | |||
import com.gitblit.manager.ServicesManager; | |||
import com.gitblit.manager.UserManager; | |||
import com.gitblit.transport.ssh.FileKeyManager; | |||
import com.gitblit.transport.ssh.IPublicKeyManager; | |||
import com.gitblit.transport.ssh.MemoryKeyManager; | |||
import com.gitblit.transport.ssh.NullKeyManager; | |||
import com.gitblit.utils.StringUtils; | |||
import com.gitblit.utils.WorkQueue; | |||
import com.google.inject.AbstractModule; | |||
import com.google.inject.Provides; | |||
@@ -59,6 +62,9 @@ public class CoreModule extends AbstractModule { | |||
bind(IStoredSettings.class).toInstance(new FileSettings()); | |||
// bind complex providers | |||
bind(WorkQueue.class).toProvider(WorkQueueProvider.class); | |||
// core managers | |||
bind(IRuntimeManager.class).to(RuntimeManager.class).in(Singleton.class); | |||
bind(IPluginManager.class).to(PluginManager.class).in(Singleton.class); | |||
@@ -71,6 +77,9 @@ public class CoreModule extends AbstractModule { | |||
// the monolithic manager | |||
bind(IGitblit.class).to(GitBlit.class).in(Singleton.class); | |||
// manager for long-running daemons and services | |||
bind(IServicesManager.class).to(ServicesManager.class); | |||
} | |||
@Provides |
@@ -0,0 +1,57 @@ | |||
/* | |||
* Copyright 2014 gitblit.com. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.gitblit.guice; | |||
import com.gitblit.IStoredSettings; | |||
import com.gitblit.Keys; | |||
import com.gitblit.manager.IRuntimeManager; | |||
import com.gitblit.utils.IdGenerator; | |||
import com.gitblit.utils.WorkQueue; | |||
import com.google.inject.Inject; | |||
import com.google.inject.Provider; | |||
import com.google.inject.Singleton; | |||
/** | |||
* Provides a lazily-instantiated WorkQueue configured from IStoredSettings. | |||
* | |||
* @author James Moger | |||
* | |||
*/ | |||
@Singleton | |||
public class WorkQueueProvider implements Provider<WorkQueue> { | |||
private final IRuntimeManager runtimeManager; | |||
private volatile WorkQueue workQueue; | |||
@Inject | |||
public WorkQueueProvider(IRuntimeManager runtimeManager) { | |||
this.runtimeManager = runtimeManager; | |||
} | |||
@Override | |||
public synchronized WorkQueue get() { | |||
if (workQueue != null) { | |||
return workQueue; | |||
} | |||
IStoredSettings settings = runtimeManager.getSettings(); | |||
int defaultThreadPoolSize = settings.getInteger(Keys.execution.defaultThreadPoolSize, 1); | |||
IdGenerator idGenerator = new IdGenerator(); | |||
workQueue = new WorkQueue(idGenerator, defaultThreadPoolSize); | |||
return workQueue; | |||
} | |||
} |
@@ -49,12 +49,10 @@ import ro.fortsoft.pf4j.Version; | |||
import com.gitblit.Constants; | |||
import com.gitblit.Constants.AccessPermission; | |||
import com.gitblit.Constants.AccessRestrictionType; | |||
import com.gitblit.Constants.FederationRequest; | |||
import com.gitblit.Constants.FederationToken; | |||
import com.gitblit.GitBlitException; | |||
import com.gitblit.IStoredSettings; | |||
import com.gitblit.Keys; | |||
import com.gitblit.models.FederationModel; | |||
import com.gitblit.models.FederationProposal; | |||
import com.gitblit.models.FederationSet; | |||
@@ -68,7 +66,6 @@ import com.gitblit.models.PluginRegistry.PluginRelease; | |||
import com.gitblit.models.ProjectModel; | |||
import com.gitblit.models.RegistrantAccessPermission; | |||
import com.gitblit.models.RepositoryModel; | |||
import com.gitblit.models.RepositoryUrl; | |||
import com.gitblit.models.SearchResult; | |||
import com.gitblit.models.ServerSettings; | |||
import com.gitblit.models.ServerStatus; | |||
@@ -79,7 +76,6 @@ import com.gitblit.tickets.ITicketService; | |||
import com.gitblit.transport.ssh.IPublicKeyManager; | |||
import com.gitblit.transport.ssh.SshKey; | |||
import com.gitblit.utils.ArrayUtils; | |||
import com.gitblit.utils.HttpUtils; | |||
import com.gitblit.utils.JsonUtils; | |||
import com.gitblit.utils.ObjectCache; | |||
import com.gitblit.utils.StringUtils; | |||
@@ -350,66 +346,6 @@ public class GitblitManager implements IGitblit { | |||
} | |||
} | |||
/** | |||
* Returns a list of repository URLs and the user access permission. | |||
* | |||
* @param request | |||
* @param user | |||
* @param repository | |||
* @return a list of repository urls | |||
*/ | |||
@Override | |||
public List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository) { | |||
if (user == null) { | |||
user = UserModel.ANONYMOUS; | |||
} | |||
String username = StringUtils.encodeUsername(UserModel.ANONYMOUS.equals(user) ? "" : user.username); | |||
List<RepositoryUrl> list = new ArrayList<RepositoryUrl>(); | |||
// http/https url | |||
if (settings.getBoolean(Keys.git.enableGitServlet, true)) { | |||
AccessPermission permission = user.getRepositoryPermission(repository).permission; | |||
if (permission.exceeds(AccessPermission.NONE)) { | |||
list.add(new RepositoryUrl(getRepositoryUrl(request, username, repository), permission)); | |||
} | |||
} | |||
// add all other urls | |||
// {0} = repository | |||
// {1} = username | |||
for (String url : settings.getStrings(Keys.web.otherUrls)) { | |||
if (url.contains("{1}")) { | |||
// external url requires username, only add url IF we have one | |||
if (!StringUtils.isEmpty(username)) { | |||
list.add(new RepositoryUrl(MessageFormat.format(url, repository.name, username), null)); | |||
} | |||
} else { | |||
// external url does not require username | |||
list.add(new RepositoryUrl(MessageFormat.format(url, repository.name), null)); | |||
} | |||
} | |||
return list; | |||
} | |||
protected String getRepositoryUrl(HttpServletRequest request, String username, RepositoryModel repository) { | |||
String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null); | |||
if (StringUtils.isEmpty(gitblitUrl)) { | |||
gitblitUrl = HttpUtils.getGitblitURL(request); | |||
} | |||
StringBuilder sb = new StringBuilder(); | |||
sb.append(gitblitUrl); | |||
sb.append(Constants.R_PATH); | |||
sb.append(repository.name); | |||
// inject username into repository url if authentication is required | |||
if (repository.accessRestriction.exceeds(AccessRestrictionType.NONE) | |||
&& !StringUtils.isEmpty(username)) { | |||
sb.insert(sb.indexOf("://") + 3, username + "@"); | |||
} | |||
return sb.toString(); | |||
} | |||
/** | |||
* Returns the list of custom client applications to be used for the | |||
* repository url panel; | |||
@@ -597,26 +533,6 @@ public class GitblitManager implements IGitblit { | |||
return runtimeManager.getSettingsModel(); | |||
} | |||
@Override | |||
public boolean isServingRepositories() { | |||
return runtimeManager.isServingRepositories(); | |||
} | |||
@Override | |||
public boolean isServingHTTP() { | |||
return runtimeManager.isServingHTTP(); | |||
} | |||
@Override | |||
public boolean isServingGIT() { | |||
return runtimeManager.isServingGIT(); | |||
} | |||
@Override | |||
public boolean isServingSSH() { | |||
return runtimeManager.isServingSSH(); | |||
} | |||
@Override | |||
public TimeZone getTimezone() { | |||
return runtimeManager.getTimezone(); |
@@ -16,14 +16,10 @@ | |||
package com.gitblit.manager; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import javax.servlet.http.HttpServletRequest; | |||
import com.gitblit.GitBlitException; | |||
import com.gitblit.models.GitClientApplication; | |||
import com.gitblit.models.RepositoryModel; | |||
import com.gitblit.models.RepositoryUrl; | |||
import com.gitblit.models.TeamModel; | |||
import com.gitblit.models.UserModel; | |||
import com.gitblit.tickets.ITicketService; | |||
@@ -39,17 +35,6 @@ public interface IGitblit extends IManager, | |||
IProjectManager, | |||
IFederationManager { | |||
/** | |||
* Returns a list of repository URLs and the user access permission. | |||
* | |||
* @param request | |||
* @param user | |||
* @param repository | |||
* @return a list of repository urls | |||
* @since 1.4.0 | |||
*/ | |||
List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository); | |||
/** | |||
* Creates a complete user object. | |||
* |
@@ -50,42 +50,6 @@ public interface IRuntimeManager extends IManager { | |||
*/ | |||
Locale getLocale(); | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* or if it is merely a repository viewer. | |||
* | |||
* @return true if Gitblit is serving repositories | |||
* @since 1.4.0 | |||
*/ | |||
boolean isServingRepositories(); | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* over HTTP. | |||
* | |||
* @return true if Gitblit is serving repositories over HTTP | |||
* @since 1.6.0 | |||
*/ | |||
boolean isServingHTTP(); | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* over the GIT Daemon protocol. | |||
* | |||
* @return true if Gitblit is serving repositories over the GIT Daemon protocol | |||
* @since 1.6.0 | |||
*/ | |||
boolean isServingGIT(); | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* over the SSH protocol. | |||
* | |||
* @return true if Gitblit is serving repositories over the SSH protocol | |||
* @since 1.6.0 | |||
*/ | |||
boolean isServingSSH(); | |||
/** | |||
* Determine if this Gitblit instance is running in debug mode | |||
* |
@@ -0,0 +1,75 @@ | |||
/* | |||
* Copyright 2014 gitblit.com. | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
package com.gitblit.manager; | |||
import java.util.List; | |||
import javax.servlet.http.HttpServletRequest; | |||
import com.gitblit.models.RepositoryModel; | |||
import com.gitblit.models.RepositoryUrl; | |||
import com.gitblit.models.UserModel; | |||
public interface IServicesManager extends IManager { | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* or if it is merely a repository viewer. | |||
* | |||
* @return true if Gitblit is serving repositories | |||
* @since 1.7.0 | |||
*/ | |||
boolean isServingRepositories(); | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* over HTTP. | |||
* | |||
* @return true if Gitblit is serving repositories over HTTP | |||
* @since 1.7.0 | |||
*/ | |||
boolean isServingHTTP(); | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* over the GIT Daemon protocol. | |||
* | |||
* @return true if Gitblit is serving repositories over the GIT Daemon protocol | |||
* @since 1.7.0 | |||
*/ | |||
boolean isServingGIT(); | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* over the SSH protocol. | |||
* | |||
* @return true if Gitblit is serving repositories over the SSH protocol | |||
* @since 1.7.0 | |||
*/ | |||
boolean isServingSSH(); | |||
/** | |||
* Returns a list of repository URLs and the user access permission. | |||
* | |||
* @param request | |||
* @param user | |||
* @param repository | |||
* @return a list of repository urls | |||
* @since 1.7.0 | |||
*/ | |||
List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository); | |||
} |
@@ -1937,21 +1937,19 @@ public class RepositoryManager implements IRepositoryManager { | |||
} | |||
protected void confirmWriteAccess() { | |||
if (runtimeManager.isServingRepositories()) { | |||
try { | |||
if (!getRepositoriesFolder().exists()) { | |||
getRepositoriesFolder().mkdirs(); | |||
} | |||
File file = File.createTempFile(".test-", ".txt", getRepositoriesFolder()); | |||
file.delete(); | |||
} catch (Exception e) { | |||
logger.error(""); | |||
logger.error(Constants.BORDER2); | |||
logger.error("Please check filesystem permissions!"); | |||
logger.error("FAILED TO WRITE TO REPOSITORIES FOLDER!!", e); | |||
logger.error(Constants.BORDER2); | |||
logger.error(""); | |||
try { | |||
if (!getRepositoriesFolder().exists()) { | |||
getRepositoriesFolder().mkdirs(); | |||
} | |||
File file = File.createTempFile(".test-", ".txt", getRepositoriesFolder()); | |||
file.delete(); | |||
} catch (Exception e) { | |||
logger.error(""); | |||
logger.error(Constants.BORDER2); | |||
logger.error("Please check filesystem permissions!"); | |||
logger.error("FAILED TO WRITE TO REPOSITORIES FOLDER!!", e); | |||
logger.error(Constants.BORDER2); | |||
logger.error(""); | |||
} | |||
} | |||
} |
@@ -22,8 +22,6 @@ import java.util.Locale; | |||
import java.util.Map; | |||
import java.util.TimeZone; | |||
import com.google.inject.Inject; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
@@ -34,8 +32,11 @@ import com.gitblit.models.ServerSettings; | |||
import com.gitblit.models.ServerStatus; | |||
import com.gitblit.models.SettingModel; | |||
import com.gitblit.utils.StringUtils; | |||
import com.google.inject.Inject; | |||
import com.google.inject.Injector; | |||
import com.google.inject.Singleton; | |||
@Singleton | |||
public class RuntimeManager implements IRuntimeManager { | |||
private final Logger logger = LoggerFactory.getLogger(getClass()); | |||
@@ -123,52 +124,6 @@ public class RuntimeManager implements IRuntimeManager { | |||
return settingsModel; | |||
} | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* or if it is merely a repository viewer. | |||
* | |||
* @return true if Gitblit is serving repositories | |||
*/ | |||
@Override | |||
public boolean isServingRepositories() { | |||
return isServingHTTP() | |||
|| isServingGIT() | |||
|| isServingSSH(); | |||
} | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* over the HTTP protocol. | |||
* | |||
* @return true if Gitblit is serving repositories over the HTTP protocol | |||
*/ | |||
@Override | |||
public boolean isServingHTTP() { | |||
return settings.getBoolean(Keys.git.enableGitServlet, true); | |||
} | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* over the Git Daemon protocol. | |||
* | |||
* @return true if Gitblit is serving repositories over the Git Daemon protocol | |||
*/ | |||
@Override | |||
public boolean isServingGIT() { | |||
return settings.getInteger(Keys.git.daemonPort, 0) > 0; | |||
} | |||
/** | |||
* Determine if this Gitblit instance is actively serving git repositories | |||
* over the SSH protocol. | |||
* | |||
* @return true if Gitblit is serving repositories over the SSH protocol | |||
*/ | |||
@Override | |||
public boolean isServingSSH() { | |||
return settings.getInteger(Keys.git.sshPort, 0) > 0; | |||
} | |||
/** | |||
* Returns the preferred timezone for the Gitblit instance. | |||
* |
@@ -18,9 +18,15 @@ package com.gitblit.manager; | |||
import java.io.IOException; | |||
import java.net.URI; | |||
import java.text.MessageFormat; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Collections; | |||
import java.util.Comparator; | |||
import java.util.Date; | |||
import java.util.HashSet; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Set; | |||
import java.util.concurrent.Executors; | |||
import java.util.concurrent.ScheduledExecutorService; | |||
import java.util.concurrent.TimeUnit; | |||
@@ -30,9 +36,11 @@ import javax.servlet.http.HttpServletRequest; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
import com.gitblit.Constants; | |||
import com.gitblit.Constants.AccessPermission; | |||
import com.gitblit.Constants.AccessRestrictionType; | |||
import com.gitblit.Constants.FederationToken; | |||
import com.gitblit.Constants.Transport; | |||
import com.gitblit.IStoredSettings; | |||
import com.gitblit.Keys; | |||
import com.gitblit.fanout.FanoutNioService; | |||
@@ -40,14 +48,18 @@ import com.gitblit.fanout.FanoutService; | |||
import com.gitblit.fanout.FanoutSocketService; | |||
import com.gitblit.models.FederationModel; | |||
import com.gitblit.models.RepositoryModel; | |||
import com.gitblit.models.RepositoryUrl; | |||
import com.gitblit.models.UserModel; | |||
import com.gitblit.service.FederationPullService; | |||
import com.gitblit.transport.git.GitDaemon; | |||
import com.gitblit.transport.ssh.SshDaemon; | |||
import com.gitblit.utils.IdGenerator; | |||
import com.gitblit.utils.HttpUtils; | |||
import com.gitblit.utils.StringUtils; | |||
import com.gitblit.utils.TimeUtils; | |||
import com.gitblit.utils.WorkQueue; | |||
import com.google.inject.Inject; | |||
import com.google.inject.Provider; | |||
import com.google.inject.Singleton; | |||
/** | |||
* Services manager manages long-running services/processes that either have no | |||
@@ -57,32 +69,35 @@ import com.gitblit.utils.WorkQueue; | |||
* @author James Moger | |||
* | |||
*/ | |||
public class ServicesManager implements IManager { | |||
@Singleton | |||
public class ServicesManager implements IServicesManager { | |||
private final Logger logger = LoggerFactory.getLogger(getClass()); | |||
private final ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(5); | |||
private final Provider<WorkQueue> workQueueProvider; | |||
private final IStoredSettings settings; | |||
private final IGitblit gitblit; | |||
private final IdGenerator idGenerator; | |||
private final WorkQueue workQueue; | |||
private FanoutService fanoutService; | |||
private GitDaemon gitDaemon; | |||
private SshDaemon sshDaemon; | |||
public ServicesManager(IGitblit gitblit) { | |||
this.settings = gitblit.getSettings(); | |||
@Inject | |||
public ServicesManager( | |||
Provider<WorkQueue> workQueueProvider, | |||
IStoredSettings settings, | |||
IGitblit gitblit) { | |||
this.workQueueProvider = workQueueProvider; | |||
this.settings = settings; | |||
this.gitblit = gitblit; | |||
int defaultThreadPoolSize = settings.getInteger(Keys.execution.defaultThreadPoolSize, 1); | |||
this.idGenerator = new IdGenerator(); | |||
this.workQueue = new WorkQueue(idGenerator, defaultThreadPoolSize); | |||
} | |||
@Override | |||
@@ -107,24 +122,181 @@ public class ServicesManager implements IManager { | |||
if (sshDaemon != null) { | |||
sshDaemon.stop(); | |||
} | |||
workQueue.stop(); | |||
workQueueProvider.get().stop(); | |||
return this; | |||
} | |||
protected String getRepositoryUrl(HttpServletRequest request, String username, RepositoryModel repository) { | |||
String gitblitUrl = settings.getString(Keys.web.canonicalUrl, null); | |||
if (StringUtils.isEmpty(gitblitUrl)) { | |||
gitblitUrl = HttpUtils.getGitblitURL(request); | |||
} | |||
StringBuilder sb = new StringBuilder(); | |||
sb.append(gitblitUrl); | |||
sb.append(Constants.R_PATH); | |||
sb.append(repository.name); | |||
// inject username into repository url if authentication is required | |||
if (repository.accessRestriction.exceeds(AccessRestrictionType.NONE) | |||
&& !StringUtils.isEmpty(username)) { | |||
sb.insert(sb.indexOf("://") + 3, username + "@"); | |||
} | |||
return sb.toString(); | |||
} | |||
/** | |||
* Returns a list of repository URLs and the user access permission. | |||
* | |||
* @param request | |||
* @param user | |||
* @param repository | |||
* @return a list of repository urls | |||
*/ | |||
@Override | |||
public List<RepositoryUrl> getRepositoryUrls(HttpServletRequest request, UserModel user, RepositoryModel repository) { | |||
if (user == null) { | |||
user = UserModel.ANONYMOUS; | |||
} | |||
String username = StringUtils.encodeUsername(UserModel.ANONYMOUS.equals(user) ? "" : user.username); | |||
List<RepositoryUrl> list = new ArrayList<RepositoryUrl>(); | |||
// http/https url | |||
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)); | |||
} | |||
} | |||
// ssh daemon url | |||
String sshDaemonUrl = getSshDaemonUrl(request, user, repository); | |||
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)); | |||
} | |||
} | |||
// git daemon url | |||
String gitDaemonUrl = getGitDaemonUrl(request, user, repository); | |||
if (!StringUtils.isEmpty(gitDaemonUrl)) { | |||
AccessPermission permission = 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)); | |||
} | |||
} | |||
// add all other urls | |||
// {0} = repository | |||
// {1} = username | |||
for (String url : settings.getStrings(Keys.web.otherUrls)) { | |||
if (url.contains("{1}")) { | |||
// external url requires username, only add url IF we have one | |||
if (!StringUtils.isEmpty(username)) { | |||
list.add(new RepositoryUrl(MessageFormat.format(url, repository.name, username), null)); | |||
} | |||
} else { | |||
// external url does not require username | |||
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; | |||
} | |||
/* (non-Javadoc) | |||
* @see com.gitblit.manager.IServicesManager#isServingRepositories() | |||
*/ | |||
@Override | |||
public boolean isServingRepositories() { | |||
return isServingHTTP() | |||
|| isServingGIT() | |||
|| isServingSSH(); | |||
} | |||
/* (non-Javadoc) | |||
* @see com.gitblit.manager.IServicesManager#isServingHTTP() | |||
*/ | |||
@Override | |||
public boolean isServingHTTP() { | |||
return settings.getBoolean(Keys.git.enableGitServlet, true); | |||
} | |||
/* (non-Javadoc) | |||
* @see com.gitblit.manager.IServicesManager#isServingGIT() | |||
*/ | |||
@Override | |||
public boolean isServingGIT() { | |||
return gitDaemon != null && gitDaemon.isRunning(); | |||
} | |||
/* (non-Javadoc) | |||
* @see com.gitblit.manager.IServicesManager#isServingSSH() | |||
*/ | |||
@Override | |||
public boolean isServingSSH() { | |||
return sshDaemon != null && sshDaemon.isRunning(); | |||
} | |||
@@ -158,6 +330,32 @@ public class ServicesManager implements IManager { | |||
} | |||
} | |||
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 : settings.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); | |||
} | |||
protected void configureGitDaemon() { | |||
int port = settings.getInteger(Keys.git.daemonPort, 0); | |||
String bindInterface = settings.getString(Keys.git.daemonBindInterface, "localhost"); | |||
@@ -179,7 +377,7 @@ public class ServicesManager implements IManager { | |||
String bindInterface = settings.getString(Keys.git.sshBindInterface, "localhost"); | |||
if (port > 0) { | |||
try { | |||
sshDaemon = new SshDaemon(gitblit, workQueue); | |||
sshDaemon = new SshDaemon(gitblit, workQueueProvider.get()); | |||
sshDaemon.start(); | |||
} catch (IOException e) { | |||
sshDaemon = null; | |||
@@ -285,7 +483,7 @@ public class ServicesManager implements IManager { | |||
*/ | |||
protected String getHostname(HttpServletRequest request) { | |||
String hostname = request.getServerName(); | |||
String canonicalUrl = gitblit.getSettings().getString(Keys.web.canonicalUrl, null); | |||
String canonicalUrl = settings.getString(Keys.web.canonicalUrl, null); | |||
if (!StringUtils.isEmpty(canonicalUrl)) { | |||
try { | |||
URI uri = new URI(canonicalUrl); |
@@ -51,6 +51,7 @@ import com.gitblit.manager.IPluginManager; | |||
import com.gitblit.manager.IProjectManager; | |||
import com.gitblit.manager.IRepositoryManager; | |||
import com.gitblit.manager.IRuntimeManager; | |||
import com.gitblit.manager.IServicesManager; | |||
import com.gitblit.manager.IUserManager; | |||
import com.gitblit.transport.ssh.IPublicKeyManager; | |||
import com.gitblit.utils.ContainerUtils; | |||
@@ -200,6 +201,7 @@ public class GitblitContext extends GuiceServletContextListener { | |||
startManager(injector, IProjectManager.class); | |||
startManager(injector, IFederationManager.class); | |||
startManager(injector, IGitblit.class); | |||
startManager(injector, IServicesManager.class); | |||
// start the plugin manager last so that plugins can depend on | |||
// deterministic access to all other managers in their start() methods |
@@ -21,9 +21,6 @@ import java.util.Locale; | |||
import java.util.Map; | |||
import java.util.TimeZone; | |||
import com.google.inject.Inject; | |||
import com.google.inject.Singleton; | |||
import org.apache.wicket.Application; | |||
import org.apache.wicket.Request; | |||
import org.apache.wicket.Response; | |||
@@ -46,6 +43,7 @@ import com.gitblit.manager.IPluginManager; | |||
import com.gitblit.manager.IProjectManager; | |||
import com.gitblit.manager.IRepositoryManager; | |||
import com.gitblit.manager.IRuntimeManager; | |||
import com.gitblit.manager.IServicesManager; | |||
import com.gitblit.manager.IUserManager; | |||
import com.gitblit.tickets.ITicketService; | |||
import com.gitblit.transport.ssh.IPublicKeyManager; | |||
@@ -92,6 +90,8 @@ import com.gitblit.wicket.pages.TicketsPage; | |||
import com.gitblit.wicket.pages.TreePage; | |||
import com.gitblit.wicket.pages.UserPage; | |||
import com.gitblit.wicket.pages.UsersPage; | |||
import com.google.inject.Inject; | |||
import com.google.inject.Singleton; | |||
@Singleton | |||
public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { | |||
@@ -124,6 +124,8 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { | |||
private final IGitblit gitblit; | |||
private final IServicesManager services; | |||
@Inject | |||
public GitBlitWebApp( | |||
IRuntimeManager runtimeManager, | |||
@@ -135,7 +137,8 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { | |||
IRepositoryManager repositoryManager, | |||
IProjectManager projectManager, | |||
IFederationManager federationManager, | |||
IGitblit gitblit) { | |||
IGitblit gitblit, | |||
IServicesManager services) { | |||
super(); | |||
this.settings = runtimeManager.getSettings(); | |||
@@ -149,6 +152,7 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { | |||
this.projectManager = projectManager; | |||
this.federationManager = federationManager; | |||
this.gitblit = gitblit; | |||
this.services = services; | |||
} | |||
@Override | |||
@@ -420,6 +424,14 @@ public class GitBlitWebApp extends WebApplication implements GitblitWicketApp { | |||
return gitblit; | |||
} | |||
/* (non-Javadoc) | |||
* @see com.gitblit.wicket.Webapp#services() | |||
*/ | |||
@Override | |||
public IServicesManager services() { | |||
return services; | |||
} | |||
/* (non-Javadoc) | |||
* @see com.gitblit.wicket.Webapp#tickets() | |||
*/ |
@@ -14,6 +14,7 @@ import com.gitblit.manager.IPluginManager; | |||
import com.gitblit.manager.IProjectManager; | |||
import com.gitblit.manager.IRepositoryManager; | |||
import com.gitblit.manager.IRuntimeManager; | |||
import com.gitblit.manager.IServicesManager; | |||
import com.gitblit.manager.IUserManager; | |||
import com.gitblit.tickets.ITicketService; | |||
import com.gitblit.transport.ssh.IPublicKeyManager; | |||
@@ -65,6 +66,8 @@ public interface GitblitWicketApp { | |||
public abstract IGitblit gitblit(); | |||
public abstract IServicesManager services(); | |||
public abstract ITicketService tickets(); | |||
public abstract TimeZone getTimezone(); |
@@ -55,7 +55,7 @@ public class EmptyRepositoryPage extends RepositoryPage { | |||
} | |||
HttpServletRequest req = ((WebRequest) getRequest()).getHttpServletRequest(); | |||
List<RepositoryUrl> repositoryUrls = app().gitblit().getRepositoryUrls(req, user, repository); | |||
List<RepositoryUrl> repositoryUrls = app().services().getRepositoryUrls(req, user, repository); | |||
RepositoryUrl primaryUrl = repositoryUrls.size() == 0 ? null : repositoryUrls.get(0); | |||
String url = primaryUrl != null ? primaryUrl.url : ""; | |||
@@ -1505,7 +1505,7 @@ public class TicketPage extends RepositoryPage { | |||
*/ | |||
protected RepositoryUrl getRepositoryUrl(UserModel user, RepositoryModel repository) { | |||
HttpServletRequest req = ((WebRequest) getRequest()).getHttpServletRequest(); | |||
List<RepositoryUrl> urls = app().gitblit().getRepositoryUrls(req, user, repository); | |||
List<RepositoryUrl> urls = app().services().getRepositoryUrls(req, user, repository); | |||
if (ArrayUtils.isEmpty(urls)) { | |||
return null; | |||
} |
@@ -104,7 +104,7 @@ public class UserPage extends RootPage { | |||
if (isMyProfile) { | |||
addPreferences(user); | |||
if (app().gitblit().isServingSSH()) { | |||
if (app().services().isServingSSH()) { | |||
// show the SSH key management tab | |||
addSshKeys(user); | |||
} else { | |||
@@ -248,14 +248,14 @@ public class UserPage extends RootPage { | |||
emailMeOnMyTicketChanges).setVisible(app().notifier().isSendingMail())); | |||
List<Transport> availableTransports = new ArrayList<>(); | |||
if (app().gitblit().isServingSSH()) { | |||
if (app().services().isServingSSH()) { | |||
availableTransports.add(Transport.SSH); | |||
} | |||
if (app().gitblit().isServingHTTP()) { | |||
if (app().services().isServingHTTP()) { | |||
availableTransports.add(Transport.HTTPS); | |||
availableTransports.add(Transport.HTTP); | |||
} | |||
if (app().gitblit().isServingGIT()) { | |||
if (app().services().isServingGIT()) { | |||
availableTransports.add(Transport.GIT); | |||
} | |||
@@ -80,7 +80,7 @@ public class RepositoryUrlPanel extends BasePanel { | |||
HttpServletRequest req = ((WebRequest) getRequest()).getHttpServletRequest(); | |||
List<RepositoryUrl> repositoryUrls = app().gitblit().getRepositoryUrls(req, user, repository); | |||
List<RepositoryUrl> repositoryUrls = app().services().getRepositoryUrls(req, user, repository); | |||
// grab primary url from the top of the list | |||
primaryUrl = repositoryUrls.size() == 0 ? null : repositoryUrls.get(0); | |||
@@ -165,7 +165,7 @@ public class RepositoryUrlPanel extends BasePanel { | |||
if (repository.isMirror) { | |||
urlPanel.add(WicketUtils.newImage("accessRestrictionIcon", "mirror_16x16.png", | |||
getString("gb.isMirror"))); | |||
} else if (app().gitblit().isServingRepositories()) { | |||
} else if (app().services().isServingRepositories()) { | |||
switch (repository.accessRestriction) { | |||
case NONE: | |||
urlPanel.add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false)); |
@@ -82,26 +82,6 @@ public class MockRuntimeManager implements IRuntimeManager { | |||
return Locale.getDefault(); | |||
} | |||
@Override | |||
public boolean isServingRepositories() { | |||
return true; | |||
} | |||
@Override | |||
public boolean isServingHTTP() { | |||
return true; | |||
} | |||
@Override | |||
public boolean isServingGIT() { | |||
return true; | |||
} | |||
@Override | |||
public boolean isServingSSH() { | |||
return true; | |||
} | |||
@Override | |||
public boolean isDebugMode() { | |||
return true; |