diff options
author | Luca Milanesio <luca.milanesio@gmail.com> | 2012-08-14 09:07:42 +0200 |
---|---|---|
committer | Luca Milanesio <luca@milanesio.org> | 2012-10-20 02:53:24 +0100 |
commit | 85f639aa3eee0b4e02eba20e6a5197b684941544 (patch) | |
tree | ef08a5119540cb7eb7d502a4ae4b40f2cae6be57 /src | |
parent | c658df9e87d65b08d5482cf04489cb0532ff83dd (diff) | |
download | gitblit-85f639aa3eee0b4e02eba20e6a5197b684941544.tar.gz gitblit-85f639aa3eee0b4e02eba20e6a5197b684941544.zip |
Allows integration of GitBlit as plug-in in other projects.
There are now three new targets on the ANT build:
- buildJAR: creates a GitBlit JAR including the GitBlit biz logic
- installMaven: install GitBlit JAR as Maven module
- uploadMaven: uploads GitBlit JAR to a Maven repository
Additional extensions have been made to allow:
a) GitBlit to load his resources outside of Wicket domain
b) GitBlit to use an injected UserService
c) Generic authentication of HTTP Request using 3rd party logic
d) Load settings programmatically from an InputStream
e) Use cookie authentication OR generic HTTP Request
authentication for Wicket pages
f) UserModel with branch-level security logic
Diffstat (limited to 'src')
-rw-r--r-- | src/com/gitblit/GitBlit.java | 74 | ||||
-rw-r--r-- | src/com/gitblit/models/UserModel.java | 7 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/BasePage.java | 18 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/RepositoriesPage.java | 4 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/RepositoryPage.java | 16 |
5 files changed, 91 insertions, 28 deletions
diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java index 36f5f35c..a1217038 100644 --- a/src/com/gitblit/GitBlit.java +++ b/src/com/gitblit/GitBlit.java @@ -55,8 +55,11 @@ import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
import org.apache.wicket.protocol.http.WebResponse;
+import org.apache.wicket.resource.ContextRelativeResource;
+import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
@@ -98,6 +101,7 @@ import com.gitblit.utils.JsonUtils; import com.gitblit.utils.MetricUtils;
import com.gitblit.utils.ObjectCache;
import com.gitblit.utils.StringUtils;
+import com.gitblit.wicket.WicketUtils;
/**
* GitBlit is the servlet context listener singleton that acts as the core for
@@ -165,6 +169,11 @@ public class GitBlit implements ServletContextListener { }
}
+ public GitBlit(final IUserService userService) {
+ this.userService = userService;
+ gitblit = this;
+ }
+
/**
* Returns the Gitblit singleton.
*
@@ -510,6 +519,28 @@ public class GitBlit implements ServletContextListener { }
/**
+ * Authenticate a user based on HTTP request paramters.
+ * This method is inteded to be used as fallback when other
+ * means of authentication are failing (username / password or cookies).
+ * @param httpRequest
+ * @return a user object or null
+ */
+ public UserModel authenticate(HttpServletRequest httpRequest) {
+ return null;
+ }
+
+ /**
+ * Open a file resource using the Servlet container.
+ * @param file to open
+ * @return InputStream of the opened file
+ * @throws ResourceStreamNotFoundException
+ */
+ public InputStream getResourceAsStream(String file) throws ResourceStreamNotFoundException {
+ ContextRelativeResource res = WicketUtils.getResource(file);
+ return res.getResourceStream().getInputStream();
+ }
+
+ /**
* Sets a cookie for the specified user.
*
* @param response
@@ -2427,10 +2458,11 @@ public class GitBlit implements ServletContextListener { * Parse the properties file and aggregate all the comments by the setting
* key. A setting model tracks the current value, the default value, the
* description of the setting and and directives about the setting.
+ * @param referencePropertiesInputStream
*
* @return Map<String, SettingModel>
*/
- private ServerSettings loadSettingModels() {
+ private ServerSettings loadSettingModels(InputStream referencePropertiesInputStream) {
ServerSettings settingsModel = new ServerSettings();
settingsModel.supportsCredentialChanges = userService.supportsCredentialChanges();
settingsModel.supportsDisplayNameChanges = userService.supportsDisplayNameChanges();
@@ -2440,7 +2472,7 @@ public class GitBlit implements ServletContextListener { // Read bundled Gitblit properties to extract setting descriptions.
// This copy is pristine and only used for populating the setting
// models map.
- InputStream is = servletContext.getResourceAsStream("/WEB-INF/reference.properties");
+ InputStream is = referencePropertiesInputStream;
BufferedReader propertiesReader = new BufferedReader(new InputStreamReader(is));
StringBuilder description = new StringBuilder();
SettingModel setting = new SettingModel();
@@ -2518,21 +2550,23 @@ public class GitBlit implements ServletContextListener { logTimezone(Constants.NAME, getTimezone());
serverStatus = new ServerStatus(isGO());
- String realm = settings.getString(Keys.realm.userService, "users.properties");
- IUserService loginService = null;
- try {
- // check to see if this "file" is a login service class
- Class<?> realmClass = Class.forName(realm);
- loginService = (IUserService) realmClass.newInstance();
- } catch (Throwable t) {
- loginService = new GitblitUserService();
+
+ if (this.userService == null) {
+ String realm = settings.getString(Keys.realm.userService, "users.properties");
+ IUserService loginService = null;
+ try {
+ // check to see if this "file" is a login service class
+ Class<?> realmClass = Class.forName(realm);
+ loginService = (IUserService) realmClass.newInstance();
+ } catch (Throwable t) {
+ loginService = new GitblitUserService();
+ }
+ setUserService(loginService);
}
- setUserService(loginService);
// load and cache the project metadata
projectConfigs = new FileBasedConfig(getFileOrFolder(Keys.web.projectsFile, "projects.conf"), FS.detect());
getProjectConfigs();
-
mailExecutor = new MailExecutor(settings);
if (mailExecutor.isReady()) {
logger.info("Mail executor is scheduled to process the message queue every 2 minutes.");
@@ -2587,6 +2621,10 @@ public class GitBlit implements ServletContextListener { */
@Override
public void contextInitialized(ServletContextEvent contextEvent) {
+ contextInitialized(contextEvent, contextEvent.getServletContext().getResourceAsStream("/WEB-INF/reference.properties"));
+ }
+
+ public void contextInitialized(ServletContextEvent contextEvent, InputStream referencePropertiesInputStream) {
servletContext = contextEvent.getServletContext();
if (settings == null) {
// Gitblit WAR is running in a servlet container
@@ -2627,7 +2665,7 @@ public class GitBlit implements ServletContextListener { }
}
- settingsModel = loadSettingModels();
+ settingsModel = loadSettingModels(referencePropertiesInputStream);
serverStatus.servletContainer = servletContext.getServerInfo();
}
@@ -2710,4 +2748,14 @@ public class GitBlit implements ServletContextListener { addToCachedRepositoryList(cloneModel);
return cloneModel;
}
+
+ /**
+ * Allow to understand if GitBlit supports and is configured to allow
+ * cookie-based authentication.
+ *
+ * @return status of Cookie authentication enablement.
+ */
+ public boolean allowCookieAuthentication() {
+ return GitBlit.getBoolean(Keys.web.allowCookieAuthentication, true) && userService.supportsCookies();
+ }
}
diff --git a/src/com/gitblit/models/UserModel.java b/src/com/gitblit/models/UserModel.java index 8b3fe826..f14c1ae8 100644 --- a/src/com/gitblit/models/UserModel.java +++ b/src/com/gitblit/models/UserModel.java @@ -217,7 +217,7 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel> return permission;
}
- private boolean canAccess(RepositoryModel repository, AccessRestrictionType ifRestriction, AccessPermission requirePermission) {
+ protected boolean canAccess(RepositoryModel repository, AccessRestrictionType ifRestriction, AccessPermission requirePermission) {
if (repository.accessRestriction.atLeast(ifRestriction)) {
AccessPermission permission = getRepositoryPermission(repository);
return permission.atLeast(requirePermission);
@@ -433,4 +433,9 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel> }
return nameVerified && emailVerified;
}
+
+ public boolean hasBranchPermission(String repositoryName, String branch) {
+ // Default UserModel doesn't implement branch-level security. Other Realms (i.e. Gerrit) may override this method.
+ return hasRepositoryPermission(repositoryName);
+ }
}
diff --git a/src/com/gitblit/wicket/pages/BasePage.java b/src/com/gitblit/wicket/pages/BasePage.java index cce323fd..4d376114 100644 --- a/src/com/gitblit/wicket/pages/BasePage.java +++ b/src/com/gitblit/wicket/pages/BasePage.java @@ -76,14 +76,14 @@ public abstract class BasePage extends WebPage { super();
logger = LoggerFactory.getLogger(getClass());
customizeHeader();
- loginByCookie();
+ login();
}
public BasePage(PageParameters params) {
super(params);
logger = LoggerFactory.getLogger(getClass());
customizeHeader();
- loginByCookie();
+ login();
}
private void customizeHeader() {
@@ -127,16 +127,14 @@ public abstract class BasePage extends WebPage { super.onAfterRender();
}
- private void loginByCookie() {
- if (!GitBlit.getBoolean(Keys.web.allowCookieAuthentication, false)) {
- return;
- }
- UserModel user = null;
-
- // Grab cookie from Browser Session
+ private void login() {
Cookie[] cookies = ((WebRequest) getRequestCycle().getRequest()).getCookies();
- if (cookies != null && cookies.length > 0) {
+ UserModel user = null;
+ if (GitBlit.self().allowCookieAuthentication() && cookies != null && cookies.length > 0) {
+ // Grab cookie from Browser Session
user = GitBlit.self().authenticate(cookies);
+ } else {
+ user = GitBlit.self().authenticate(((WebRequest) getRequestCycle().getRequest()).getHttpServletRequest());
}
// Login the user
diff --git a/src/com/gitblit/wicket/pages/RepositoriesPage.java b/src/com/gitblit/wicket/pages/RepositoriesPage.java index 36f2c6d5..97c6aa23 100644 --- a/src/com/gitblit/wicket/pages/RepositoriesPage.java +++ b/src/com/gitblit/wicket/pages/RepositoriesPage.java @@ -17,7 +17,6 @@ package com.gitblit.wicket.pages; import java.io.File;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.MessageFormat;
@@ -154,8 +153,7 @@ public class RepositoriesPage extends RootPage { }
String message;
try {
- ContextRelativeResource res = WicketUtils.getResource(file);
- InputStream is = res.getResourceStream().getInputStream();
+ InputStream is = GitBlit.self().getResourceAsStream(file);
InputStreamReader reader = new InputStreamReader(is, Constants.CHARACTER_ENCODING);
message = MarkdownUtils.transformMarkdown(reader);
reader.close();
diff --git a/src/com/gitblit/wicket/pages/RepositoryPage.java b/src/com/gitblit/wicket/pages/RepositoryPage.java index b7cade6f..fd2cbccc 100644 --- a/src/com/gitblit/wicket/pages/RepositoryPage.java +++ b/src/com/gitblit/wicket/pages/RepositoryPage.java @@ -48,6 +48,7 @@ import com.gitblit.Keys; import com.gitblit.PagesServlet;
import com.gitblit.SyndicationServlet;
import com.gitblit.models.ProjectModel;
+import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.SubmoduleModel;
import com.gitblit.models.UserModel;
@@ -91,6 +92,19 @@ public abstract class RepositoryPage extends BasePage { }
objectId = WicketUtils.getObject(params);
+ if (objectId != null) {
+ RefModel branch = null;
+ if ((branch = JGitUtils.getBranch(getRepository(), objectId)) != null) {
+ boolean canAccess = GitBlitWebSession
+ .get()
+ .getUser()
+ .hasBranchPermission(getRepositoryModel().name,
+ branch.reference.getName());
+ if (!canAccess) {
+ error("Access denied", true);
+ }
+ }
+ }
if (StringUtils.isEmpty(repositoryName)) {
error(MessageFormat.format(getString("gb.repositoryNotSpecifiedFor"), getPageName()), true);
}
@@ -576,4 +590,4 @@ public abstract class RepositoryPage extends BasePage { getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));
}
}
-}
\ No newline at end of file +} |