]> source.dussan.org Git - gitblit.git/commitdiff
Added SparkleShare invite url panel
authorJames Moger <james.moger@gitblit.com>
Fri, 3 May 2013 01:44:07 +0000 (21:44 -0400)
committerJames Moger <james.moger@gitblit.com>
Fri, 3 May 2013 01:44:18 +0000 (21:44 -0400)
This will probably be merged into a refined, single multi-protocol
url panel.

src/main/java/WEB-INF/web.xml
src/main/java/com/gitblit/Constants.java
src/main/java/com/gitblit/SparkleShareInviteServlet.java [new file with mode: 0644]
src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
src/main/java/com/gitblit/wicket/pages/BasePage.java
src/main/java/com/gitblit/wicket/pages/SummaryPage.html
src/main/java/com/gitblit/wicket/pages/SummaryPage.java
src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.html [new file with mode: 0644]
src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.java [new file with mode: 0644]

index 5ee5ed236fe378630b3213e9516dd7e04ee1dfb8..573305c4e2c94ca45491225c1efdc548c8afda3f 100644 (file)
                <servlet-name>GitServlet</servlet-name>         \r
                <url-pattern>/git/*</url-pattern>\r
        </servlet-mapping>\r
+\r
        \r
+       <!-- SparkleShare Invite Servlet\r
+                <url-pattern> MUST match: \r
+                       * com.gitblit.Constants.SPARKLESHARE_INVITE_PATH\r
+                       * Wicket Filter ignorePaths parameter -->\r
+       <servlet>\r
+               <servlet-name>SparkleShareInviteServlet</servlet-name>\r
+               <servlet-class>com.gitblit.SparkleShareInviteServlet</servlet-class>\r
+       </servlet>\r
+       <servlet-mapping>\r
+               <servlet-name>SparkleShareInviteServlet</servlet-name>          \r
+               <url-pattern>/sparkleshare/*</url-pattern>\r
+       </servlet-mapping>\r
+\r
        \r
        <!-- Syndication Servlet\r
                 <url-pattern> MUST match: \r
                * GitFilter <url-pattern>\r
                * GitServlet <url-pattern>\r
                * com.gitblit.Constants.GIT_PATH\r
+               * SparkleshareInviteServlet <url-pattern>\r
+               * com.gitblit.Constants.SPARKLESHARE_INVITE_PATH\r
                * Zipfilter <url-pattern>\r
                * ZipServlet <url-pattern>\r
                * com.gitblit.Constants.ZIP_PATH\r
                * PagesFilter <url-pattern>\r
                * PagesServlet <url-pattern>\r
                * com.gitblit.Constants.PAGES_PATH -->\r
-            <param-value>git/,feed/,zip/,federation/,rpc/,pages/,robots.txt</param-value>\r
+            <param-value>git/,feed/,zip/,federation/,rpc/,pages/,robots.txt,sparkleshare/</param-value>\r
         </init-param>\r
     </filter>\r
     <filter-mapping>\r
index 5bd5b600eabd9daaa7c38861e28a0886e3ceeac8..f03734647e3bf4c5864c4c332c2c97fa96c14b1a 100644 (file)
@@ -56,7 +56,9 @@ public class Constants {
 \r
        public static final String RPC_PATH = "/rpc/";\r
        \r
-       public static final String PAGES= "/pages/";\r
+       public static final String PAGES = "/pages/";\r
+       \r
+       public static final String SPARKLESHARE_INVITE_PATH = "/sparkleshare/";\r
 \r
        public static final String BORDER = "***********************************************************";\r
 \r
diff --git a/src/main/java/com/gitblit/SparkleShareInviteServlet.java b/src/main/java/com/gitblit/SparkleShareInviteServlet.java
new file mode 100644 (file)
index 0000000..3cabb41
--- /dev/null
@@ -0,0 +1,210 @@
+/*\r
+ * Copyright 2013 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit;\r
+\r
+import java.io.IOException;\r
+import java.text.MessageFormat;\r
+import java.util.List;\r
+\r
+import javax.servlet.ServletException;\r
+import javax.servlet.http.HttpServlet;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import com.gitblit.Constants.AccessRestrictionType;\r
+import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.UserModel;\r
+import com.gitblit.utils.StringUtils;\r
+\r
+/**\r
+ * Handles requests for Sparkleshare Invites\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class SparkleShareInviteServlet extends HttpServlet {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       public SparkleShareInviteServlet() {\r
+               super();\r
+       }\r
+       \r
+       /**\r
+        * Returns an Sparkleshare invite url to this servlet for the repository.\r
+        * https://github.com/hbons/SparkleShare/wiki/Invites\r
+        * \r
+        * @param baseURL\r
+        * @param repository\r
+        * @param username\r
+        * @return an url\r
+        */\r
+       public static String asLink(String baseURL, String repository, String username) {\r
+               if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {\r
+                       baseURL = baseURL.substring(0, baseURL.length() - 1);\r
+               }\r
+               String url = baseURL + Constants.SPARKLESHARE_INVITE_PATH\r
+                               + ((StringUtils.isEmpty(username) ? "" : (username + "@")))\r
+                               + repository + ".xml";\r
+               url = url.replace("https://", "sparkleshare://");\r
+               url = url.replace("http://", "sparkleshare-unsafe://");\r
+               return url;\r
+       }\r
+       \r
+       @Override\r
+       protected void doPost(HttpServletRequest request, HttpServletResponse response)\r
+                       throws ServletException, java.io.IOException {\r
+               processRequest(request, response);\r
+       }\r
+\r
+       @Override\r
+       protected void doGet(HttpServletRequest request, HttpServletResponse response)\r
+                       throws ServletException, IOException {\r
+               processRequest(request, response);\r
+       }\r
+\r
+       protected void processRequest(javax.servlet.http.HttpServletRequest request,\r
+                       javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,\r
+                       java.io.IOException {           \r
+               \r
+               // extract repo name from request\r
+               String path = request.getPathInfo();\r
+               if (path != null && path.length() > 1) {\r
+                       if (path.charAt(0) == '/') {\r
+                               path = path.substring(1);\r
+                       }\r
+               }\r
+               // trim trailing .xml\r
+               if (path.endsWith(".xml")) {\r
+                       path = path.substring(0, path.length() - 4);\r
+               }\r
+               \r
+               String username = null;\r
+               int fetch = path.indexOf('@');\r
+               if (fetch > -1) {\r
+                       username = path.substring(0, fetch);\r
+                       path = path.substring(fetch + 1);\r
+               }\r
+               UserModel user;\r
+               if (StringUtils.isEmpty(username)) {\r
+                       user = GitBlit.self().authenticate(request);\r
+               } else {\r
+                       user = GitBlit.self().getUserModel(username);\r
+               }\r
+               if (user == null) {\r
+                       user = UserModel.ANONYMOUS;\r
+                       username = "";\r
+               }\r
+               \r
+               // ensure that the requested repository exists and is sparkleshared\r
+               RepositoryModel model = GitBlit.self().getRepositoryModel(path);\r
+               if (model == null) {\r
+                       response.setStatus(HttpServletResponse.SC_NOT_FOUND);\r
+                       response.getWriter().append(MessageFormat.format("Repository \"{0}\" not found!", path));\r
+                       return;\r
+               } else if (!model.isSparkleshared()) {\r
+                       response.setStatus(HttpServletResponse.SC_FORBIDDEN);\r
+                       response.getWriter().append(MessageFormat.format("Repository \"{0}\" is not sparkleshared!", path));\r
+                       return;\r
+               }\r
+               \r
+               if (GitBlit.getBoolean(Keys.git.enableGitServlet, true)\r
+                               || GitBlit.getInteger(Keys.git.daemonPort, 0) > 0) {\r
+                       // Gitblit as server\r
+                       // determine username for repository url\r
+                       if (model.accessRestriction.exceeds(AccessRestrictionType.NONE)) {\r
+                               if (!user.canRewindRef(model)) {\r
+                                       response.setStatus(HttpServletResponse.SC_FORBIDDEN);\r
+                                       response.getWriter().append(MessageFormat.format("\"{0}\" does not have RW+ permissions for {1}!", user.username, path));\r
+                                       return;\r
+                               }\r
+                       }\r
+                       \r
+                       if (model.accessRestriction.exceeds(AccessRestrictionType.NONE)) {\r
+                               username = user.username + "@";\r
+                       } else {\r
+                               username = "";\r
+                       }\r
+\r
+                       String serverPort = "";\r
+                       if (request.getScheme().equals("https")) {\r
+                               if (request.getServerPort() != 443) {\r
+                                       serverPort = ":" + request.getServerPort();\r
+                               }\r
+                       } else if (request.getScheme().equals("http")) {\r
+                               if (request.getServerPort() != 80) {\r
+                                       serverPort = ":" + request.getServerPort();\r
+                               }\r
+                       }\r
+\r
+                       // assume http/https serving\r
+                       String scheme = request.getScheme();\r
+                       String servletPath = Constants.GIT_PATH;\r
+\r
+                       // try to switch to git://, if git servlet disabled and repo has no restrictions\r
+                       if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true)\r
+                                       && (GitBlit.getInteger(Keys.git.daemonPort, 0) > 0)\r
+                                       && AccessRestrictionType.NONE == model.accessRestriction) {\r
+                               scheme = "git";\r
+                               servletPath = "/";\r
+                               serverPort = GitBlit.getString(Keys.git.daemonPort, "");\r
+                       }\r
+\r
+                       // construct Sparkleshare invite\r
+                       StringBuilder sb = new StringBuilder();         \r
+                       sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");\r
+                       sb.append("<sparkleshare><invite>\n");\r
+                       sb.append(MessageFormat.format("<address>{0}://{1}{2}{3}{4}</address>\n", scheme, username, request.getServerName(), serverPort, request.getContextPath()));\r
+                       sb.append(MessageFormat.format("<remote_path>{0}{1}</remote_path>\n", servletPath, model.name));\r
+                       if (GitBlit.getInteger(Keys.fanout.port, 0) > 0) {\r
+                               // Gitblit is running it's own fanout service for pubsub notifications\r
+                               sb.append(MessageFormat.format("<announcements_url>tcp://{0}:{1}</announcements_url>\n", request.getServerName(), GitBlit.getString(Keys.fanout.port, "")));\r
+                       }\r
+                       sb.append("</invite></sparkleshare>\n");\r
+\r
+                       // write invite to client\r
+                       response.setContentType("application/xml");\r
+                       response.setContentLength(sb.length());\r
+                       response.getWriter().append(sb.toString());\r
+               } else {\r
+                       // Gitblit as viewer, repository access handled externally so\r
+                       // assume RW+ permission\r
+                       List<String> others = GitBlit.getStrings(Keys.web.otherUrls);\r
+                       if (others.size() == 0) {\r
+                               return;\r
+                       }\r
+                       \r
+                       String address = MessageFormat.format(others.get(0), "", username);\r
+                       \r
+                       StringBuilder sb = new StringBuilder();         \r
+                       sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");\r
+                       sb.append("<sparkleshare><invite>\n");\r
+                       \r
+                       sb.append(MessageFormat.format("<address>{0}</address>\n", address));\r
+                       sb.append(MessageFormat.format("<remote_path>{0}</remote_path>\n", model.name));\r
+                       if (GitBlit.getInteger(Keys.fanout.port, 0) > 0) {\r
+                               // Gitblit is running it's own fanout service for pubsub notifications\r
+                               sb.append(MessageFormat.format("<announcements_url>tcp://{0}:{1}</announcements_url>\n", request.getServerName(), GitBlit.getString(Keys.fanout.port, "")));\r
+                       }\r
+                       sb.append("</invite></sparkleshare>\n");\r
+\r
+                       // write invite to client\r
+                       response.setContentType("application/xml");\r
+                       response.setContentLength(sb.length());\r
+                       response.getWriter().append(sb.toString());\r
+               }\r
+       }\r
+}\r
index aa5a415a2c98142f0172b1bd5275e38df8295e62..049cc4089de5853195083ea274bd63583e6a17e5 100644 (file)
@@ -445,10 +445,11 @@ gb.isSparkleshared = repository is Sparkleshared
 gb.owners = owners\r
 gb.sessionEnded = Session has been closed\r
 gb.closeBrowser = Please close the browser to properly end the session.\r
-gb.doesNotExistInTree = {0} does not exist in tree {1}\r
+gb.doesNotExistInTree = {0} does not exist in tree {1}
 gb.enableIncrementalPushTags = enable incremental push tags\r
 gb.useIncrementalPushTagsDescription = on push, automatically tag each branch tip with an incremental revision number\r
 gb.incrementalPushTagMessage = Auto-tagged [{0}] branch on push\r
 gb.externalPermissions = {0} access permissions for {1} are externally maintained\r
 gb.viewAccess = You do not have Gitblit read or write access\r
-gb.yourProtocolPermissionIs = Your {0} access permission for {1} is {2}
\ No newline at end of file
+gb.yourProtocolPermissionIs = Your {0} access permission for {1} is {2}\r
+gb.sparkleshareInvite = SparkleShare invite
\ No newline at end of file
index b2dcce3f7a85b77d2cda5ae3a7a06d1e4c9d409c..b3b0767bbf8b880f47182252c8154f92d2aae9be 100644 (file)
@@ -57,6 +57,7 @@ import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.Constants.FederationStrategy;\r
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
+import com.gitblit.SparkleShareInviteServlet;\r
 import com.gitblit.models.ProjectModel;\r
 import com.gitblit.models.RepositoryModel;\r
 import com.gitblit.models.TeamModel;\r
@@ -311,7 +312,33 @@ public abstract class BasePage extends SessionPage {
                        return new Label(wicketId).setVisible(false);\r
                }\r
        }\r
-       \r
+\r
+       protected String getSparkleShareInviteUrl(RepositoryModel repository) {\r
+               if (repository.isBare && repository.isSparkleshared()) {\r
+                       UserModel user = GitBlitWebSession.get().getUser();\r
+                       if (user == null) {\r
+                               user = UserModel.ANONYMOUS;\r
+                       }\r
+                       String username = null;\r
+                       if (UserModel.ANONYMOUS != user) {\r
+                               username = user.username;\r
+                       }\r
+                       if (GitBlit.getBoolean(Keys.git.enableGitServlet, true) || (GitBlit.getInteger(Keys.git.daemonPort, 0) > 0)) {\r
+                               // Gitblit as server\r
+                               // ensure user can rewind\r
+                               if (user.canRewindRef(repository)) {\r
+                                       String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());\r
+                                       return SparkleShareInviteServlet.asLink(baseURL, repository.name, username);\r
+                               }\r
+                       } else {\r
+                               // Gitblit as viewer, assume RW+ permission\r
+                               String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest());\r
+                               return SparkleShareInviteServlet.asLink(baseURL, repository.name, username);\r
+                       }\r
+               }\r
+               return null;\r
+       }\r
+\r
        protected List<ProjectModel> getProjectModels() {\r
                final UserModel user = GitBlitWebSession.get().getUser();\r
                List<ProjectModel> projects = GitBlit.self().getProjectModels(user, true);\r
index a751d1f0d146925e02777da3a1c52fa15e270be4..c9bce4017f483f04eb5c37c14f11d5287acda80b 100644 (file)
@@ -26,6 +26,7 @@
                                        <div wicket:id="otherUrls" >\r
                                                <div wicket:id="otherUrl" style="padding-top:10px"></div>\r
                                        </div>\r
+                                       <div wicket:id="repositorySparkleShareInviteUrl">[repository sparkleshare invite url]</div>\r
                                    </td>\r
                                </tr>\r
                        </table>\r
index 863974b345fe183d2b19c5383c028711ff69f740..f092a387e85c941b3c205ea65522d13307e4606c 100644 (file)
@@ -60,6 +60,7 @@ import com.gitblit.wicket.panels.BranchesPanel;
 import com.gitblit.wicket.panels.DetailedRepositoryUrlPanel;\r
 import com.gitblit.wicket.panels.LinkPanel;\r
 import com.gitblit.wicket.panels.LogPanel;\r
+import com.gitblit.wicket.panels.SparkleShareInvitePanel;\r
 import com.gitblit.wicket.panels.TagsPanel;\r
 \r
 public class SummaryPage extends RepositoryPage {\r
@@ -167,6 +168,15 @@ public class SummaryPage extends RepositoryPage {
                }\r
                add(gitDaemonUrlPanel);\r
                \r
+               String sparkleshareUrl = getSparkleShareInviteUrl(model);\r
+               if (StringUtils.isEmpty(sparkleshareUrl)) {\r
+                       add(new Label("repositorySparkleShareInviteUrl").setVisible(false));\r
+               } else {\r
+                       Component sparklesharePanel = new SparkleShareInvitePanel("repositorySparkleShareInviteUrl", getLocalizer(), this, sparkleshareUrl, accessPermission);\r
+                       WicketUtils.setCssStyle(sparklesharePanel, "padding-top: 10px;");\r
+                       add(sparklesharePanel);\r
+               }\r
+\r
                ListDataProvider<String> urls = new ListDataProvider<String>(repositoryUrls);\r
                DataView<String> otherUrlsView = new DataView<String>("otherUrls", urls) {\r
                        private static final long serialVersionUID = 1L;\r
diff --git a/src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.html b/src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.html
new file mode 100644 (file)
index 0000000..483050c
--- /dev/null
@@ -0,0 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml"  \r
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  \r
+      xml:lang="en"  \r
+      lang="en"> \r
+\r
+<wicket:panel>\r
+       <span class="repositoryUrlContainer">\r
+               <span class="repositoryUrlEndCap">\r
+                       <img wicket:id="sparkleshareIcon"></img>\r
+               </span>\r
+               <span class="repositoryUrl">\r
+                       <a wicket:id="inviteUrl"><wicket:message key="gb.sparkleshareInvite"></wicket:message></a>\r
+               </span>\r
+               <span class="hidden-phone hidden-tablet repositoryUrlEndCap" wicket:id="accessPermission">[access permission]</span>\r
+       </span>\r
+</wicket:panel>\r
+</html>
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.java b/src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.java
new file mode 100644 (file)
index 0000000..5d7aa58
--- /dev/null
@@ -0,0 +1,52 @@
+/*\r
+ * Copyright 2013 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.wicket.panels;\r
+\r
+import org.apache.wicket.Component;\r
+import org.apache.wicket.Localizer;\r
+import org.apache.wicket.markup.html.basic.Label;\r
+import org.apache.wicket.markup.html.image.ContextImage;\r
+import org.apache.wicket.markup.html.link.ExternalLink;\r
+\r
+import com.gitblit.Constants.AccessPermission;\r
+import com.gitblit.wicket.WicketUtils;\r
+\r
+public class SparkleShareInvitePanel extends BasePanel {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       public SparkleShareInvitePanel(String wicketId, Localizer localizer, Component parent, String url, AccessPermission ap) {\r
+               super(wicketId);\r
+               ContextImage star = WicketUtils.newImage("sparkleshareIcon", "star_16x16.png");\r
+               add(star);\r
+               add(new ExternalLink("inviteUrl", url));\r
+               String note = localizer.getString("gb.externalAccess", parent);\r
+               String permission = "";\r
+               if (ap != null) {\r
+                       permission = ap.toString();\r
+                       if (ap.atLeast(AccessPermission.PUSH)) {\r
+                               note = localizer.getString("gb.readWriteAccess", parent);\r
+                       } else if (ap.atLeast(AccessPermission.CLONE)) {\r
+                               note = localizer.getString("gb.readOnlyAccess", parent);\r
+                       } else {\r
+                               note = localizer.getString("gb.viewAccess", parent);\r
+                       }\r
+               }\r
+               Label label = new Label("accessPermission", permission);\r
+               WicketUtils.setHtmlTooltip(label, note);\r
+               add(label);\r
+       }\r
+}\r