]> source.dussan.org Git - gitblit.git/commitdiff
Block pushes to a repository with a working copy (issue 49)
authorJames Moger <james.moger@gitblit.com>
Fri, 3 Feb 2012 23:16:16 +0000 (18:16 -0500)
committerJames Moger <james.moger@gitblit.com>
Fri, 3 Feb 2012 23:16:16 +0000 (18:16 -0500)
docs/00_index.mkd
docs/04_releases.mkd
src/com/gitblit/AccessRestrictionFilter.java
src/com/gitblit/DownloadZipFilter.java
src/com/gitblit/GitBlit.java
src/com/gitblit/GitFilter.java
src/com/gitblit/PagesFilter.java
src/com/gitblit/SyndicationFilter.java
src/com/gitblit/models/RepositoryModel.java
test-gitblit.properties
tests/com/gitblit/tests/GitServletTest.java

index e49750e17e7f92de498115330d0c55fbea25c335..a0438eefe169003fd5e6207b1b92130b6ba0f220 100644 (file)
 Gitblit is an open-source, pure Java stack for managing, viewing, and serving [Git][git] repositories.  \r
 It's designed primarily as a tool for small workgroups who want to host centralized repositories.\r
 \r
-You can browse a live demo [here](http://demo-gitblit.rhcloud.com) hosted on [RedHat's OpenShift][rhcloud] cloud service.\r
-\r
-**NOTE:**  \r
-The demo is a bit unstable due to a bug in JBossAS7/Tomcat when running in LOW_MEMORY mode which OpenShift mandates.  RedHat engineers hope to have this issue resolved soon.\r
+You can browse a live demo [here](https://demo-gitblit.rhcloud.com) hosted on [RedHat's OpenShift][rhcloud] cloud service.\r
 \r
 ### GO: Single-Stack Solution\r
 \r
index c8e9d1975f957cd50e9e667e7b6eb7bf395a1d24..e511319239c29f701520ce288992eb1fe5e48ef6 100644 (file)
@@ -6,6 +6,7 @@
 \r
 #### changes\r
 \r
+- block pushes to a repository with a working copy (i.e. non-bare repository) (issue-49)\r
 - web.datetimestampLongFormat from *EEEE, MMMM d, yyyy h:mm a z* to *EEEE, MMMM d, yyyy HH:mm Z* (issue 50)\r
 \r
 #### additions\r
index a8d50b8c8fc9bf362c804e573d9731d4eb5d9158..e9b6587b4372a53c54a647fa8491144d4aac5dc1 100644 (file)
@@ -61,6 +61,15 @@ public abstract class AccessRestrictionFilter extends AuthenticationFilter {
         */\r
        protected abstract String getUrlRequestAction(String url);\r
 \r
+       /**\r
+        * Determine if the action may be executed on the repository.\r
+        * \r
+        * @param repository\r
+        * @param action\r
+        * @return true if the action may be performed\r
+        */\r
+       protected abstract boolean isActionAllowed(RepositoryModel repository, String action);\r
+\r
        /**\r
         * Determine if the repository requires authentication.\r
         * \r
@@ -110,6 +119,14 @@ public abstract class AccessRestrictionFilter extends AuthenticationFilter {
                        httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND);\r
                        return;\r
                }\r
+               \r
+               // Confirm that the action may be executed on the repository\r
+               if (!isActionAllowed(model, urlRequestType)) {\r
+                       logger.info(MessageFormat.format("ARF: action {0} on {1} forbidden ({2})",\r
+                                       urlRequestType, model, HttpServletResponse.SC_FORBIDDEN));\r
+                       httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);\r
+                       return;\r
+               }\r
 \r
                // Wrap the HttpServletRequest with the AccessRestrictionRequest which\r
                // overrides the servlet container user principal methods.\r
index c308cbbb35d2ac7b4a280fedd8bdfad48dceaae2..d22649b5eb8753ccf98e6c070d60298f8f058a4a 100644 (file)
@@ -56,6 +56,18 @@ public class DownloadZipFilter extends AccessRestrictionFilter {
                return "DOWNLOAD";\r
        }\r
 \r
+       /**\r
+        * Determine if the action may be executed on the repository.\r
+        * \r
+        * @param repository\r
+        * @param action\r
+        * @return true if the action may be performed\r
+        */\r
+       @Override\r
+       protected boolean isActionAllowed(RepositoryModel repository, String action) {\r
+               return true;\r
+       }\r
+\r
        /**\r
         * Determine if the repository requires authentication.\r
         * \r
index a689b48ee63b4770ec069012a10c280e0d92f59d..7a6411c48dfc658e161e32a06ee9e1a3d75587f2 100644 (file)
@@ -760,6 +760,7 @@ public class GitBlit implements ServletContextListener {
                model.name = repositoryName;\r
                model.hasCommits = JGitUtils.hasCommits(r);\r
                model.lastChange = JGitUtils.getLastChange(r, null);\r
+               model.isBare = r.isBare();\r
                StoredConfig config = JGitUtils.readConfig(r);\r
                if (config != null) {\r
                        model.description = getConfig(config, "description", "");\r
index a7f0fe741abcb4f9104dc74e72d831c60f254c47..e76fd767bf2902ac47b2ec22fa973076ad9c3ba0 100644 (file)
@@ -81,6 +81,25 @@ public class GitFilter extends AccessRestrictionFilter {
                }\r
                return null;\r
        }\r
+       \r
+       /**\r
+        * Determine if the repository can receive pushes.\r
+        * \r
+        * @param repository\r
+        * @param action\r
+        * @return true if the action may be performed\r
+        */\r
+       @Override\r
+       protected boolean isActionAllowed(RepositoryModel repository, String action) {\r
+               if (action.equals(gitReceivePack)) {\r
+                       // Push request\r
+                       if (!repository.isBare) {\r
+                               logger.warn("Gitblit does not allow pushes to repositories with a working copy");\r
+                               return false;\r
+                       }\r
+               }\r
+               return true;\r
+       }\r
 \r
        /**\r
         * Determine if the repository requires authentication.\r
@@ -107,8 +126,8 @@ public class GitFilter extends AccessRestrictionFilter {
                if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {\r
                        // Git Servlet disabled\r
                        return false;\r
-               }\r
-               boolean readOnly = repository.isFrozen;\r
+               }               \r
+               boolean readOnly = repository.isFrozen; \r
                if (readOnly || repository.accessRestriction.atLeast(AccessRestrictionType.PUSH)) {\r
                        boolean authorizedUser = user.canAccessRepository(repository);\r
                        if (action.equals(gitReceivePack)) {\r
index 87fef0d2d82294bd1c0fba76c5c8c640b9e9496a..b29bede2536468022091f4a2dd620279327ce960 100644 (file)
@@ -76,6 +76,18 @@ public class PagesFilter extends AccessRestrictionFilter {
                return "VIEW";\r
        }\r
 \r
+       /**\r
+        * Determine if the action may be executed on the repository.\r
+        * \r
+        * @param repository\r
+        * @param action\r
+        * @return true if the action may be performed\r
+        */\r
+       @Override\r
+       protected boolean isActionAllowed(RepositoryModel repository, String action) {\r
+               return true;\r
+       }\r
+       \r
        /**\r
         * Determine if the repository requires authentication.\r
         * \r
index d6dd1f2d9b48e553306ca8b305a5a158ef886dc9..7e2561b9832db6f1c246f2bda89868440887bc22 100644 (file)
@@ -54,6 +54,18 @@ public class SyndicationFilter extends AccessRestrictionFilter {
                return "VIEW";\r
        }\r
 \r
+       /**\r
+        * Determine if the action may be executed on the repository.\r
+        * \r
+        * @param repository\r
+        * @param action\r
+        * @return true if the action may be performed\r
+        */\r
+       @Override\r
+       protected boolean isActionAllowed(RepositoryModel repository, String action) {\r
+               return true;\r
+       }\r
+       \r
        /**\r
         * Determine if the repository requires authentication.\r
         * \r
index b633c69e3f8bf516b817fbff798eb906be81a11e..10dcbc684307ffebff3040b1da754c84d2a4838b 100644 (file)
@@ -53,14 +53,14 @@ public class RepositoryModel implements Serializable, Comparable<RepositoryModel
        public boolean skipSizeCalculation;\r
        public boolean skipSummaryMetrics;\r
        public String frequency;\r
+       public boolean isBare;\r
        public String origin;\r
+       public String HEAD;\r
+       public List<String> availableRefs;\r
        public String size;\r
        public List<String> preReceiveScripts;\r
        public List<String> postReceiveScripts;\r
        public List<String> mailingLists;\r
-       public String HEAD;\r
-       public List<String> availableRefs;\r
-\r
        private String displayName;\r
        \r
        public RepositoryModel() {\r
index a815198b6b1cb8b22e76d6461ba95a05c54077bd..9249bbd0a2a0ebf65a47bfd345a565f56a8deccc 100644 (file)
@@ -7,7 +7,7 @@ git.searchRepositoriesSubfolders = true
 git.enableGitServlet = true
 groovy.scriptsFolder = groovy
 groovy.preReceiveScripts = blockpush
-groovy.postReceiveScripts = sendmail jenkins
+groovy.postReceiveScripts = sendmail
 web.authenticateViewPages = false
 web.authenticateAdminPages = true
 web.allowCookieAuthentication = true
index 88bbe91741b0a286719aec577d8f9f02bb6c4d7e..38d7fa9fe7cc257760f8796b60af71492d5d459a 100644 (file)
@@ -30,6 +30,8 @@ public class GitServletTest {
        static File ticgit2Folder = new File(GitBlitSuite.REPOSITORIES, "working/ticgit2");\r
 \r
        static File jgitFolder = new File(GitBlitSuite.REPOSITORIES, "working/jgit");\r
+       \r
+       static File jgit2Folder = new File(GitBlitSuite.REPOSITORIES, "working/jgit2");\r
 \r
        String url = GitBlitSuite.url;\r
        String account = GitBlitSuite.account;\r
@@ -61,6 +63,9 @@ public class GitServletTest {
                if (jgitFolder.exists()) {\r
                        FileUtils.delete(jgitFolder, FileUtils.RECURSIVE);\r
                }\r
+               if (jgit2Folder.exists()) {\r
+                       FileUtils.delete(jgit2Folder, FileUtils.RECURSIVE);\r
+               }\r
        }\r
 \r
        @Test\r
@@ -141,6 +146,34 @@ public class GitServletTest {
                close(git);\r
        }\r
        \r
+       @Test\r
+       public void testPushToNonBareRepository() throws Exception {\r
+               CloneCommand clone = Git.cloneRepository();\r
+               clone.setURI(MessageFormat.format("{0}/git/working/jgit", url));\r
+               clone.setDirectory(jgit2Folder);\r
+               clone.setBare(false);\r
+               clone.setCloneAllBranches(true);\r
+               clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password));\r
+               close(clone.call());\r
+               assertTrue(true);\r
+\r
+               Git git = Git.open(jgit2Folder);\r
+               File file = new File(jgit2Folder, "NONBARE");\r
+               OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file, true));\r
+               BufferedWriter w = new BufferedWriter(os);\r
+               w.write("// " + new Date().toString() + "\n");\r
+               w.close();\r
+               git.add().addFilepattern(file.getName()).call();\r
+               git.commit().setMessage("test commit followed by push to non-bare repository").call();\r
+               try {\r
+                       git.push().setPushAll().call();\r
+                       assertTrue(false);\r
+               } catch (Exception e) {\r
+                       assertTrue(e.getCause().getMessage().contains("git-receive-pack not permitted"));\r
+               }\r
+               close(git);\r
+       }\r
+       \r
        private void close(Git git) {\r
                // really close the repository\r
                // decrement the use counter to 0\r