summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Moger <james.moger@gitblit.com>2012-11-02 16:52:41 -0400
committerJames Moger <james.moger@gitblit.com>2012-11-02 16:52:41 -0400
commitba6150d1712d5f5986e72333831940a46316aab3 (patch)
tree50bd7211f952d50dd1034b0bcf0fc0f258c1cbfd
parent368dad4d78b15057f835f1a41c633ee3b7a83dcf (diff)
downloadgitblit-ba6150d1712d5f5986e72333831940a46316aab3.tar.gz
gitblit-ba6150d1712d5f5986e72333831940a46316aab3.zip
Permission filtering in web ui
Present the mutable permissions by default. Allow the administrator or owner to toggle the displayed permissions to see how the user and team permissions are applied to a repository.
-rw-r--r--.gitignore1
-rw-r--r--src/com/gitblit/GitBlit.java61
-rw-r--r--src/com/gitblit/client/GitblitClient.java56
-rw-r--r--src/com/gitblit/client/RegistrantPermissionsPanel.java25
-rw-r--r--src/com/gitblit/client/UsersPanel.java2
-rw-r--r--src/com/gitblit/client/Utils.java25
-rw-r--r--src/com/gitblit/models/RegistrantAccessPermission.java51
-rw-r--r--src/com/gitblit/models/UserModel.java25
-rw-r--r--src/com/gitblit/wicket/GitBlitWebApp.properties5
-rw-r--r--src/com/gitblit/wicket/pages/EditUserPage.java22
-rw-r--r--src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html20
-rw-r--r--src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java90
12 files changed, 328 insertions, 55 deletions
diff --git a/.gitignore b/.gitignore
index 173bd34f..ffaba310 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,3 +28,4 @@
/.gradle
/projects.conf
/pom.xml
+/deploy
diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java
index 0d883ad2..0d37b44f 100644
--- a/src/com/gitblit/GitBlit.java
+++ b/src/com/gitblit/GitBlit.java
@@ -79,6 +79,8 @@ import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.Constants.FederationRequest;
import com.gitblit.Constants.FederationStrategy;
import com.gitblit.Constants.FederationToken;
+import com.gitblit.Constants.PermissionType;
+import com.gitblit.Constants.RegistrantType;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.FederationSet;
@@ -658,18 +660,48 @@ public class GitBlit implements ServletContextListener {
* @return a user object or null
*/
public UserModel getUserModel(String username) {
- UserModel user = userService.getUserModel(username);
- if (user != null) {
- // TODO reconsider ownership as a user property
- // manually specify personal repository ownerships
- String folder = "~" + username;
- for (String repository : getRepositoryList()) {
- if (repository.toLowerCase().startsWith(folder)) {
- user.setRepositoryPermission(repository, AccessPermission.REWIND);
+ UserModel user = userService.getUserModel(username);
+ return user;
+ }
+
+ /**
+ * Returns the effective list of permissions for this user, taking into account
+ * team memberships, ownerships.
+ *
+ * @param user
+ * @return the effective list of permissions for the user
+ */
+ public List<RegistrantAccessPermission> getUserAccessPermissions(UserModel user) {
+ Set<RegistrantAccessPermission> set = new LinkedHashSet<RegistrantAccessPermission>();
+ set.addAll(user.getRepositoryPermissions());
+ // Flag missing repositories
+ for (RegistrantAccessPermission permission : set) {
+ if (permission.mutable && PermissionType.EXPLICIT.equals(permission.permissionType)) {
+ RepositoryModel rm = GitBlit.self().getRepositoryModel(permission.registrant);
+ if (rm == null) {
+ permission.permissionType = PermissionType.MISSING;
+ permission.mutable = false;
+ continue;
}
}
}
- return user;
+
+ // TODO reconsider ownership as a user property
+ // manually specify personal repository ownerships
+ for (RepositoryModel rm : repositoryListCache.values()) {
+ if (rm.isUsersPersonalRepository(user.username) || rm.isOwner(user.username)) {
+ RegistrantAccessPermission rp = new RegistrantAccessPermission(rm.name, AccessPermission.REWIND,
+ PermissionType.OWNER, RegistrantType.REPOSITORY, null, false);
+ // user may be owner of a repository to which they've inherited
+ // a team permission, replace any existing perm with owner perm
+ set.remove(rp);
+ set.add(rp);
+ }
+ }
+
+ List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>(set);
+ Collections.sort(list);
+ return list;
}
/**
@@ -681,7 +713,16 @@ public class GitBlit implements ServletContextListener {
* @return a list of RegistrantAccessPermissions
*/
public List<RegistrantAccessPermission> getUserAccessPermissions(RepositoryModel repository) {
- List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>();
+ List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>();
+ if (AccessRestrictionType.NONE.equals(repository.accessRestriction)) {
+ // no permissions needed, REWIND for everyone!
+ return list;
+ }
+ if (AuthorizationControl.AUTHENTICATED.equals(repository.authorizationControl)) {
+ // no permissions needed, REWIND for authenticated!
+ return list;
+ }
+ // NAMED users and teams
for (UserModel user : userService.getAllUsers()) {
RegistrantAccessPermission ap = user.getRepositoryPermission(repository);
if (ap.permission.exceeds(AccessPermission.NONE)) {
diff --git a/src/com/gitblit/client/GitblitClient.java b/src/com/gitblit/client/GitblitClient.java
index 56078fc3..1101cd60 100644
--- a/src/com/gitblit/client/GitblitClient.java
+++ b/src/com/gitblit/client/GitblitClient.java
@@ -31,6 +31,8 @@ import com.gitblit.Constants;
import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.AuthorizationControl;
+import com.gitblit.Constants.PermissionType;
+import com.gitblit.Constants.RegistrantType;
import com.gitblit.GitBlitException.ForbiddenException;
import com.gitblit.GitBlitException.NotAllowedException;
import com.gitblit.GitBlitException.UnauthorizedException;
@@ -505,15 +507,63 @@ public class GitblitClient implements Serializable {
return usernames;
}
+ /**
+ * Returns the effective list of permissions for this user, taking into account
+ * team memberships, ownerships.
+ *
+ * @param user
+ * @return the effective list of permissions for the user
+ */
+ public List<RegistrantAccessPermission> getUserAccessPermissions(UserModel user) {
+ Set<RegistrantAccessPermission> set = new LinkedHashSet<RegistrantAccessPermission>();
+ set.addAll(user.getRepositoryPermissions());
+ // Flag missing repositories
+ for (RegistrantAccessPermission permission : set) {
+ if (permission.mutable && PermissionType.EXPLICIT.equals(permission.permissionType)) {
+ RepositoryModel rm = getRepository(permission.registrant);
+ if (rm == null) {
+ permission.permissionType = PermissionType.MISSING;
+ permission.mutable = false;
+ continue;
+ }
+ }
+ }
+
+ // TODO reconsider ownership as a user property
+ // manually specify personal repository ownerships
+ for (RepositoryModel rm : allRepositories) {
+ if (rm.isUsersPersonalRepository(user.username) || rm.isOwner(user.username)) {
+ RegistrantAccessPermission rp = new RegistrantAccessPermission(rm.name, AccessPermission.REWIND,
+ PermissionType.OWNER, RegistrantType.REPOSITORY, null, false);
+ // user may be owner of a repository to which they've inherited
+ // a team permission, replace any existing perm with owner perm
+ set.remove(rp);
+ set.add(rp);
+ }
+ }
+
+ List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>(set);
+ Collections.sort(list);
+ return list;
+ }
+
public List<RegistrantAccessPermission> getUserAccessPermissions(RepositoryModel repository) {
- List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>();
- for (UserModel user : getUsers()) {
+ List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>();
+ if (AccessRestrictionType.NONE.equals(repository.accessRestriction)) {
+ // no permissions needed, REWIND for everyone!
+ return list;
+ }
+ if (AuthorizationControl.AUTHENTICATED.equals(repository.authorizationControl)) {
+ // no permissions needed, REWIND for authenticated!
+ return list;
+ }
+ // NAMED users and teams
+ for (UserModel user : allUsers) {
RegistrantAccessPermission ap = user.getRepositoryPermission(repository);
if (ap.permission.exceeds(AccessPermission.NONE)) {
list.add(ap);
}
}
- Collections.sort(list);
return list;
}
diff --git a/src/com/gitblit/client/RegistrantPermissionsPanel.java b/src/com/gitblit/client/RegistrantPermissionsPanel.java
index ef04a876..98dbfb72 100644
--- a/src/com/gitblit/client/RegistrantPermissionsPanel.java
+++ b/src/com/gitblit/client/RegistrantPermissionsPanel.java
@@ -16,11 +16,14 @@
package com.gitblit.client;
import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import javax.swing.DefaultCellEditor;
@@ -36,6 +39,7 @@ import javax.swing.table.DefaultTableCellRenderer;
import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.PermissionType;
import com.gitblit.Constants.RegistrantType;
+import com.gitblit.client.Utils.RowRenderer;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.utils.StringUtils;
@@ -60,7 +64,23 @@ public class RegistrantPermissionsPanel extends JPanel {
public RegistrantPermissionsPanel(final RegistrantType registrantType) {
super(new BorderLayout(5, 5));
tableModel = new RegistrantPermissionsTableModel();
- permissionsTable = Utils.newTable(tableModel, Utils.DATE_FORMAT);
+ permissionsTable = Utils.newTable(tableModel, Utils.DATE_FORMAT, new RowRenderer() {
+ Color clear = new Color(0, 0, 0, 0);
+ Color iceGray = new Color(0xf0, 0xf0, 0xf0);
+
+ @Override
+ public void prepareRow(Component c, boolean isSelected, int row, int column) {
+ if (isSelected) {
+ c.setBackground(permissionsTable.getSelectionBackground());
+ } else {
+ if (tableModel.permissions.get(row).mutable) {
+ c.setBackground(clear);
+ } else {
+ c.setBackground(iceGray);
+ }
+ }
+ }
+ });
permissionsTable.setModel(tableModel);
permissionsTable.setPreferredScrollableViewportSize(new Dimension(400, 150));
JScrollPane jsp = new JScrollPane(permissionsTable);
@@ -91,11 +111,14 @@ public class RegistrantPermissionsPanel extends JPanel {
rp.permission = (AccessPermission) permissionSelector.getSelectedItem();
if (StringUtils.findInvalidCharacter(rp.registrant) != null) {
rp.permissionType = PermissionType.REGEX;
+ rp.source = rp.registrant;
} else {
rp.permissionType = PermissionType.EXPLICIT;
}
tableModel.permissions.add(rp);
+ // resort permissions after insert to convey idea of eval order
+ Collections.sort(tableModel.permissions);
registrantModel.removeElement(rp.registrant);
registrantSelector.setSelectedIndex(-1);
diff --git a/src/com/gitblit/client/UsersPanel.java b/src/com/gitblit/client/UsersPanel.java
index 1810f8cb..e14c0010 100644
--- a/src/com/gitblit/client/UsersPanel.java
+++ b/src/com/gitblit/client/UsersPanel.java
@@ -308,7 +308,7 @@ public abstract class UsersPanel extends JPanel {
gitblit.getSettings());
dialog.setLocationRelativeTo(UsersPanel.this);
dialog.setUsers(gitblit.getUsers());
- dialog.setRepositories(gitblit.getRepositories(), user.getRepositoryPermissions());
+ dialog.setRepositories(gitblit.getRepositories(), gitblit.getUserAccessPermissions(user));
dialog.setTeams(gitblit.getTeams(), user.teams == null ? null : new ArrayList<TeamModel>(
user.teams));
dialog.setVisible(true);
diff --git a/src/com/gitblit/client/Utils.java b/src/com/gitblit/client/Utils.java
index b24c6d8e..1e6ab2bf 100644
--- a/src/com/gitblit/client/Utils.java
+++ b/src/com/gitblit/client/Utils.java
@@ -49,7 +49,25 @@ public class Utils {
public final static String DATE_FORMAT = "yyyy-MM-dd";
public static JTable newTable(TableModel model, String datePattern) {
- JTable table = new JTable(model);
+ return newTable(model, datePattern, null);
+ }
+
+ public static JTable newTable(TableModel model, String datePattern, final RowRenderer rowRenderer) {
+ JTable table;
+ if (rowRenderer == null) {
+ table = new JTable(model);
+ } else {
+ table = new JTable(model) {
+
+ @Override
+ public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
+ Component c = super.prepareRenderer(renderer, row, column);
+ boolean isSelected = isCellSelected(row, column);
+ rowRenderer.prepareRow(c, isSelected, row, column);
+ return c;
+ }
+ };
+ }
table.setRowHeight(table.getFont().getSize() + 8);
table.setCellSelectionEnabled(false);
table.setRowSelectionAllowed(true);
@@ -148,5 +166,8 @@ public class Utils {
showException(null, x);
}
}
-
+
+ public static abstract class RowRenderer {
+ public abstract void prepareRow(Component c, boolean isSelected, int row, int column);
+ }
}
diff --git a/src/com/gitblit/models/RegistrantAccessPermission.java b/src/com/gitblit/models/RegistrantAccessPermission.java
index 4bdc2da4..8f4049a8 100644
--- a/src/com/gitblit/models/RegistrantAccessPermission.java
+++ b/src/com/gitblit/models/RegistrantAccessPermission.java
@@ -63,18 +63,67 @@ public class RegistrantAccessPermission implements Serializable, Comparable<Regi
public boolean isOwner() {
return PermissionType.OWNER.equals(permissionType);
}
+
+ public boolean isExplicit() {
+ return PermissionType.EXPLICIT.equals(permissionType);
+ }
+
+ public boolean isRegex() {
+ return PermissionType.REGEX.equals(permissionType);
+ }
+
+ public boolean isTeam() {
+ return PermissionType.TEAM.equals(permissionType);
+ }
public boolean isMissing() {
return PermissionType.MISSING.equals(permissionType);
}
+ public int getScore() {
+ switch (registrantType) {
+ case REPOSITORY:
+ if (isAdmin()) {
+ return 0;
+ }
+ if (isOwner()) {
+ return 1;
+ }
+ if (isExplicit()) {
+ return 2;
+ }
+ if (isRegex()) {
+ return 3;
+ }
+ if (isTeam()) {
+ return 4;
+ }
+ default:
+ return 0;
+ }
+ }
+
@Override
public int compareTo(RegistrantAccessPermission p) {
switch (registrantType) {
case REPOSITORY:
+ // repository permissions are sorted in score order
+ // to convey the order in which permissions are tested
+ int score1 = getScore();
+ int score2 = p.getScore();
+ if (score1 <= 2 && score2 <= 2) {
+ // group admin, owner, and explicit together
+ return StringUtils.compareRepositoryNames(registrant, p.registrant);
+ }
+ if (score1 < score2) {
+ return -1;
+ } else if (score2 < score1) {
+ return 1;
+ }
return StringUtils.compareRepositoryNames(registrant, p.registrant);
default:
- return registrant.toLowerCase().compareTo(p.registrant.toLowerCase());
+ // user and team permissions are string sorted
+ return registrant.toLowerCase().compareTo(p.registrant.toLowerCase());
}
}
diff --git a/src/com/gitblit/models/UserModel.java b/src/com/gitblit/models/UserModel.java
index 23322c26..1159905d 100644
--- a/src/com/gitblit/models/UserModel.java
+++ b/src/com/gitblit/models/UserModel.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -160,7 +161,20 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel>
list.add(new RegistrantAccessPermission(registrant, ap, pType, RegistrantType.REPOSITORY, source, mutable));
}
Collections.sort(list);
- return list;
+
+ // include immutable team permissions, being careful to preserve order
+ Set<RegistrantAccessPermission> set = new LinkedHashSet<RegistrantAccessPermission>(list);
+ for (TeamModel team : teams) {
+ for (RegistrantAccessPermission teamPermission : team.getRepositoryPermissions()) {
+ // we can not change an inherited team permission, though we can override
+ teamPermission.registrantType = RegistrantType.REPOSITORY;
+ teamPermission.permissionType = PermissionType.TEAM;
+ teamPermission.source = team.name;
+ teamPermission.mutable = false;
+ set.add(teamPermission);
+ }
+ }
+ return new ArrayList<RegistrantAccessPermission>(set);
}
/**
@@ -253,6 +267,13 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel>
ap.permission = AccessPermission.NONE;
ap.mutable = false;
+ if (AccessRestrictionType.NONE.equals(repository.accessRestriction)) {
+ // anonymous rewind
+ ap.permissionType = PermissionType.ADMINISTRATOR;
+ ap.permission = AccessPermission.REWIND;
+ return ap;
+ }
+
// administrator
if (canAdmin()) {
ap.permissionType = PermissionType.ADMINISTRATOR;
@@ -277,7 +298,7 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel>
}
if (AuthorizationControl.AUTHENTICATED.equals(repository.authorizationControl) && isAuthenticated) {
- // AUTHENTICATED is a shortcut for authorizing all logged-in users RW access
+ // AUTHENTICATED is a shortcut for authorizing all logged-in users RW+ access
ap.permission = AccessPermission.REWIND;
return ap;
}
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties
index 4303b134..22ae92f7 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -370,4 +370,7 @@ gb.administratorPermission = Gitblit administrator
gb.team = team
gb.teamPermission = permission set by \"{0}\" team membership
gb.missing = missing!
-gb.missingPermission = the repository for this permission is missing! \ No newline at end of file
+gb.missingPermission = the repository for this permission is missing!
+gb.mutable = mutable
+gb.specified = specified
+gb.effective = effective
diff --git a/src/com/gitblit/wicket/pages/EditUserPage.java b/src/com/gitblit/wicket/pages/EditUserPage.java
index ea92293e..80f09dba 100644
--- a/src/com/gitblit/wicket/pages/EditUserPage.java
+++ b/src/com/gitblit/wicket/pages/EditUserPage.java
@@ -34,13 +34,11 @@ import org.apache.wicket.model.Model;
import org.apache.wicket.model.util.CollectionModel;
import org.apache.wicket.model.util.ListModel;
-import com.gitblit.Constants.PermissionType;
import com.gitblit.Constants.RegistrantType;
import com.gitblit.GitBlit;
import com.gitblit.GitBlitException;
import com.gitblit.Keys;
import com.gitblit.models.RegistrantAccessPermission;
-import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
@@ -104,25 +102,7 @@ public class EditUserPage extends RootSubPage {
Collections.sort(userTeams);
final String oldName = userModel.username;
- final List<RegistrantAccessPermission> permissions = userModel.getRepositoryPermissions();
- for (RegistrantAccessPermission permission : permissions) {
- if (permission.mutable && PermissionType.EXPLICIT.equals(permission.permissionType)) {
- // Ensure this is NOT an owner permission - which is non-editable
- // We don't know this from within the usermodel, ownership is a
- // property of a repository.
- RepositoryModel rm = GitBlit.self().getRepositoryModel(permission.registrant);
- if (rm == null) {
- permission.permissionType = PermissionType.MISSING;
- permission.mutable = false;
- continue;
- }
- boolean isOwner = rm.isOwner(oldName);
- if (isOwner) {
- permission.permissionType = PermissionType.OWNER;
- permission.mutable = false;
- }
- }
- }
+ final List<RegistrantAccessPermission> permissions = GitBlit.self().getUserAccessPermissions(userModel);
final Palette<String> teams = new Palette<String>("teams", new ListModel<String>(
new ArrayList<String>(userTeams)), new CollectionModel<String>(GitBlit.self()
diff --git a/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html b/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html
index ec8d43dd..eb82245c 100644
--- a/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html
+++ b/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html
@@ -7,20 +7,32 @@
<body>
<wicket:panel>
- <div wicket:id="permissionRow">
+ <form class="form-inline" wicket:id="permissionToggleForm">
+ <div style="padding-bottom:10px" class="btn-group pull-right" data-toggle="buttons-radio">
+ <a class="btn btn-info" wicket:id="showMutable"><wicket:message key="gb.mutable"></wicket:message></a>
+ <a class="btn btn-info" wicket:id="showSpecified"><wicket:message key="gb.specified"></wicket:message></a>
+ <a class="btn btn-info" wicket:id="showEffective"><wicket:message key="gb.effective"></wicket:message></a>
+ </div>
+ </form>
+
+ <div style="clear:both;" wicket:id="permissionRow">
<div style="padding-top:10px;border-left:1px solid #ccc;border-right:1px solid #ccc;" class="row-fluid">
<div style="padding-top:5px;padding-left:5px" class="span6"><span wicket:id="registrant"></span></div><div style="padding-top:5px;padding-right:5px;text-align:right;" class="span3"><span class="label" wicket:id="pType">[permission type]</span></div> <select class="input-medium" wicket:id="permission"></select>
</div>
</div>
- <div style="padding-top:15px;" class="row-fluid">
+ <div style="clear:both; padding-top:15px;" class="row-fluid">
<form style="padding: 20px 40px;" class="well form-inline" wicket:id="addPermissionForm">
<select class="input-xlarge" wicket:id="registrant"></select> <select class="input-large" wicket:id="permission"></select> <input class="btn btn-success" type="submit" value="Add" wicket:message="value:gb.add" wicket:id="addPermissionButton"/>
</form>
</div>
-
+
+ <wicket:fragment wicket:id="repositoryRegistrant">
+ <b><span class="repositorySwatch" wicket:id="repositorySwatch"></span></b> <span wicket:id="repositoryName"></span>
+ </wicket:fragment>
+
<wicket:fragment wicket:id="userRegistrant">
- <span wicket:id="userAvatar"></span> <span style="font-weight: bold;" wicket:id="userName"></span>
+ <span wicket:id="userAvatar"></span> <span wicket:id="userName"></span>
</wicket:fragment>
<wicket:fragment wicket:id="teamRegistrant">
diff --git a/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java b/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java
index 9431df8f..689ee571 100644
--- a/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java
+++ b/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java
@@ -18,10 +18,12 @@ package com.gitblit.wicket.panels;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
@@ -57,12 +59,42 @@ import com.gitblit.wicket.WicketUtils;
public class RegistrantPermissionsPanel extends BasePanel {
private static final long serialVersionUID = 1L;
-
+
+ public enum Show {
+ specified, mutable, effective;
+
+ public boolean show(RegistrantAccessPermission ap) {
+ switch (this) {
+ case specified:
+ return ap.mutable || ap.isOwner();
+ case mutable:
+ return ap.mutable;
+ case effective:
+ return true;
+ default:
+ return true;
+ }
+ }
+ }
+
+ private Show activeState = Show.mutable;
+
public RegistrantPermissionsPanel(String wicketId, RegistrantType registrantType, List<String> allRegistrants, final List<RegistrantAccessPermission> permissions, final Map<AccessPermission, String> translations) {
super(wicketId);
setOutputMarkupId(true);
-
- // update existing permissions repeater
+
+ /*
+ * Permission view toggle buttons
+ */
+ Form<Void> permissionToggleForm = new Form<Void>("permissionToggleForm");
+ permissionToggleForm.add(new ShowStateButton("showSpecified", Show.specified));
+ permissionToggleForm.add(new ShowStateButton("showMutable", Show.mutable));
+ permissionToggleForm.add(new ShowStateButton("showEffective", Show.effective));
+ add(permissionToggleForm);
+
+ /*
+ * Permission repeating display
+ */
RefreshingView<RegistrantAccessPermission> dataView = new RefreshingView<RegistrantAccessPermission>("permissionRow") {
private static final long serialVersionUID = 1L;
@@ -91,16 +123,19 @@ public class RegistrantPermissionsPanel extends BasePanel {
String repoName = StringUtils.stripDotGit(entry.registrant);
if (!entry.isMissing() && StringUtils.findInvalidCharacter(repoName) == null) {
// repository, strip .git and show swatch
- Label registrant = new Label("registrant", repoName);
- WicketUtils.setCssClass(registrant, "repositorySwatch");
- WicketUtils.setCssBackground(registrant, repoName);
- item.add(registrant);
+ Fragment repositoryFragment = new Fragment("registrant", "repositoryRegistrant", RegistrantPermissionsPanel.this);
+ Component swatch = new Label("repositorySwatch", "&nbsp;").setEscapeModelStrings(false);
+ WicketUtils.setCssBackground(swatch, entry.toString());
+ repositoryFragment.add(swatch);
+ Label registrant = new Label("repositoryName", repoName);
+ repositoryFragment.add(registrant);
+ item.add(repositoryFragment);
} else {
// regex or missing
Label label = new Label("registrant", entry.registrant);
WicketUtils.setCssStyle(label, "font-weight: bold;");
item.add(label);
- }
+ }
} else if (RegistrantType.USER.equals(entry.registrantType)) {
// user
PersonIdent ident = new PersonIdent(entry.registrant, null);
@@ -160,6 +195,8 @@ public class RegistrantPermissionsPanel extends BasePanel {
break;
}
+ item.setVisible(activeState.show(entry));
+
// use ajax to get immediate update of permission level change
// otherwise we can lose it if they change levels and then add
// a new repository permission
@@ -203,7 +240,9 @@ public class RegistrantPermissionsPanel extends BasePanel {
}
}
- // add new permission form
+ /*
+ * Add permission form
+ */
IModel<RegistrantAccessPermission> addPermissionModel = new CompoundPropertyModel<RegistrantAccessPermission>(new RegistrantAccessPermission(registrantType));
Form<RegistrantAccessPermission> addPermissionForm = new Form<RegistrantAccessPermission>("addPermissionForm", addPermissionModel);
addPermissionForm.add(new DropDownChoice<String>("registrant", registrants));
@@ -223,9 +262,13 @@ public class RegistrantPermissionsPanel extends BasePanel {
RegistrantAccessPermission copy = DeepCopier.copy(rp);
if (StringUtils.findInvalidCharacter(copy.registrant) != null) {
copy.permissionType = PermissionType.REGEX;
+ copy.source = copy.registrant;
}
permissions.add(copy);
+ // resort permissions after insert to convey idea of eval order
+ Collections.sort(permissions);
+
// remove registrant from available choices
registrants.remove(rp.registrant);
@@ -265,4 +308,33 @@ public class RegistrantPermissionsPanel extends BasePanel {
return Integer.toString(index);
}
}
+
+ private class ShowStateButton extends AjaxButton {
+ private static final long serialVersionUID = 1L;
+
+ Show buttonState;
+
+ public ShowStateButton(String wicketId, Show state) {
+ super(wicketId);
+ this.buttonState = state;
+ setOutputMarkupId(true);
+ }
+
+ @Override
+ protected void onBeforeRender()
+ {
+ String cssClass = "btn";
+ if (buttonState.equals(RegistrantPermissionsPanel.this.activeState)) {
+ cssClass = "btn btn-info active";
+ }
+ WicketUtils.setCssClass(this, cssClass);
+ super.onBeforeRender();
+ }
+
+ @Override
+ protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
+ RegistrantPermissionsPanel.this.activeState = buttonState;
+ target.addComponent(RegistrantPermissionsPanel.this);
+ }
+ };
}