]> source.dussan.org Git - gitblit.git/commitdiff
Allows integration of GitBlit as plug-in in other projects. 46/head
authorLuca Milanesio <luca.milanesio@gmail.com>
Tue, 14 Aug 2012 07:07:42 +0000 (09:07 +0200)
committerLuca Milanesio <luca@milanesio.org>
Sat, 20 Oct 2012 01:53:24 +0000 (02:53 +0100)
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

.gitignore
build.xml
pom.xml [new file with mode: 0644]
src/com/gitblit/GitBlit.java
src/com/gitblit/models/UserModel.java
src/com/gitblit/wicket/pages/BasePage.java
src/com/gitblit/wicket/pages/RepositoriesPage.java
src/com/gitblit/wicket/pages/RepositoryPage.java
tmplt.pom.xml [new file with mode: 0644]

index e93e18e440bc0f5fc15606a2c81f3ee79521f855..173bd34fe5dd30d8c2e0d399efd089a7641a91db 100644 (file)
@@ -27,3 +27,4 @@
 *.directory\r
 /.gradle
 /projects.conf
+/pom.xml
index 86b613b5638f1fcc51658aeaedff0b1e65845df1..6dca87d49bdd6e9df72395c3cbbb3bb2ac7ca114 100644 (file)
--- a/build.xml
+++ b/build.xml
        <property name="project.build.dir" value="${basedir}/build" />\r
        <property name="project.deploy.dir" value="${basedir}/deploy" />\r
        <property name="project.war.dir" value="${basedir}/war" />\r
+       <property name="project.jar.dir" value="${basedir}/jar" />\r
        <property name="project.site.dir" value="${basedir}/site" />\r
        <property name="project.resources.dir" value="${basedir}/resources" />  \r
        <property name="project.express.dir" value="${basedir}/express" />\r
+       <property name="project.maven.repo.url" value="enter here your Maven repo URL" />\r
+       <property name="project.maven.repo.id" value="gitblit.maven.repo" />\r
        <available property="hasBuildProps" file="${basedir}/build.properties"/>\r
 \r
        <!--\r
@@ -85,6 +88,8 @@
                </loadfile>     \r
                <property name="distribution.zipfile" value="gitblit-${gb.version}.zip" />\r
                <property name="distribution.warfile" value="gitblit-${gb.version}.war" />\r
+               <property name="distribution.jarfile" value="gitblit-${gb.version}.jar" />\r
+               <property name="distribution.pomfile" value="${basedir}/pom.xml" />\r
                <property name="fedclient.zipfile" value="fedclient-${gb.version}.zip" />\r
                <property name="manager.zipfile" value="manager-${gb.version}.zip" />\r
                <property name="gbapi.zipfile" value="gbapi-${gb.version}.zip" />\r
        </target>\r
 \r
        \r
+       <!--\r
+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+               Build Gitblit JAR for usage in other projects plug-ins (i.e. Gerrit)\r
+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+       -->\r
+       <target name="buildJAR" depends="compile" description="Build Gitblit JAR">\r
+\r
+               <echo>Building Gitblit JAR ${gb.version}</echo>\r
+\r
+               <delete dir="${project.jar.dir}" />\r
+\r
+               <!-- Gitblit classes -->\r
+               <mkdir dir="${project.jar.dir}"/>\r
+               <copy todir="${project.jar.dir}">\r
+                       <fileset dir="${project.build.dir}">\r
+                               <exclude name="WEB-INF/" />\r
+                               <exclude name="com/gitblit/tests/" />\r
+                               <exclude name="com/gitblit/build/**" />\r
+                               <exclude name="com/gitblit/client/**" />\r
+                               <exclude name="com/gitblit/AddIndexedBranch*.class" />\r
+                               <exclude name="com/gitblit/GitBlitServer*.class" />\r
+                               <exclude name="com/gitblit/Launcher*.class" />\r
+                               <exclude name="com/gitblit/MakeCertificate*.class" />\r
+                       </fileset>\r
+               </copy>\r
+\r
+               <!-- Build the JAR file -->\r
+               <jar basedir="${project.jar.dir}" destfile="${distribution.jarfile}" compress="true" />\r
+       </target>\r
+\r
+       <!--\r
+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+               Build pom.xml for GitBlit JAR Maven module\r
+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+       -->\r
+       <target name="buildMaven" depends="buildJAR" description="Build pom.xml for Gitblit JAR Maven module">\r
+               <copy tofile="${distribution.pomfile}" file="${distribution.pomfileTmplt}"/>\r
+               <replace file="${distribution.pomfile}" token="@gb.version@" value="${gb.version}" />\r
+       </target>\r
+\r
+       <!--\r
+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+               Install Gitblit JAR for usage as Maven module\r
+               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+       -->\r
+       <target name="installMaven" depends="buildMaven" description="Install Gitblit JAR as Maven module">\r
+               <exec executable="mvn">\r
+                       <arg value="install:install-file" />\r
+                       <arg value="-Dfile=${distribution.jarfile}" />\r
+                       <arg value="-DpomFile=${distribution.pomfile}" />\r
+                       <arg value="-DcreateChecksum=true" />\r
+               </exec>\r
+       </target>\r
+\r
+       <!--\r
+       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+       Upload Gitblit JAR to remote Maven repository\r
+       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+    -->\r
+       <target name="uploadMaven" depends="buildJAR" description="Upload Gitblit JAR to remote Maven repository">\r
+               <exec executable="mvn">\r
+                       <arg value="deploy:deploy-file" />\r
+                       <arg value="-Dfile=${distribution.jarfile}" />\r
+                       <arg value="-DpomFile=${distribution.pomfile}" />\r
+                       <arg value="-Durl=${project.maven.repo.url}" />\r
+                       <arg value="-DrepositoryId=${project.maven.repo.id}" />\r
+                       <arg value="-DcreateChecksum=true" />\r
+               </exec>\r
+       </target>\r
+\r
        <!-- \r
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
                Build the stand-alone, command-line Gitblit Federation Client\r
diff --git a/pom.xml b/pom.xml
new file mode 100644 (file)
index 0000000..406e2f6
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,7 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+               <modelVersion>4.0.0</modelVersion>
+               <groupId>com.gitblit</groupId>
+               <artifactId>gitblit</artifactId>
+               <version>1.1.0</version>
+</project>
index 36f5f35ca310b3034604900310c9a93d81fae516..a12170389fc2f3a2802dfabf4350ac48ab41c2fb 100644 (file)
@@ -55,8 +55,11 @@ import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;\r
 import javax.servlet.ServletContextListener;\r
 import javax.servlet.http.Cookie;\r
+import javax.servlet.http.HttpServletRequest;\r
 \r
 import org.apache.wicket.protocol.http.WebResponse;\r
+import org.apache.wicket.resource.ContextRelativeResource;\r
+import org.apache.wicket.util.resource.ResourceStreamNotFoundException;\r
 import org.eclipse.jgit.lib.Repository;\r
 import org.eclipse.jgit.lib.RepositoryCache;\r
 import org.eclipse.jgit.lib.RepositoryCache.FileKey;\r
@@ -98,6 +101,7 @@ import com.gitblit.utils.JsonUtils;
 import com.gitblit.utils.MetricUtils;\r
 import com.gitblit.utils.ObjectCache;\r
 import com.gitblit.utils.StringUtils;\r
+import com.gitblit.wicket.WicketUtils;\r
 \r
 /**\r
  * GitBlit is the servlet context listener singleton that acts as the core for\r
@@ -165,6 +169,11 @@ public class GitBlit implements ServletContextListener {
                }\r
        }\r
 \r
+       public GitBlit(final IUserService userService) {\r
+               this.userService = userService;\r
+               gitblit = this;\r
+       }\r
+\r
        /**\r
         * Returns the Gitblit singleton.\r
         * \r
@@ -509,6 +518,28 @@ public class GitBlit implements ServletContextListener {
                return null;\r
        }\r
 \r
+       /**\r
+        * Authenticate a user based on HTTP request paramters.\r
+        * This method is inteded to be used as fallback when other\r
+        * means of authentication are failing (username / password or cookies).\r
+        * @param httpRequest\r
+        * @return a user object or null\r
+        */\r
+       public UserModel authenticate(HttpServletRequest httpRequest) {\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * Open a file resource using the Servlet container.\r
+        * @param file to open\r
+        * @return InputStream of the opened file\r
+        * @throws ResourceStreamNotFoundException\r
+        */\r
+       public InputStream getResourceAsStream(String file) throws ResourceStreamNotFoundException {\r
+               ContextRelativeResource res = WicketUtils.getResource(file);\r
+               return res.getResourceStream().getInputStream();\r
+       }\r
+\r
        /**\r
         * Sets a cookie for the specified user.\r
         * \r
@@ -2427,10 +2458,11 @@ public class GitBlit implements ServletContextListener {
         * Parse the properties file and aggregate all the comments by the setting\r
         * key. A setting model tracks the current value, the default value, the\r
         * description of the setting and and directives about the setting.\r
+        * @param referencePropertiesInputStream\r
         * \r
         * @return Map<String, SettingModel>\r
         */\r
-       private ServerSettings loadSettingModels() {\r
+       private ServerSettings loadSettingModels(InputStream referencePropertiesInputStream) {\r
                ServerSettings settingsModel = new ServerSettings();\r
                settingsModel.supportsCredentialChanges = userService.supportsCredentialChanges();\r
                settingsModel.supportsDisplayNameChanges = userService.supportsDisplayNameChanges();\r
@@ -2440,7 +2472,7 @@ public class GitBlit implements ServletContextListener {
                        // Read bundled Gitblit properties to extract setting descriptions.\r
                        // This copy is pristine and only used for populating the setting\r
                        // models map.\r
-                       InputStream is = servletContext.getResourceAsStream("/WEB-INF/reference.properties");\r
+                       InputStream is = referencePropertiesInputStream;\r
                        BufferedReader propertiesReader = new BufferedReader(new InputStreamReader(is));\r
                        StringBuilder description = new StringBuilder();\r
                        SettingModel setting = new SettingModel();\r
@@ -2518,21 +2550,23 @@ public class GitBlit implements ServletContextListener {
                logTimezone(Constants.NAME, getTimezone());\r
 \r
                serverStatus = new ServerStatus(isGO());\r
-               String realm = settings.getString(Keys.realm.userService, "users.properties");\r
-               IUserService loginService = null;\r
-               try {\r
-                       // check to see if this "file" is a login service class\r
-                       Class<?> realmClass = Class.forName(realm);\r
-                       loginService = (IUserService) realmClass.newInstance();\r
-               } catch (Throwable t) {\r
-                       loginService = new GitblitUserService();\r
+\r
+               if (this.userService == null) {\r
+                       String realm = settings.getString(Keys.realm.userService, "users.properties");\r
+                       IUserService loginService = null;\r
+                       try {\r
+                               // check to see if this "file" is a login service class\r
+                               Class<?> realmClass = Class.forName(realm);\r
+                               loginService = (IUserService) realmClass.newInstance();\r
+                       } catch (Throwable t) {\r
+                               loginService = new GitblitUserService();\r
+                       }\r
+                       setUserService(loginService);\r
                }\r
-               setUserService(loginService);\r
                \r
                // load and cache the project metadata\r
                projectConfigs = new FileBasedConfig(getFileOrFolder(Keys.web.projectsFile, "projects.conf"), FS.detect());\r
                getProjectConfigs();\r
-               \r
                mailExecutor = new MailExecutor(settings);\r
                if (mailExecutor.isReady()) {\r
                        logger.info("Mail executor is scheduled to process the message queue every 2 minutes.");\r
@@ -2587,6 +2621,10 @@ public class GitBlit implements ServletContextListener {
         */\r
        @Override\r
        public void contextInitialized(ServletContextEvent contextEvent) {\r
+               contextInitialized(contextEvent, contextEvent.getServletContext().getResourceAsStream("/WEB-INF/reference.properties"));\r
+       }\r
+\r
+       public void contextInitialized(ServletContextEvent contextEvent, InputStream referencePropertiesInputStream) {\r
                servletContext = contextEvent.getServletContext();\r
                if (settings == null) {\r
                        // Gitblit WAR is running in a servlet container\r
@@ -2627,7 +2665,7 @@ public class GitBlit implements ServletContextListener {
                        }\r
                }\r
                \r
-               settingsModel = loadSettingModels();\r
+               settingsModel = loadSettingModels(referencePropertiesInputStream);\r
                serverStatus.servletContainer = servletContext.getServerInfo();\r
        }\r
 \r
@@ -2710,4 +2748,14 @@ public class GitBlit implements ServletContextListener {
                addToCachedRepositoryList(cloneModel);\r
                return cloneModel;\r
        }\r
+\r
+       /**\r
+        * Allow to understand if GitBlit supports and is configured to allow\r
+        * cookie-based authentication.\r
+        * \r
+        * @return status of Cookie authentication enablement.\r
+        */\r
+       public boolean allowCookieAuthentication() {\r
+               return GitBlit.getBoolean(Keys.web.allowCookieAuthentication, true) && userService.supportsCookies();\r
+       }\r
 }\r
index 8b3fe82682381face045426716dfe5976953adab..f14c1ae88cc1ad087df42c6b2f6845c62188332e 100644 (file)
@@ -217,7 +217,7 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel>
                return permission;\r
        }\r
        \r
-       private boolean canAccess(RepositoryModel repository, AccessRestrictionType ifRestriction, AccessPermission requirePermission) {\r
+       protected boolean canAccess(RepositoryModel repository, AccessRestrictionType ifRestriction, AccessPermission requirePermission) {\r
                if (repository.accessRestriction.atLeast(ifRestriction)) {\r
                        AccessPermission permission = getRepositoryPermission(repository);\r
                        return permission.atLeast(requirePermission);\r
@@ -433,4 +433,9 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel>
                }\r
                return nameVerified && emailVerified;\r
        }\r
+       \r
+       public boolean hasBranchPermission(String repositoryName, String branch) {\r
+               // Default UserModel doesn't implement branch-level security. Other Realms (i.e. Gerrit) may override this method.\r
+               return hasRepositoryPermission(repositoryName);\r
+       }\r
 }\r
index cce323fdb9bf5cea1a3e4f557b0c4b591ba093a8..4d3761147f8bfe1904a071e44cbd3ae94d569d55 100644 (file)
@@ -76,14 +76,14 @@ public abstract class BasePage extends WebPage {
                super();\r
                logger = LoggerFactory.getLogger(getClass());\r
                customizeHeader();\r
-               loginByCookie();\r
+               login();\r
        }\r
 \r
        public BasePage(PageParameters params) {\r
                super(params);\r
                logger = LoggerFactory.getLogger(getClass());\r
                customizeHeader();\r
-               loginByCookie();\r
+               login();\r
        }\r
        \r
        private void customizeHeader() {\r
@@ -127,16 +127,14 @@ public abstract class BasePage extends WebPage {
                super.onAfterRender();\r
        }       \r
 \r
-       private void loginByCookie() {\r
-               if (!GitBlit.getBoolean(Keys.web.allowCookieAuthentication, false)) {\r
-                       return;\r
-               }\r
-               UserModel user = null;\r
-\r
-               // Grab cookie from Browser Session\r
+       private void login() {\r
                Cookie[] cookies = ((WebRequest) getRequestCycle().getRequest()).getCookies();\r
-               if (cookies != null && cookies.length > 0) {\r
+               UserModel user = null;\r
+               if (GitBlit.self().allowCookieAuthentication() && cookies != null && cookies.length > 0) {\r
+                       // Grab cookie from Browser Session\r
                        user = GitBlit.self().authenticate(cookies);\r
+               } else {\r
+                       user = GitBlit.self().authenticate(((WebRequest) getRequestCycle().getRequest()).getHttpServletRequest());\r
                }\r
 \r
                // Login the user\r
index 36f2c6d533d9baf1ca17ee68c0b7fdaab620c258..97c6aa236bd1f9b8024a10233a39bf46d74c4235 100644 (file)
@@ -17,7 +17,6 @@ package com.gitblit.wicket.pages;
 \r
 import java.io.File;\r
 import java.io.FileInputStream;\r
-import java.io.FileNotFoundException;\r
 import java.io.InputStream;\r
 import java.io.InputStreamReader;\r
 import java.text.MessageFormat;\r
@@ -154,8 +153,7 @@ public class RepositoriesPage extends RootPage {
                }\r
                String message;\r
                try {                   \r
-                       ContextRelativeResource res = WicketUtils.getResource(file);\r
-                       InputStream is = res.getResourceStream().getInputStream();\r
+                   InputStream is = GitBlit.self().getResourceAsStream(file);\r
                        InputStreamReader reader = new InputStreamReader(is, Constants.CHARACTER_ENCODING);\r
                        message = MarkdownUtils.transformMarkdown(reader);\r
                        reader.close();\r
index b7cade6fd7474f97b91e6aa6cca89a6276c4ce82..fd2cbccc608ca954984755795d585f88459a0fd9 100644 (file)
@@ -48,6 +48,7 @@ import com.gitblit.Keys;
 import com.gitblit.PagesServlet;\r
 import com.gitblit.SyndicationServlet;\r
 import com.gitblit.models.ProjectModel;\r
+import com.gitblit.models.RefModel;\r
 import com.gitblit.models.RepositoryModel;\r
 import com.gitblit.models.SubmoduleModel;\r
 import com.gitblit.models.UserModel;\r
@@ -91,6 +92,19 @@ public abstract class RepositoryPage extends BasePage {
                }\r
                objectId = WicketUtils.getObject(params);\r
                \r
+               if (objectId != null) {\r
+                       RefModel branch = null;\r
+                       if ((branch = JGitUtils.getBranch(getRepository(), objectId)) != null) {\r
+                               boolean canAccess = GitBlitWebSession\r
+                                               .get()\r
+                                               .getUser()\r
+                                               .hasBranchPermission(getRepositoryModel().name,\r
+                                                               branch.reference.getName());\r
+                               if (!canAccess) {\r
+                                       error("Access denied", true);\r
+                               }\r
+                       }\r
+               }\r
                if (StringUtils.isEmpty(repositoryName)) {\r
                        error(MessageFormat.format(getString("gb.repositoryNotSpecifiedFor"), getPageName()), true);\r
                }\r
@@ -576,4 +590,4 @@ public abstract class RepositoryPage extends BasePage {
                        getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl));\r
                }\r
        }\r
-}
\ No newline at end of file
+}
diff --git a/tmplt.pom.xml b/tmplt.pom.xml
new file mode 100644 (file)
index 0000000..4abe4be
--- /dev/null
@@ -0,0 +1,7 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+               <modelVersion>4.0.0</modelVersion>
+               <groupId>com.gitblit</groupId>
+               <artifactId>gitblit</artifactId>
+               <version>@gb.version@</version>
+</project>