From 264ba908941414ea5e750524b2472f7ad0670563 Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Thu, 02 May 2013 21:37:58 -0400 Subject: [PATCH] Improved the repository url panel and show git daemon url, appropriately --- src/main/java/com/gitblit/wicket/pages/BasePage.java | 42 ++++++++ src/main/java/com/gitblit/wicket/pages/ProjectPage.html | 2 src/main/java/com/gitblit/wicket/pages/SummaryPage.java | 34 +++++- src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.html | 2 src/main/resources/gitblit.css | 24 ++++ src/main/java/com/gitblit/wicket/panels/DetailedRepositoryUrlPanel.java | 115 +++++++++++++++++++++++ src/main/java/com/gitblit/wicket/GitBlitWebApp.properties | 7 + src/main/java/com/gitblit/wicket/panels/DetailedRepositoryUrlPanel.html | 42 ++++++++ src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java | 12 + src/main/java/com/gitblit/wicket/pages/SummaryPage.html | 10 + src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java | 6 11 files changed, 279 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties index f2d4a36..aa5a415 100644 --- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties @@ -445,7 +445,10 @@ 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 \ No newline at end of file +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 diff --git a/src/main/java/com/gitblit/wicket/pages/BasePage.java b/src/main/java/com/gitblit/wicket/pages/BasePage.java index bb7d8c9..b2dcce3 100644 --- a/src/main/java/com/gitblit/wicket/pages/BasePage.java +++ b/src/main/java/com/gitblit/wicket/pages/BasePage.java @@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletRequest; import org.apache.wicket.Application; +import org.apache.wicket.Component; import org.apache.wicket.MarkupContainer; import org.apache.wicket.PageParameters; import org.apache.wicket.RedirectToUrlException; @@ -44,6 +45,7 @@ import org.apache.wicket.markup.html.panel.FeedbackPanel; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.protocol.http.RequestUtils; +import org.apache.wicket.protocol.http.WebRequest; import org.apache.wicket.protocol.http.servlet.ServletWebRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,6 +65,7 @@ import com.gitblit.utils.TimeUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; +import com.gitblit.wicket.panels.DetailedRepositoryUrlPanel; import com.gitblit.wicket.panels.LinkPanel; public abstract class BasePage extends SessionPage { @@ -270,6 +273,45 @@ return sb.toString(); } + protected Component createGitDaemonUrlPanel(String wicketId, UserModel user, RepositoryModel repository) { + int gitDaemonPort = GitBlit.getInteger(Keys.git.daemonPort, 0); + if (gitDaemonPort > 0 && user.canClone(repository)) { + String servername = ((WebRequest) getRequest()).getHttpServletRequest().getServerName(); + String gitDaemonUrl; + if (gitDaemonPort == 9418) { + // standard port + gitDaemonUrl = MessageFormat.format("git://{0}/{1}", servername, repository.name); + } else { + // non-standard port + gitDaemonUrl = MessageFormat.format("git://{0}:{1,number,0}/{2}", servername, gitDaemonPort, repository.name); + } + + AccessPermission gitDaemonPermission = user.getRepositoryPermission(repository).permission;; + if (gitDaemonPermission.atLeast(AccessPermission.CLONE)) { + if (repository.accessRestriction.atLeast(AccessRestrictionType.CLONE)) { + // can not authenticate clone via anonymous git protocol + gitDaemonPermission = AccessPermission.NONE; + } else if (repository.accessRestriction.atLeast(AccessRestrictionType.PUSH)) { + // can not authenticate push via anonymous git protocol + gitDaemonPermission = AccessPermission.CLONE; + } else { + // normal user permission + } + } + + if (AccessPermission.NONE.equals(gitDaemonPermission)) { + // repository prohibits all anonymous access + return new Label(wicketId).setVisible(false); + } else { + // repository allows some form of anonymous access + return new DetailedRepositoryUrlPanel(wicketId, getLocalizer(), this, repository.name, gitDaemonUrl, gitDaemonPermission); + } + } else { + // git daemon is not running + return new Label(wicketId).setVisible(false); + } + } + 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/EmptyRepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java index cccf8a6..a2264c4 100644 --- a/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/EmptyRepositoryPage.java @@ -22,6 +22,7 @@ import org.apache.wicket.PageParameters; import org.apache.wicket.markup.html.basic.Label; +import com.gitblit.Constants.AccessPermission; import com.gitblit.GitBlit; import com.gitblit.Keys; import com.gitblit.models.RepositoryModel; @@ -30,7 +31,7 @@ import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.GitblitRedirectException; import com.gitblit.wicket.WicketUtils; -import com.gitblit.wicket.panels.RepositoryUrlPanel; +import com.gitblit.wicket.panels.DetailedRepositoryUrlPanel; public class EmptyRepositoryPage extends RootPage { @@ -59,11 +60,16 @@ repositoryUrls.add(getRepositoryUrl(repository)); } UserModel user = GitBlitWebSession.get().getUser(); - repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(repositoryName, user == null ? "" : user.username)); + if (user == null) { + user = UserModel.ANONYMOUS; + } + repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(repositoryName, UserModel.ANONYMOUS.equals(user) ? "" : user.username)); String primaryUrl = ArrayUtils.isEmpty(repositoryUrls) ? "" : repositoryUrls.get(0); + AccessPermission accessPermission = user.getRepositoryPermission(repository).permission; + add(new Label("repository", repositoryName)); - add(new RepositoryUrlPanel("pushurl", primaryUrl)); + add(new DetailedRepositoryUrlPanel("pushurl", getLocalizer(), this, repository.name, primaryUrl, accessPermission)); add(new Label("cloneSyntax", MessageFormat.format("git clone {0}", repositoryUrls.get(0)))); add(new Label("remoteSyntax", MessageFormat.format("git remote add gitblit {0}\ngit push gitblit master", primaryUrl))); } diff --git a/src/main/java/com/gitblit/wicket/pages/ProjectPage.html b/src/main/java/com/gitblit/wicket/pages/ProjectPage.html index 3e73ba5..6c16195 100644 --- a/src/main/java/com/gitblit/wicket/pages/ProjectPage.html +++ b/src/main/java/com/gitblit/wicket/pages/ProjectPage.html @@ -38,7 +38,7 @@ </div> </div> <div class="row"> - <div class="span6" style="border-bottom:1px solid #eee;" wicket:id="repositoryList"> + <div class="span6" wicket:id="repositoryList"> <span wicket:id="repository"></span> </div> </div> diff --git a/src/main/java/com/gitblit/wicket/pages/SummaryPage.html b/src/main/java/com/gitblit/wicket/pages/SummaryPage.html index 3e85df9..a751d1f 100644 --- a/src/main/java/com/gitblit/wicket/pages/SummaryPage.html +++ b/src/main/java/com/gitblit/wicket/pages/SummaryPage.html @@ -19,7 +19,15 @@ <tr><th><wicket:message key="gb.owners">[owner]</wicket:message></th><td><span wicket:id="repositoryOwners"><span wicket:id="owner"></span><span wicket:id="comma"></span></span></td></tr> <tr><th><wicket:message key="gb.lastChange">[last change]</wicket:message></th><td><span wicket:id="repositoryLastChange">[repository last change]</span></td></tr> <tr><th><wicket:message key="gb.stats">[stats]</wicket:message></th><td><span wicket:id="branchStats">[branch stats]</span> <span class="link"><a wicket:id="metrics"><wicket:message key="gb.metrics">[metrics]</wicket:message></a></span></td></tr> - <tr><th style="vertical-align:top;"><wicket:message key="gb.repositoryUrl">[URL]</wicket:message> <img style="vertical-align: top;padding-left:3px;" wicket:id="accessRestrictionIcon" /></th><td><span wicket:id="repositoryCloneUrl">[repository clone url]</span><div wicket:id="otherUrls"></div></td></tr> + <tr><th style="vertical-align:top;padding-top:4px;"><wicket:message key="gb.repositoryUrl">[URL]</wicket:message> <img style="vertical-align: top;padding-left:3px;" wicket:id="accessRestrictionIcon" /></th> + <td style="padding-top:4px;"> + <div wicket:id="repositoryPrimaryUrl">[repository primary url]</div> + <div wicket:id="repositoryGitDaemonUrl">[repository git daemon url]</div> + <div wicket:id="otherUrls" > + <div wicket:id="otherUrl" style="padding-top:10px"></div> + </div> + </td> + </tr> </table> </div> </div> diff --git a/src/main/java/com/gitblit/wicket/pages/SummaryPage.java b/src/main/java/com/gitblit/wicket/pages/SummaryPage.java index d68add0..863974b 100644 --- a/src/main/java/com/gitblit/wicket/pages/SummaryPage.java +++ b/src/main/java/com/gitblit/wicket/pages/SummaryPage.java @@ -42,6 +42,7 @@ import org.wicketstuff.googlecharts.MarkerType; import org.wicketstuff.googlecharts.ShapeMarker; +import com.gitblit.Constants.AccessPermission; import com.gitblit.Constants.AccessRestrictionType; import com.gitblit.GitBlit; import com.gitblit.Keys; @@ -56,9 +57,9 @@ import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; 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.RepositoryUrlPanel; import com.gitblit.wicket.panels.TagsPanel; public class SummaryPage extends RepositoryPage { @@ -73,8 +74,11 @@ int numberRefs = GitBlit.getInteger(Keys.web.summaryRefsCount, 5); Repository r = getRepository(); - RepositoryModel model = getRepositoryModel(); + final RepositoryModel model = getRepositoryModel(); UserModel user = GitBlitWebSession.get().getUser(); + if (user == null) { + user = UserModel.ANONYMOUS; + } List<Metric> metrics = null; Metric metricsTotal = null; @@ -124,7 +128,9 @@ List<String> repositoryUrls = new ArrayList<String>(); - if (GitBlit.getBoolean(Keys.git.enableGitServlet, true)) { + AccessPermission accessPermission = null; + if (GitBlit.getBoolean(Keys.git.enableGitServlet, true)) { + accessPermission = user.getRepositoryPermission(model).permission; AccessRestrictionType accessRestriction = getRepositoryModel().accessRestriction; switch (accessRestriction) { case NONE: @@ -150,13 +156,27 @@ } else { add(WicketUtils.newClearPixel("accessRestrictionIcon").setVisible(false)); } - repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(repositoryName, user == null ? "" : user.username)); + repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(repositoryName, UserModel.ANONYMOUS.equals(user) ? "" : user.username)); String primaryUrl = ArrayUtils.isEmpty(repositoryUrls) ? "" : repositoryUrls.remove(0); - add(new RepositoryUrlPanel("repositoryCloneUrl", primaryUrl)); + add(new DetailedRepositoryUrlPanel("repositoryPrimaryUrl", getLocalizer(), this, model.name, primaryUrl, accessPermission)); - add(new Label("otherUrls", StringUtils.flattenStrings(repositoryUrls, "<br/>")) - .setEscapeModelStrings(false)); + Component gitDaemonUrlPanel = createGitDaemonUrlPanel("repositoryGitDaemonUrl", user, model); + if (!StringUtils.isEmpty(primaryUrl) && gitDaemonUrlPanel instanceof DetailedRepositoryUrlPanel) { + WicketUtils.setCssStyle(gitDaemonUrlPanel, "padding-top: 10px"); + } + add(gitDaemonUrlPanel); + + ListDataProvider<String> urls = new ListDataProvider<String>(repositoryUrls); + DataView<String> otherUrlsView = new DataView<String>("otherUrls", urls) { + private static final long serialVersionUID = 1L; + + public void populateItem(final Item<String> item) { + final String url = item.getModelObject(); + item.add(new DetailedRepositoryUrlPanel("otherUrl", getLocalizer(), this, model.name, url)); + } + }; + add(otherUrlsView); add(new LogPanel("commitsPanel", repositoryName, getRepositoryModel().HEAD, r, numberCommits, 0, getRepositoryModel().showRemoteBranches)); add(new TagsPanel("tagsPanel", repositoryName, r, numberRefs).hideIfEmpty()); diff --git a/src/main/java/com/gitblit/wicket/panels/DetailedRepositoryUrlPanel.html b/src/main/java/com/gitblit/wicket/panels/DetailedRepositoryUrlPanel.html new file mode 100644 index 0000000..e671435 --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/DetailedRepositoryUrlPanel.html @@ -0,0 +1,42 @@ +<!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 wicket:id="urlPanel"></span> + + <!-- Repository url panel --> + <wicket:fragment wicket:id="repositoryUrlPanel"> + <span class="repositoryUrlContainer"> + <span wicket:id="repositoryProtocol" class="repositoryUrlEndCap">[protocol]</span> + <span class="repositoryUrl"> + <span wicket:id="repositoryUrl">[repository url]</span> + <span class="hidden-phone hidden-tablet" wicket:id="copyFunction"></span> + </span> + <span class="hidden-phone hidden-tablet repositoryUrlEndCap" wicket:id="repositoryUrlPermission">[repository url permission]</span> + </span> + </wicket:fragment> + + <!-- Plain JavaScript manual copy & paste --> + <wicket:fragment wicket:id="jsPanel"> + <span style="vertical-align:baseline;"> + <img wicket:id="copyIcon" wicket:message="title:gb.copyToClipboard"></img> + </span> + </wicket:fragment> + + <!-- flash-based button-press copy & paste --> + <wicket:fragment wicket:id="clippyPanel"> + <object wicket:message="title:gb.copyToClipboard" style="vertical-align:middle;" + wicket:id="clippy" + width="14" + height="14" + bgcolor="#ffffff" + quality="high" + wmode="transparent" + scale="noscale" + allowScriptAccess="always"></object> + </wicket:fragment> +</wicket:panel> +</html> \ No newline at end of file diff --git a/src/main/java/com/gitblit/wicket/panels/DetailedRepositoryUrlPanel.java b/src/main/java/com/gitblit/wicket/panels/DetailedRepositoryUrlPanel.java new file mode 100644 index 0000000..afeee1d --- /dev/null +++ b/src/main/java/com/gitblit/wicket/panels/DetailedRepositoryUrlPanel.java @@ -0,0 +1,115 @@ +/* + * 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 java.text.MessageFormat; + +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.panel.Fragment; + +import com.gitblit.Constants.AccessPermission; +import com.gitblit.GitBlit; +import com.gitblit.Keys; +import com.gitblit.utils.StringUtils; +import com.gitblit.wicket.WicketUtils; + +public class DetailedRepositoryUrlPanel extends BasePanel { + + private static final long serialVersionUID = 1L; + public DetailedRepositoryUrlPanel(String wicketId, Localizer localizer, Component parent, String repository, String url) { + this(wicketId, localizer, parent, repository, url, null); + } + + public DetailedRepositoryUrlPanel(String wicketId, Localizer localizer, Component parent, String repository, String url, AccessPermission ap) { + super(wicketId); + + String protocol = url.substring(0, url.indexOf(':')); + String note; + String permission; + + if (ap == null) { + note = MessageFormat.format(localizer.getString("gb.externalPermissions", parent), protocol, repository); + permission = ""; + } else { + note = null; + permission = ap.toString(); + String key; + switch (ap) { + case OWNER: + case REWIND: + key = "gb.rewindPermission"; + break; + case DELETE: + key = "gb.deletePermission"; + break; + case CREATE: + key = "gb.createPermission"; + break; + case PUSH: + key = "gb.pushPermission"; + break; + case CLONE: + key = "gb.clonePermission"; + break; + default: + key = null; + note = localizer.getString("gb.viewAccess", parent); + break; + } + + if (note == null) { + String pattern = localizer.getString(key, parent); + String description = MessageFormat.format(pattern, permission); + String permissionPattern = localizer.getString("gb.yourProtocolPermissionIs", parent); + note = MessageFormat.format(permissionPattern, protocol.toUpperCase(), repository, description); + } + } + + if (!StringUtils.isEmpty(url) && ((ap == null) || ap.atLeast(AccessPermission.CLONE))) { + // valid repository url + Fragment fragment = new Fragment("urlPanel", "repositoryUrlPanel", this); + add(fragment); + fragment.add(WicketUtils.setHtmlTooltip(new Label("repositoryProtocol", protocol + "://"), note)); + fragment.add(new Label("repositoryUrl", url.substring(url.indexOf("://") + 3))); + fragment.add(WicketUtils.setHtmlTooltip(new Label("repositoryUrlPermission", permission), note)); + + if (StringUtils.isEmpty(url)) { + fragment.add(new Label("copyFunction").setVisible(false)); + } else if (GitBlit.getBoolean(Keys.web.allowFlashCopyToClipboard, true)) { + // clippy: flash-based copy & paste + Fragment copyFragment = new Fragment("copyFunction", "clippyPanel", this); + String baseUrl = WicketUtils.getGitblitURL(getRequest()); + ShockWaveComponent clippy = new ShockWaveComponent("clippy", baseUrl + "/clippy.swf"); + clippy.setValue("flashVars", "text=" + StringUtils.encodeURL(url)); + copyFragment.add(clippy); + fragment.add(copyFragment); + } else { + // javascript: manual copy & paste with modal browser prompt dialog + Fragment copyFragment = new Fragment("copyFunction", "jsPanel", this); + ContextImage img = WicketUtils.newImage("copyIcon", "clippy.png"); + img.add(new JavascriptTextPrompt("onclick", "Copy to Clipboard (Ctrl+C, Enter)", url)); + copyFragment.add(img); + fragment.add(copyFragment); + } + } else { + // no Git url, there may be a message + add(new Label("urlPanel", MessageFormat.format("<i>{0}</i>", note)).setEscapeModelStrings(false).setVisible(!StringUtils.isEmpty(note))); + } + } +} diff --git a/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.html b/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.html index 9b621d5..e67e641 100644 --- a/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.html +++ b/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.html @@ -72,7 +72,7 @@ <span style="font-size:0.8em;" wicket:id="repositorySize">[repository size]</span> </div> - <div class="hidden-phone hidden-tablet" wicket:id="repositoryCloneUrl">[repository clone url]</div> + <div class="hidden-phone hidden-tablet" style="padding-top: 5px;" wicket:id="repositoryPrimaryUrl">[repository primary url]</div> </div> </div> </div> diff --git a/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java b/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java index f2b56e1..822a9b2 100644 --- a/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java +++ b/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java @@ -29,6 +29,7 @@ import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.panel.Fragment; +import com.gitblit.Constants.AccessPermission; import com.gitblit.Constants.AccessRestrictionType; import com.gitblit.GitBlit; import com.gitblit.Keys; @@ -221,9 +222,10 @@ // add the Gitblit repository url repositoryUrls.add(BasePage.getRepositoryUrl(entry)); } - repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(entry.name, user == null ? "" : user.username)); + repositoryUrls.addAll(GitBlit.self().getOtherCloneUrls(entry.name, UserModel.ANONYMOUS.equals(user) ? "" : user.username)); + AccessPermission ap = user.getRepositoryPermission(entry).permission; String primaryUrl = ArrayUtils.isEmpty(repositoryUrls) ? "" : repositoryUrls.remove(0); - add(new RepositoryUrlPanel("repositoryCloneUrl", primaryUrl)); + add(new DetailedRepositoryUrlPanel("repositoryPrimaryUrl",localizer, parent, entry.name, primaryUrl, ap)); } } diff --git a/src/main/resources/gitblit.css b/src/main/resources/gitblit.css index 811b08a..c93f6a6 100644 --- a/src/main/resources/gitblit.css +++ b/src/main/resources/gitblit.css @@ -179,6 +179,30 @@ vertical-align: middle; } +span.repositoryUrlContainer { + color: black; + background-color: #eee; + padding: 4px; + border: 1px solid #ccc; + border-radius: 3px +} + +span.repositoryUrlEndCap { + padding: 4px; + font-weight: bold; + font-size: 0.85em; + font-family:menlo,consolas,monospace; +} + +span.repositoryUrl { + font-size: 1em; + padding: 4px; + color: blue; + background-color: #fff; + border-left: 1px solid #ccc; + border-right: 1px solid #ccc; +} + div.odd { } -- Gitblit v1.9.1