From ba6150d1712d5f5986e72333831940a46316aab3 Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Fri, 02 Nov 2012 16:52:41 -0400 Subject: [PATCH] Permission filtering in web ui --- src/com/gitblit/models/RegistrantAccessPermission.java | 51 +++++++ src/com/gitblit/GitBlit.java | 61 +++++++- src/com/gitblit/wicket/GitBlitWebApp.properties | 5 .gitignore | 1 src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java | 90 +++++++++++- src/com/gitblit/client/GitblitClient.java | 56 +++++++ src/com/gitblit/client/RegistrantPermissionsPanel.java | 25 +++ src/com/gitblit/client/UsersPanel.java | 2 src/com/gitblit/wicket/pages/EditUserPage.java | 22 --- src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html | 20 ++ src/com/gitblit/client/Utils.java | 25 +++ src/com/gitblit/models/UserModel.java | 25 +++ 12 files changed, 328 insertions(+), 55 deletions(-) diff --git a/.gitignore b/.gitignore index 173bd34..ffaba31 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 0d883ad..0d37b44 100644 --- a/src/com/gitblit/GitBlit.java +++ b/src/com/gitblit/GitBlit.java @@ -79,6 +79,8 @@ 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 @@ * @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 @@ * @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 56078fc..1101cd6 100644 --- a/src/com/gitblit/client/GitblitClient.java +++ b/src/com/gitblit/client/GitblitClient.java @@ -31,6 +31,8 @@ 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 @@ 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 ef04a87..98dbfb7 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 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 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 @@ 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 1810f8c..e14c001 100644 --- a/src/com/gitblit/client/UsersPanel.java +++ b/src/com/gitblit/client/UsersPanel.java @@ -308,7 +308,7 @@ 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 b24c6d8..1e6ab2b 100644 --- a/src/com/gitblit/client/Utils.java +++ b/src/com/gitblit/client/Utils.java @@ -49,7 +49,25 @@ 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 @@ 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 4bdc2da..8f4049a 100644 --- a/src/com/gitblit/models/RegistrantAccessPermission.java +++ b/src/com/gitblit/models/RegistrantAccessPermission.java @@ -63,18 +63,67 @@ 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 23322c2..1159905 100644 --- a/src/com/gitblit/models/UserModel.java +++ b/src/com/gitblit/models/UserModel.java @@ -21,6 +21,7 @@ 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 @@ 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 @@ 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 @@ } 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 4303b13..22ae92f 100644 --- a/src/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/com/gitblit/wicket/GitBlitWebApp.properties @@ -370,4 +370,7 @@ 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 ea92293..80f09db 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.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 @@ 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 ec8d43d..eb82245 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 9431df8..689ee57 100644 --- a/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java +++ b/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java @@ -18,10 +18,12 @@ 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 @@ 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 @@ 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", " ").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 @@ 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 @@ } } - // 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,8 +262,12 @@ 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 @@ 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); + } + }; } -- Gitblit v1.9.1