From 27ae9095639bb228a1b7ff86a3ebe4264abf05be Mon Sep 17 00:00:00 2001
From: mschaefers <mschaefers@scoop-gmbh.de>
Date: Thu, 29 Nov 2012 12:33:09 -0500
Subject: [PATCH] feature: when using LdapUserService one can configure Gitblit to fetch all users from ldap that can possibly login. This allows to see newly generated LDAP users instantly in Gitblit. By now an LDAP user had to log in once to appear in GitBlit.
---
src/com/gitblit/wicket/panels/RepositoriesPanel.java | 289 ++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 234 insertions(+), 55 deletions(-)
diff --git a/src/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/com/gitblit/wicket/panels/RepositoriesPanel.java
index c141379..d3b8ddb 100644
--- a/src/com/gitblit/wicket/panels/RepositoriesPanel.java
+++ b/src/com/gitblit/wicket/panels/RepositoriesPanel.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2011 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;
@@ -10,12 +25,14 @@
import java.util.List;
import java.util.Map;
+import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.extensions.markup.html.repeater.data.sort.OrderByBorder;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.repeater.Item;
@@ -28,49 +45,103 @@
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
+import com.gitblit.SyndicationServlet;
+import com.gitblit.models.ProjectModel;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
-import com.gitblit.utils.TimeUtils;
import com.gitblit.wicket.GitBlitWebSession;
-import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.WicketUtils;
-import com.gitblit.wicket.models.RepositoryModel;
-import com.gitblit.wicket.models.UserModel;
+import com.gitblit.wicket.pages.BasePage;
import com.gitblit.wicket.pages.EditRepositoryPage;
+import com.gitblit.wicket.pages.EmptyRepositoryPage;
+import com.gitblit.wicket.pages.ProjectPage;
+import com.gitblit.wicket.pages.RepositoriesPage;
import com.gitblit.wicket.pages.SummaryPage;
+import com.gitblit.wicket.pages.UserPage;
public class RepositoriesPanel extends BasePanel {
private static final long serialVersionUID = 1L;
- public RepositoriesPanel(String wicketId, final boolean showAdmin, final Map<AccessRestrictionType, String> accessRestrictionTranslations) {
+ public RepositoriesPanel(String wicketId, final boolean showAdmin, final boolean showManagement,
+ List<RepositoryModel> models, boolean enableLinks,
+ final Map<AccessRestrictionType, String> accessRestrictionTranslations) {
super(wicketId);
+ final boolean linksActive = enableLinks;
+ final boolean showSize = GitBlit.getBoolean(Keys.web.showRepositorySizes, true);
+
final UserModel user = GitBlitWebSession.get().getUser();
- List<RepositoryModel> models = GitBlit.self().getRepositoryModels(user);
+
final IDataProvider<RepositoryModel> dp;
- Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);
- adminLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
- add(adminLinks.setVisible(showAdmin));
+ Fragment managementLinks;
+ if (showAdmin) {
+ // user is admin
+ managementLinks = new Fragment("managementPanel", "adminLinks", this);
+ managementLinks.add(new Link<Void>("clearCache") {
- if (GitBlit.self().settings().getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("grouped")) {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void onClick() {
+ GitBlit.self().resetRepositoryListCache();
+ setResponsePage(RepositoriesPage.class);
+ }
+ }.setVisible(GitBlit.getBoolean(Keys.git.cacheRepositoryList, true)));
+ managementLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
+ add(managementLinks);
+ } else if (showManagement && user != null && user.canCreate()) {
+ // user can create personal repositories
+ managementLinks = new Fragment("managementPanel", "personalLinks", this);
+ managementLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
+ add(managementLinks);
+ } else {
+ // user has no management permissions
+ add (new Label("managementPanel").setVisible(false));
+ }
+
+ if (GitBlit.getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("grouped")) {
+ List<RepositoryModel> rootRepositories = new ArrayList<RepositoryModel>();
Map<String, List<RepositoryModel>> groups = new HashMap<String, List<RepositoryModel>>();
for (RepositoryModel model : models) {
String rootPath = StringUtils.getRootPath(model.name);
if (StringUtils.isEmpty(rootPath)) {
- rootPath = GitBlit.self().settings().getString(Keys.web.repositoryRootGroupName, " ");
+ // root repository
+ rootRepositories.add(model);
+ } else {
+ // non-root, grouped repository
+ if (!groups.containsKey(rootPath)) {
+ groups.put(rootPath, new ArrayList<RepositoryModel>());
+ }
+ groups.get(rootPath).add(model);
}
- if (!groups.containsKey(rootPath)) {
- groups.put(rootPath, new ArrayList<RepositoryModel>());
- }
- groups.get(rootPath).add(model);
}
List<String> roots = new ArrayList<String>(groups.keySet());
Collections.sort(roots);
+
+ if (rootRepositories.size() > 0) {
+ // inject the root repositories at the top of the page
+ String rootPath = GitBlit.getString(Keys.web.repositoryRootGroupName, " ");
+ roots.add(0, rootPath);
+ groups.put(rootPath, rootRepositories);
+ }
+
+ Map<String, ProjectModel> projects = new HashMap<String, ProjectModel>();
+ for (ProjectModel project : GitBlit.self().getProjectModels(user, true)) {
+ projects.put(project.name, project);
+ }
List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>();
for (String root : roots) {
List<RepositoryModel> subModels = groups.get(root);
- groupedModels.add(new GroupRepositoryModel(root, subModels.size()));
+ GroupRepositoryModel group = new GroupRepositoryModel(root, subModels.size());
+ if (projects.containsKey(root)) {
+ group.title = projects.get(root).title;
+ group.description = projects.get(root).description;
+ }
+ groupedModels.add(group);
+ Collections.sort(subModels);
groupedModels.addAll(subModels);
}
dp = new RepositoriesProvider(groupedModels);
@@ -78,9 +149,13 @@
dp = new SortableRepositoriesProvider(models);
}
+ final String baseUrl = WicketUtils.getGitblitURL(getRequest());
+ final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true);
+
DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) {
private static final long serialVersionUID = 1L;
- int counter = 0;
+ int counter;
+ String currGroupName;
@Override
protected void onBeforeRender() {
@@ -91,70 +166,158 @@
public void populateItem(final Item<RepositoryModel> item) {
final RepositoryModel entry = item.getModelObject();
if (entry instanceof GroupRepositoryModel) {
+ GroupRepositoryModel groupRow = (GroupRepositoryModel) entry;
+ currGroupName = entry.name;
Fragment row = new Fragment("rowContent", "groupRepositoryRow", this);
item.add(row);
- row.add(new Label("groupName", entry.toString()));
+
+ String name = groupRow.name;
+ if (name.charAt(0) == '~') {
+ // user page
+ String username = name.substring(1);
+ UserModel user = GitBlit.self().getUserModel(username);
+ row.add(new LinkPanel("groupName", null, (user == null ? username : user.getDisplayName()) + " (" + groupRow.count + ")", UserPage.class, WicketUtils.newUsernameParameter(username)));
+ row.add(new Label("groupDescription", getString("gb.personalRepositories")));
+ } else {
+ // project page
+ row.add(new LinkPanel("groupName", null, groupRow.toString(), ProjectPage.class, WicketUtils.newProjectParameter(entry.name)));
+ row.add(new Label("groupDescription", entry.description == null ? "":entry.description));
+ }
WicketUtils.setCssClass(item, "group");
+ // reset counter so that first row is light background
+ counter = 0;
return;
}
Fragment row = new Fragment("rowContent", "repositoryRow", this);
item.add(row);
+
+ // try to strip group name for less cluttered list
+ String repoName = entry.toString();
+ if (!StringUtils.isEmpty(currGroupName) && (repoName.indexOf('/') > -1)) {
+ repoName = repoName.substring(currGroupName.length() + 1);
+ }
+
+ // repository swatch
+ Component swatch;
+ if (entry.isBare){
+ swatch = new Label("repositorySwatch", " ").setEscapeModelStrings(false);
+ } else {
+ swatch = new Label("repositorySwatch", "!");
+ WicketUtils.setHtmlTooltip(swatch, getString("gb.workingCopyWarning"));
+ }
+ WicketUtils.setCssBackground(swatch, entry.toString());
+ row.add(swatch);
+ swatch.setVisible(showSwatch);
+
+ if (linksActive) {
+ Class<? extends BasePage> linkPage;
+ if (entry.hasCommits) {
+ // repository has content
+ linkPage = SummaryPage.class;
+ } else {
+ // new/empty repository OR proposed repository
+ linkPage = EmptyRepositoryPage.class;
+ }
+
+ PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);
+ row.add(new LinkPanel("repositoryName", "list", repoName, linkPage, pp));
+ row.add(new LinkPanel("repositoryDescription", "list", entry.description,
+ linkPage, pp));
+ } else {
+ // no links like on a federation page
+ row.add(new Label("repositoryName", repoName));
+ row.add(new Label("repositoryDescription", entry.description));
+ }
if (entry.hasCommits) {
// Existing repository
- PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);
- row.add(new LinkPanel("repositoryName", "list", entry.name, SummaryPage.class, pp));
- row.add(new LinkPanel("repositoryDescription", "list", entry.description, SummaryPage.class, pp));
+ row.add(new Label("repositorySize", entry.size).setVisible(showSize));
} else {
// New repository
- row.add(new Label("repositoryName", entry.name + "<span class='empty'>(empty)</span>").setEscapeModelStrings(false));
- row.add(new Label("repositoryDescription", entry.description));
+ row.add(new Label("repositorySize", "<span class='empty'>(" + getString("gb.empty") + ")</span>")
+ .setEscapeModelStrings(false));
+ }
+
+ if (entry.isFork()) {
+ row.add(WicketUtils.newImage("forkIcon", "commit_divide_16x16.png",
+ getString("gb.isFork")));
+ } else {
+ row.add(WicketUtils.newClearPixel("forkIcon").setVisible(false));
}
if (entry.useTickets) {
- row.add(WicketUtils.newImage("ticketsIcon", "bug_16x16.png", getString("gb.tickets")));
+ row.add(WicketUtils.newImage("ticketsIcon", "bug_16x16.png",
+ getString("gb.tickets")));
} else {
row.add(WicketUtils.newBlankImage("ticketsIcon"));
}
if (entry.useDocs) {
- row.add(WicketUtils.newImage("docsIcon", "book_16x16.png", getString("gb.docs")));
+ row.add(WicketUtils
+ .newImage("docsIcon", "book_16x16.png", getString("gb.docs")));
} else {
row.add(WicketUtils.newBlankImage("docsIcon"));
}
if (entry.isFrozen) {
- row.add(WicketUtils.newImage("frozenIcon", "cold_16x16.png", getString("gb.isFrozen")));
+ row.add(WicketUtils.newImage("frozenIcon", "cold_16x16.png",
+ getString("gb.isFrozen")));
} else {
row.add(WicketUtils.newClearPixel("frozenIcon").setVisible(false));
+ }
+
+ if (entry.isFederated) {
+ row.add(WicketUtils.newImage("federatedIcon", "federated_16x16.png",
+ getString("gb.isFederated")));
+ } else {
+ row.add(WicketUtils.newClearPixel("federatedIcon").setVisible(false));
}
switch (entry.accessRestriction) {
case NONE:
row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));
break;
case PUSH:
- row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));
+ row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png",
+ accessRestrictionTranslations.get(entry.accessRestriction)));
break;
case CLONE:
- row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));
+ row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png",
+ accessRestrictionTranslations.get(entry.accessRestriction)));
break;
case VIEW:
- row.add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));
+ row.add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png",
+ accessRestrictionTranslations.get(entry.accessRestriction)));
break;
default:
row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));
}
- row.add(new Label("repositoryOwner", entry.owner));
+ String owner = entry.owner;
+ if (!StringUtils.isEmpty(owner)) {
+ UserModel ownerModel = GitBlit.self().getUserModel(owner);
+ if (ownerModel != null) {
+ owner = ownerModel.getDisplayName();
+ }
+ }
+ row.add(new Label("repositoryOwner", owner));
- String lastChange = TimeUtils.timeAgo(entry.lastChange);
+ String lastChange;
+ if (entry.lastChange.getTime() == 0) {
+ lastChange = "--";
+ } else {
+ lastChange = getTimeUtils().timeAgo(entry.lastChange);
+ }
Label lastChangeLabel = new Label("repositoryLastChange", lastChange);
row.add(lastChangeLabel);
- WicketUtils.setCssClass(lastChangeLabel, TimeUtils.timeAgoCss(entry.lastChange));
+ WicketUtils.setCssClass(lastChangeLabel, getTimeUtils().timeAgoCss(entry.lastChange));
- boolean showOwner = user != null && user.getUsername().equalsIgnoreCase(entry.owner);
- if (showAdmin) {
- Fragment repositoryLinks = new Fragment("repositoryLinks", "repositoryAdminLinks", this);
- repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository", EditRepositoryPage.class, WicketUtils.newRepositoryParameter(entry.name)));
+ boolean showOwner = user != null && entry.isOwner(user.username);
+ boolean myPersonalRepository = showOwner && entry.isUsersPersonalRepository(user.username);
+ if (showAdmin || myPersonalRepository) {
+ Fragment repositoryLinks = new Fragment("repositoryLinks",
+ "repositoryAdminLinks", this);
+ repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository",
+ EditRepositoryPage.class, WicketUtils
+ .newRepositoryParameter(entry.name)));
Link<Void> deleteLink = new Link<Void>("deleteRepository") {
private static final long serialVersionUID = 1L;
@@ -162,27 +325,33 @@
@Override
public void onClick() {
if (GitBlit.self().deleteRepositoryModel(entry)) {
- info(MessageFormat.format("Repository ''{0}'' deleted.", entry));
if (dp instanceof SortableRepositoriesProvider) {
+ info(MessageFormat.format(getString("gb.repositoryDeleted"), entry));
((SortableRepositoriesProvider) dp).remove(entry);
} else {
- ((RepositoriesProvider) dp).remove(entry);
+ setResponsePage(getPage().getClass(), getPage().getPageParameters());
}
} else {
- error(MessageFormat.format("Failed to delete repository ''{0}''!", entry));
+ error(MessageFormat.format(getString("gb.repositoryDeleteFailed"), entry));
}
}
};
- deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format("Delete repository \"{0}\"?", entry)));
+ deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format(
+ getString("gb.deleteRepository"), entry)));
repositoryLinks.add(deleteLink);
row.add(repositoryLinks);
} else if (showOwner) {
- Fragment repositoryLinks = new Fragment("repositoryLinks", "repositoryOwnerLinks", this);
- repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository", EditRepositoryPage.class, WicketUtils.newRepositoryParameter(entry.name)));
+ Fragment repositoryLinks = new Fragment("repositoryLinks",
+ "repositoryOwnerLinks", this);
+ repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository",
+ EditRepositoryPage.class, WicketUtils
+ .newRepositoryParameter(entry.name)));
row.add(repositoryLinks);
} else {
row.add(new Label("repositoryLinks"));
}
+ row.add(new ExternalLink("syndication", SyndicationServlet.asLink(baseUrl,
+ entry.name, null, 0)).setVisible(linksActive));
WicketUtils.setAlternatingBackground(item, counter);
counter++;
}
@@ -205,11 +374,12 @@
}
}
- private class GroupRepositoryModel extends RepositoryModel {
+ private static class GroupRepositoryModel extends RepositoryModel {
private static final long serialVersionUID = 1L;
- int count = 0;
+ int count;
+ String title;
GroupRepositoryModel(String name, int count) {
super(name, "", "", new Date(0));
@@ -218,7 +388,7 @@
@Override
public String toString() {
- return name + " (" + count + ")";
+ return (StringUtils.isEmpty(title) ? name : title) + " (" + count + ")";
}
}
@@ -226,7 +396,8 @@
repository, description, owner, date;
}
- protected OrderByBorder newSort(String wicketId, SortBy field, SortableDataProvider<?> dp, final DataView<?> dataView) {
+ protected OrderByBorder newSort(String wicketId, SortBy field, SortableDataProvider<?> dp,
+ final DataView<?> dataView) {
return new OrderByBorder(wicketId, field.name(), dp) {
private static final long serialVersionUID = 1L;
@@ -237,7 +408,7 @@
};
}
- private class RepositoriesProvider extends ListDataProvider<RepositoryModel> {
+ private static class RepositoriesProvider extends ListDataProvider<RepositoryModel> {
private static final long serialVersionUID = 1L;
@@ -264,7 +435,8 @@
}
} else if (index < (getData().size() - 1)) {
// not last element. check next element for group match.
- if (getData().get(index - 1) instanceof GroupRepositoryModel && getData().get(index + 1) instanceof GroupRepositoryModel) {
+ if (getData().get(index - 1) instanceof GroupRepositoryModel
+ && getData().get(index + 1) instanceof GroupRepositoryModel) {
// repository is sandwiched by group headers so this
// repository is the only element in the group. remove
// group.
@@ -289,9 +461,11 @@
}
}
- private class SortableRepositoriesProvider extends SortableDataProvider<RepositoryModel> {
+ private static class SortableRepositoriesProvider extends SortableDataProvider<RepositoryModel> {
+
private static final long serialVersionUID = 1L;
- private List<RepositoryModel> list = null;
+
+ private List<RepositoryModel> list;
protected SortableRepositoriesProvider(List<RepositoryModel> list) {
this.list = list;
@@ -304,8 +478,9 @@
@Override
public int size() {
- if (list == null)
+ if (list == null) {
return 0;
+ }
return list.size();
}
@@ -324,8 +499,9 @@
Collections.sort(list, new Comparator<RepositoryModel>() {
@Override
public int compare(RepositoryModel o1, RepositoryModel o2) {
- if (asc)
+ if (asc) {
return o1.lastChange.compareTo(o2.lastChange);
+ }
return o2.lastChange.compareTo(o1.lastChange);
}
});
@@ -333,8 +509,9 @@
Collections.sort(list, new Comparator<RepositoryModel>() {
@Override
public int compare(RepositoryModel o1, RepositoryModel o2) {
- if (asc)
+ if (asc) {
return o1.name.compareTo(o2.name);
+ }
return o2.name.compareTo(o1.name);
}
});
@@ -342,8 +519,9 @@
Collections.sort(list, new Comparator<RepositoryModel>() {
@Override
public int compare(RepositoryModel o1, RepositoryModel o2) {
- if (asc)
+ if (asc) {
return o1.owner.compareTo(o2.owner);
+ }
return o2.owner.compareTo(o1.owner);
}
});
@@ -351,8 +529,9 @@
Collections.sort(list, new Comparator<RepositoryModel>() {
@Override
public int compare(RepositoryModel o1, RepositoryModel o2) {
- if (asc)
+ if (asc) {
return o1.description.compareTo(o2.description);
+ }
return o2.description.compareTo(o1.description);
}
});
--
Gitblit v1.9.1