src/main/java/WEB-INF/web.xml | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/Constants.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/SparkleShareInviteServlet.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/wicket/GitBlitWebApp.properties | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/wicket/pages/BasePage.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/wicket/pages/SummaryPage.html | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/wicket/pages/SummaryPage.java | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.html | ●●●●● patch | view | raw | blame | history | |
src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.java | ●●●●● patch | view | raw | blame | history |
src/main/java/WEB-INF/web.xml
@@ -55,6 +55,20 @@ </servlet-mapping> <!-- SparkleShare Invite Servlet <url-pattern> MUST match: * com.gitblit.Constants.SPARKLESHARE_INVITE_PATH * Wicket Filter ignorePaths parameter --> <servlet> <servlet-name>SparkleShareInviteServlet</servlet-name> <servlet-class>com.gitblit.SparkleShareInviteServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SparkleShareInviteServlet</servlet-name> <url-pattern>/sparkleshare/*</url-pattern> </servlet-mapping> <!-- Syndication Servlet <url-pattern> MUST match: * SyndicationFilter @@ -244,6 +258,8 @@ * GitFilter <url-pattern> * GitServlet <url-pattern> * com.gitblit.Constants.GIT_PATH * SparkleshareInviteServlet <url-pattern> * com.gitblit.Constants.SPARKLESHARE_INVITE_PATH * Zipfilter <url-pattern> * ZipServlet <url-pattern> * com.gitblit.Constants.ZIP_PATH @@ -253,7 +269,7 @@ * PagesFilter <url-pattern> * PagesServlet <url-pattern> * com.gitblit.Constants.PAGES_PATH --> <param-value>git/,feed/,zip/,federation/,rpc/,pages/,robots.txt</param-value> <param-value>git/,feed/,zip/,federation/,rpc/,pages/,robots.txt,sparkleshare/</param-value> </init-param> </filter> <filter-mapping> src/main/java/com/gitblit/Constants.java
@@ -57,6 +57,8 @@ public static final String RPC_PATH = "/rpc/"; public static final String PAGES= "/pages/"; public static final String SPARKLESHARE_INVITE_PATH = "/sparkleshare/"; public static final String BORDER = "***********************************************************"; src/main/java/com/gitblit/SparkleShareInviteServlet.java
New file @@ -0,0 +1,210 @@ /* * Copyright 2013 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; import java.io.IOException; import java.text.MessageFormat; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.gitblit.Constants.AccessRestrictionType; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.utils.StringUtils; /** * Handles requests for Sparkleshare Invites * * @author James Moger * */ public class SparkleShareInviteServlet extends HttpServlet { private static final long serialVersionUID = 1L; public SparkleShareInviteServlet() { super(); } /** * Returns an Sparkleshare invite url to this servlet for the repository. * https://github.com/hbons/SparkleShare/wiki/Invites * * @param baseURL * @param repository * @param username * @return an url */ public static String asLink(String baseURL, String repository, String username) { if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') { baseURL = baseURL.substring(0, baseURL.length() - 1); } String url = baseURL + Constants.SPARKLESHARE_INVITE_PATH + ((StringUtils.isEmpty(username) ? "" : (username + "@"))) + repository + ".xml"; url = url.replace("https://", "sparkleshare://"); url = url.replace("http://", "sparkleshare-unsafe://"); return url; } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { processRequest(request, response); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } protected void processRequest(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException { // extract repo name from request String path = request.getPathInfo(); if (path != null && path.length() > 1) { if (path.charAt(0) == '/') { path = path.substring(1); } } // trim trailing .xml if (path.endsWith(".xml")) { path = path.substring(0, path.length() - 4); } String username = null; int fetch = path.indexOf('@'); if (fetch > -1) { username = path.substring(0, fetch); path = path.substring(fetch + 1); } UserModel user; if (StringUtils.isEmpty(username)) { user = GitBlit.self().authenticate(request); } else { user = GitBlit.self().getUserModel(username); } if (user == null) { user = UserModel.ANONYMOUS; username = ""; } // ensure that the requested repository exists and is sparkleshared RepositoryModel model = GitBlit.self().getRepositoryModel(path); if (model == null) { response.setStatus(HttpServletResponse.SC_NOT_FOUND); response.getWriter().append(MessageFormat.format("Repository \"{0}\" not found!", path)); return; } else if (!model.isSparkleshared()) { response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.getWriter().append(MessageFormat.format("Repository \"{0}\" is not sparkleshared!", path)); return; } if (GitBlit.getBoolean(Keys.git.enableGitServlet, true) || GitBlit.getInteger(Keys.git.daemonPort, 0) > 0) { // Gitblit as server // determine username for repository url if (model.accessRestriction.exceeds(AccessRestrictionType.NONE)) { if (!user.canRewindRef(model)) { response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.getWriter().append(MessageFormat.format("\"{0}\" does not have RW+ permissions for {1}!", user.username, path)); return; } } if (model.accessRestriction.exceeds(AccessRestrictionType.NONE)) { username = user.username + "@"; } else { username = ""; } String serverPort = ""; if (request.getScheme().equals("https")) { if (request.getServerPort() != 443) { serverPort = ":" + request.getServerPort(); } } else if (request.getScheme().equals("http")) { if (request.getServerPort() != 80) { serverPort = ":" + request.getServerPort(); } } // assume http/https serving String scheme = request.getScheme(); String servletPath = Constants.GIT_PATH; // try to switch to git://, if git servlet disabled and repo has no restrictions if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true) && (GitBlit.getInteger(Keys.git.daemonPort, 0) > 0) && AccessRestrictionType.NONE == model.accessRestriction) { scheme = "git"; servletPath = "/"; serverPort = GitBlit.getString(Keys.git.daemonPort, ""); } // construct Sparkleshare invite StringBuilder sb = new StringBuilder(); sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); sb.append("<sparkleshare><invite>\n"); sb.append(MessageFormat.format("<address>{0}://{1}{2}{3}{4}</address>\n", scheme, username, request.getServerName(), serverPort, request.getContextPath())); sb.append(MessageFormat.format("<remote_path>{0}{1}</remote_path>\n", servletPath, model.name)); if (GitBlit.getInteger(Keys.fanout.port, 0) > 0) { // Gitblit is running it's own fanout service for pubsub notifications sb.append(MessageFormat.format("<announcements_url>tcp://{0}:{1}</announcements_url>\n", request.getServerName(), GitBlit.getString(Keys.fanout.port, ""))); } sb.append("</invite></sparkleshare>\n"); // write invite to client response.setContentType("application/xml"); response.setContentLength(sb.length()); response.getWriter().append(sb.toString()); } else { // Gitblit as viewer, repository access handled externally so // assume RW+ permission List<String> others = GitBlit.getStrings(Keys.web.otherUrls); if (others.size() == 0) { return; } String address = MessageFormat.format(others.get(0), "", username); StringBuilder sb = new StringBuilder(); sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); sb.append("<sparkleshare><invite>\n"); sb.append(MessageFormat.format("<address>{0}</address>\n", address)); sb.append(MessageFormat.format("<remote_path>{0}</remote_path>\n", model.name)); if (GitBlit.getInteger(Keys.fanout.port, 0) > 0) { // Gitblit is running it's own fanout service for pubsub notifications sb.append(MessageFormat.format("<announcements_url>tcp://{0}:{1}</announcements_url>\n", request.getServerName(), GitBlit.getString(Keys.fanout.port, ""))); } sb.append("</invite></sparkleshare>\n"); // write invite to client response.setContentType("application/xml"); response.setContentLength(sb.length()); response.getWriter().append(sb.toString()); } } } src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
@@ -452,3 +452,4 @@ gb.externalPermissions = {0} access permissions for {1} are externally maintained gb.viewAccess = You do not have Gitblit read or write access gb.yourProtocolPermissionIs = Your {0} access permission for {1} is {2} gb.sparkleshareInvite = SparkleShare invite src/main/java/com/gitblit/wicket/pages/BasePage.java
@@ -57,6 +57,7 @@ import com.gitblit.Constants.FederationStrategy; import com.gitblit.GitBlit; import com.gitblit.Keys; import com.gitblit.SparkleShareInviteServlet; import com.gitblit.models.ProjectModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.TeamModel; @@ -312,6 +313,32 @@ } } protected String getSparkleShareInviteUrl(RepositoryModel repository) { if (repository.isBare && repository.isSparkleshared()) { UserModel user = GitBlitWebSession.get().getUser(); if (user == null) { user = UserModel.ANONYMOUS; } String username = null; if (UserModel.ANONYMOUS != user) { username = user.username; } if (GitBlit.getBoolean(Keys.git.enableGitServlet, true) || (GitBlit.getInteger(Keys.git.daemonPort, 0) > 0)) { // Gitblit as server // ensure user can rewind if (user.canRewindRef(repository)) { String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest()); return SparkleShareInviteServlet.asLink(baseURL, repository.name, username); } } else { // Gitblit as viewer, assume RW+ permission String baseURL = WicketUtils.getGitblitURL(RequestCycle.get().getRequest()); return SparkleShareInviteServlet.asLink(baseURL, repository.name, username); } } return null; } protected List<ProjectModel> getProjectModels() { final UserModel user = GitBlitWebSession.get().getUser(); List<ProjectModel> projects = GitBlit.self().getProjectModels(user, true); src/main/java/com/gitblit/wicket/pages/SummaryPage.html
@@ -26,6 +26,7 @@ <div wicket:id="otherUrls" > <div wicket:id="otherUrl" style="padding-top:10px"></div> </div> <div wicket:id="repositorySparkleShareInviteUrl">[repository sparkleshare invite url]</div> </td> </tr> </table> src/main/java/com/gitblit/wicket/pages/SummaryPage.java
@@ -60,6 +60,7 @@ import com.gitblit.wicket.panels.DetailedRepositoryUrlPanel; import com.gitblit.wicket.panels.LinkPanel; import com.gitblit.wicket.panels.LogPanel; import com.gitblit.wicket.panels.SparkleShareInvitePanel; import com.gitblit.wicket.panels.TagsPanel; public class SummaryPage extends RepositoryPage { @@ -167,6 +168,15 @@ } add(gitDaemonUrlPanel); String sparkleshareUrl = getSparkleShareInviteUrl(model); if (StringUtils.isEmpty(sparkleshareUrl)) { add(new Label("repositorySparkleShareInviteUrl").setVisible(false)); } else { Component sparklesharePanel = new SparkleShareInvitePanel("repositorySparkleShareInviteUrl", getLocalizer(), this, sparkleshareUrl, accessPermission); WicketUtils.setCssStyle(sparklesharePanel, "padding-top: 10px;"); add(sparklesharePanel); } ListDataProvider<String> urls = new ListDataProvider<String>(repositoryUrls); DataView<String> otherUrlsView = new DataView<String>("otherUrls", urls) { private static final long serialVersionUID = 1L; src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.html
New file @@ -0,0 +1,18 @@ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" xml:lang="en" lang="en"> <wicket:panel> <span class="repositoryUrlContainer"> <span class="repositoryUrlEndCap"> <img wicket:id="sparkleshareIcon"></img> </span> <span class="repositoryUrl"> <a wicket:id="inviteUrl"><wicket:message key="gb.sparkleshareInvite"></wicket:message></a> </span> <span class="hidden-phone hidden-tablet repositoryUrlEndCap" wicket:id="accessPermission">[access permission]</span> </span> </wicket:panel> </html> src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.java
New file @@ -0,0 +1,52 @@ /* * Copyright 2013 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.wicket.panels; import org.apache.wicket.Component; import org.apache.wicket.Localizer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.image.ContextImage; import org.apache.wicket.markup.html.link.ExternalLink; import com.gitblit.Constants.AccessPermission; import com.gitblit.wicket.WicketUtils; public class SparkleShareInvitePanel extends BasePanel { private static final long serialVersionUID = 1L; public SparkleShareInvitePanel(String wicketId, Localizer localizer, Component parent, String url, AccessPermission ap) { super(wicketId); ContextImage star = WicketUtils.newImage("sparkleshareIcon", "star_16x16.png"); add(star); add(new ExternalLink("inviteUrl", url)); String note = localizer.getString("gb.externalAccess", parent); String permission = ""; if (ap != null) { permission = ap.toString(); if (ap.atLeast(AccessPermission.PUSH)) { note = localizer.getString("gb.readWriteAccess", parent); } else if (ap.atLeast(AccessPermission.CLONE)) { note = localizer.getString("gb.readOnlyAccess", parent); } else { note = localizer.getString("gb.viewAccess", parent); } } Label label = new Label("accessPermission", permission); WicketUtils.setHtmlTooltip(label, note); add(label); } }