diff options
Diffstat (limited to 'src/main/java')
9 files changed, 342 insertions, 5 deletions
diff --git a/src/main/java/WEB-INF/web.xml b/src/main/java/WEB-INF/web.xml index 5ee5ed23..573305c4 100644 --- a/src/main/java/WEB-INF/web.xml +++ b/src/main/java/WEB-INF/web.xml @@ -53,7 +53,21 @@ <servlet-name>GitServlet</servlet-name>
<url-pattern>/git/*</url-pattern>
</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:
@@ -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>
diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index 5bd5b600..f0373464 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -56,7 +56,9 @@ public class Constants { public static final String RPC_PATH = "/rpc/";
- public static final String PAGES= "/pages/";
+ public static final String PAGES = "/pages/";
+
+ public static final String SPARKLESHARE_INVITE_PATH = "/sparkleshare/";
public static final String BORDER = "***********************************************************";
diff --git a/src/main/java/com/gitblit/SparkleShareInviteServlet.java b/src/main/java/com/gitblit/SparkleShareInviteServlet.java new file mode 100644 index 00000000..3cabb411 --- /dev/null +++ b/src/main/java/com/gitblit/SparkleShareInviteServlet.java @@ -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());
+ }
+ }
+}
diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index aa5a415a..049cc408 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -445,10 +445,11 @@ gb.isSparkleshared = repository is Sparkleshared gb.owners = owners
gb.sessionEnded = Session has been closed
gb.closeBrowser = Please close the browser to properly end the session.
-gb.doesNotExistInTree = {0} does not exist in tree {1}
+gb.doesNotExistInTree = {0} does not exist in tree {1} gb.enableIncrementalPushTags = enable incremental push tags
gb.useIncrementalPushTagsDescription = on push, automatically tag each branch tip with an incremental revision number
gb.incrementalPushTagMessage = Auto-tagged [{0}] branch on push
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}
\ No newline at end of file +gb.yourProtocolPermissionIs = Your {0} access permission for {1} is {2}
+gb.sparkleshareInvite = SparkleShare invite
\ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/pages/BasePage.java b/src/main/java/com/gitblit/wicket/pages/BasePage.java index b2dcce3f..b3b0767b 100644 --- a/src/main/java/com/gitblit/wicket/pages/BasePage.java +++ b/src/main/java/com/gitblit/wicket/pages/BasePage.java @@ -57,6 +57,7 @@ import com.gitblit.Constants.AuthorizationControl; 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;
@@ -311,7 +312,33 @@ public abstract class BasePage extends SessionPage { return new Label(wicketId).setVisible(false);
}
}
-
+
+ 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);
diff --git a/src/main/java/com/gitblit/wicket/pages/SummaryPage.html b/src/main/java/com/gitblit/wicket/pages/SummaryPage.html index a751d1f0..c9bce401 100644 --- a/src/main/java/com/gitblit/wicket/pages/SummaryPage.html +++ b/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>
diff --git a/src/main/java/com/gitblit/wicket/pages/SummaryPage.java b/src/main/java/com/gitblit/wicket/pages/SummaryPage.java index 863974b3..f092a387 100644 --- a/src/main/java/com/gitblit/wicket/pages/SummaryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/SummaryPage.java @@ -60,6 +60,7 @@ import com.gitblit.wicket.panels.BranchesPanel; 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 @@ public class SummaryPage extends RepositoryPage { }
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;
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 index 00000000..483050c5 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.html @@ -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>
\ 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 index 00000000..5d7aa589 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/SparkleShareInvitePanel.java @@ -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);
+ }
+}
|