diff options
author | James Moger <james.moger@gitblit.com> | 2012-10-29 23:22:54 -0400 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2012-10-29 23:22:54 -0400 |
commit | 092f0a62302e87f44403ba24fc519c65534dbfff (patch) | |
tree | 340b5c18c29c1662d790fbf0d4422702c92eb3ce | |
parent | 8bc725871269aa47f8ef6db086a4cfedc75ef140 (diff) | |
download | gitblit-092f0a62302e87f44403ba24fc519c65534dbfff.tar.gz gitblit-092f0a62302e87f44403ba24fc519c65534dbfff.zip |
Stabilizing and polishing permissions ui. Still in-progress.
23 files changed, 519 insertions, 114 deletions
diff --git a/resources/gitblit.css b/resources/gitblit.css index 5c2d92a8..e5363c85 100644 --- a/resources/gitblit.css +++ b/resources/gitblit.css @@ -188,6 +188,12 @@ div.even { vertical-align: middle;
}
+span.authorizationControl label {
+ display: inline;
+ color: #777;
+ padding:5px 0px 5px 10px;
+}
+
div.page_footer {
clear: both;
height: 17px;
diff --git a/src/com/gitblit/Constants.java b/src/com/gitblit/Constants.java index f74317ea..e7812ee3 100644 --- a/src/com/gitblit/Constants.java +++ b/src/com/gitblit/Constants.java @@ -386,6 +386,10 @@ public class Constants { REPOSITORY, USER, TEAM;
}
+ public static enum PermissionType {
+ EXPLICIT, OWNER, REGEX;
+ }
+
public static enum GCStatus {
READY, COLLECTING;
diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java index 402f600d..6e587caa 100644 --- a/src/com/gitblit/GitBlit.java +++ b/src/com/gitblit/GitBlit.java @@ -79,6 +79,7 @@ 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;
@@ -670,14 +671,35 @@ public class GitBlit implements ServletContextListener { * @return a list of User-AccessPermission tuples
*/
public List<RegistrantAccessPermission> getUserAccessPermissions(RepositoryModel repository) {
- List<RegistrantAccessPermission> permissions = new ArrayList<RegistrantAccessPermission>();
+ Set<RegistrantAccessPermission> permissions = new LinkedHashSet<RegistrantAccessPermission>();
+ if (!StringUtils.isEmpty(repository.owner)) {
+ UserModel owner = userService.getUserModel(repository.owner);
+ if (owner != null) {
+ permissions.add(new RegistrantAccessPermission(owner.username, AccessPermission.REWIND, PermissionType.OWNER, RegistrantType.USER, false));
+ }
+ }
+ if (repository.isPersonalRepository()) {
+ UserModel owner = userService.getUserModel(repository.projectPath.substring(1));
+ if (owner != null) {
+ permissions.add(new RegistrantAccessPermission(owner.username, AccessPermission.REWIND, PermissionType.OWNER, RegistrantType.USER, false));
+ }
+ }
for (String user : userService.getUsernamesForRepositoryRole(repository.name)) {
UserModel model = userService.getUserModel(user);
AccessPermission ap = model.getRepositoryPermission(repository);
- boolean isExplicit = model.hasExplicitRepositoryPermission(repository.name);
- permissions.add(new RegistrantAccessPermission(user, ap, isExplicit, RegistrantType.USER));
- }
- return permissions;
+ PermissionType pType = PermissionType.REGEX;
+ boolean editable = false;
+ if (repository.isOwner(model.username)) {
+ pType = PermissionType.OWNER;
+ } else if (repository.isUsersPersonalRepository(model.username)) {
+ pType = PermissionType.OWNER;
+ } else if (model.hasExplicitRepositoryPermission(repository.name)) {
+ pType = PermissionType.EXPLICIT;
+ editable = true;
+ }
+ permissions.add(new RegistrantAccessPermission(user, ap, pType, RegistrantType.USER, editable));
+ }
+ return new ArrayList<RegistrantAccessPermission>(permissions);
}
/**
@@ -690,8 +712,8 @@ public class GitBlit implements ServletContextListener { public boolean setUserAccessPermissions(RepositoryModel repository, Collection<RegistrantAccessPermission> permissions) {
List<UserModel> users = new ArrayList<UserModel>();
for (RegistrantAccessPermission up : permissions) {
- if (up.isExplicit) {
- // only set explicitly defined permissions
+ if (up.isEditable) {
+ // only set editable defined permissions
UserModel user = userService.getUserModel(up.registrant);
user.setRepositoryPermission(repository.name, up.permission);
users.add(user);
@@ -811,8 +833,13 @@ public class GitBlit implements ServletContextListener { for (String team : userService.getTeamnamesForRepositoryRole(repository.name)) {
TeamModel model = userService.getTeamModel(team);
AccessPermission ap = model.getRepositoryPermission(repository);
- boolean isExplicit = model.hasExplicitRepositoryPermission(repository.name);
- permissions.add(new RegistrantAccessPermission(team, ap, isExplicit, RegistrantType.TEAM));
+ PermissionType pType = PermissionType.REGEX;
+ boolean editable = false;
+ if (model.hasExplicitRepositoryPermission(repository.name)) {
+ pType = PermissionType.EXPLICIT;
+ editable = true;
+ }
+ permissions.add(new RegistrantAccessPermission(team, ap, pType, RegistrantType.TEAM, editable));
}
return permissions;
}
@@ -827,7 +854,7 @@ public class GitBlit implements ServletContextListener { public boolean setTeamAccessPermissions(RepositoryModel repository, Collection<RegistrantAccessPermission> permissions) {
List<TeamModel> teams = new ArrayList<TeamModel>();
for (RegistrantAccessPermission tp : permissions) {
- if (tp.isExplicit) {
+ if (tp.isEditable) {
// only set explicitly defined access permissions
TeamModel team = userService.getTeamModel(tp.registrant);
team.setRepositoryPermission(repository.name, tp.permission);
@@ -1870,7 +1897,9 @@ public class GitBlit implements ServletContextListener { config.setBoolean(Constants.CONFIG_GITBLIT, null, "isFederated", repository.isFederated);
config.setString(Constants.CONFIG_GITBLIT, null, "gcThreshold", repository.gcThreshold);
config.setString(Constants.CONFIG_GITBLIT, null, "gcPeriod", repository.gcPeriod);
- config.setString(Constants.CONFIG_GITBLIT, null, "lastGC", new SimpleDateFormat(Constants.ISO8601).format(repository.lastGC));
+ if (repository.lastGC != null) {
+ config.setString(Constants.CONFIG_GITBLIT, null, "lastGC", new SimpleDateFormat(Constants.ISO8601).format(repository.lastGC));
+ }
updateList(config, "federationSets", repository.federationSets);
updateList(config, "preReceiveScript", repository.preReceiveScripts);
diff --git a/src/com/gitblit/client/EditRepositoryDialog.java b/src/com/gitblit/client/EditRepositoryDialog.java index 0adf8a80..06621c21 100644 --- a/src/com/gitblit/client/EditRepositoryDialog.java +++ b/src/com/gitblit/client/EditRepositoryDialog.java @@ -24,6 +24,8 @@ import java.awt.GridLayout; import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.text.MessageFormat;
import java.util.ArrayList;
@@ -37,6 +39,7 @@ import java.util.Set; import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
+import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
@@ -59,6 +62,7 @@ import javax.swing.ScrollPaneConstants; import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.Constants.FederationStrategy;
+import com.gitblit.Constants.RegistrantType;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
import com.gitblit.utils.ArrayUtils;
@@ -218,13 +222,41 @@ public class EditRepositoryDialog extends JDialog { accessRestriction = new JComboBox(AccessRestrictionType.values());
accessRestriction.setRenderer(new AccessRestrictionRenderer());
accessRestriction.setSelectedItem(anRepository.accessRestriction);
+ accessRestriction.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ if (e.getStateChange() == ItemEvent.SELECTED) {
+ AccessRestrictionType art = (AccessRestrictionType) accessRestriction.getSelectedItem();
+ EditRepositoryDialog.this.setupAccessPermissions(art);
+ }
+ }
+ });
boolean authenticated = anRepository.authorizationControl != null
&& AuthorizationControl.AUTHENTICATED.equals(anRepository.authorizationControl);
allowAuthenticated = new JRadioButton(Translation.get("gb.allowAuthenticatedDescription"));
allowAuthenticated.setSelected(authenticated);
+ allowAuthenticated.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ if (e.getStateChange() == ItemEvent.SELECTED) {
+ usersPalette.setEnabled(false);
+ teamsPalette.setEnabled(false);
+ }
+ }
+ });
+
allowNamed = new JRadioButton(Translation.get("gb.allowNamedDescription"));
allowNamed.setSelected(!authenticated);
+ allowNamed.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ if (e.getStateChange() == ItemEvent.SELECTED) {
+ usersPalette.setEnabled(true);
+ teamsPalette.setEnabled(true);
+ }
+ }
+ });
ButtonGroup group = new ButtonGroup();
group.add(allowAuthenticated);
@@ -281,7 +313,7 @@ public class EditRepositoryDialog extends JDialog { clonePushPanel
.add(newFieldPanel(Translation.get("gb.verifyCommitter"), verifyCommitter));
- usersPalette = new RegistrantPermissionsPanel();
+ usersPalette = new RegistrantPermissionsPanel(RegistrantType.USER);
JPanel northAccessPanel = new JPanel(new BorderLayout(5, 5));
northAccessPanel.add(newFieldPanel(Translation.get("gb.accessRestriction"),
accessRestriction), BorderLayout.NORTH);
@@ -294,7 +326,7 @@ public class EditRepositoryDialog extends JDialog { accessPanel.add(newFieldPanel(Translation.get("gb.userPermissions"),
usersPalette), BorderLayout.CENTER);
- teamsPalette = new RegistrantPermissionsPanel();
+ teamsPalette = new RegistrantPermissionsPanel(RegistrantType.TEAM);
JPanel teamsPanel = new JPanel(new BorderLayout(5, 5));
teamsPanel.add(
newFieldPanel(Translation.get("gb.teamPermissions"),
@@ -349,6 +381,8 @@ public class EditRepositoryDialog extends JDialog { panel.addTab(Translation.get("gb.customFields"), customFieldsScrollPane);
+ setupAccessPermissions(anRepository.accessRestriction);
+
JButton createButton = new JButton(Translation.get("gb.save"));
createButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
@@ -403,6 +437,25 @@ public class EditRepositoryDialog extends JDialog { panel.add(comp);
return panel;
}
+
+ private void setupAccessPermissions(AccessRestrictionType art) {
+ if (AccessRestrictionType.NONE.equals(art)) {
+ usersPalette.setEnabled(false);
+ teamsPalette.setEnabled(false);
+
+ allowAuthenticated.setEnabled(false);
+ allowNamed.setEnabled(false);
+ } else {
+ allowAuthenticated.setEnabled(true);
+ allowNamed.setEnabled(true);
+
+ if (allowNamed.isSelected()) {
+ usersPalette.setEnabled(true);
+ teamsPalette.setEnabled(true);
+ }
+ }
+
+ }
private boolean validateFields() {
String rname = nameField.getText();
@@ -538,6 +591,7 @@ public class EditRepositoryDialog extends JDialog { public void setAccessRestriction(AccessRestrictionType restriction) {
this.accessRestriction.setSelectedItem(restriction);
+ setupAccessPermissions(restriction);
}
public void setAuthorizationControl(AuthorizationControl authorization) {
@@ -659,14 +713,15 @@ public class EditRepositoryDialog extends JDialog { * restriction.
*
*/
- private class AccessRestrictionRenderer extends JLabel implements
- ListCellRenderer {
+ private class AccessRestrictionRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 1L;
@Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
+ super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+
if (value instanceof AccessRestrictionType) {
AccessRestrictionType restriction = (AccessRestrictionType) value;
switch (restriction) {
diff --git a/src/com/gitblit/client/EditTeamDialog.java b/src/com/gitblit/client/EditTeamDialog.java index 4350310e..4d7af261 100644 --- a/src/com/gitblit/client/EditTeamDialog.java +++ b/src/com/gitblit/client/EditTeamDialog.java @@ -45,11 +45,12 @@ import javax.swing.JTextField; import javax.swing.KeyStroke;
import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
+import com.gitblit.Constants.RegistrantType;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.ServerSettings;
import com.gitblit.models.TeamModel;
-import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.StringUtils;
public class EditTeamDialog extends JDialog {
@@ -140,7 +141,7 @@ public class EditTeamDialog extends JDialog { fieldsPanel.add(newFieldPanel(Translation.get("gb.mailingLists"), mailingListsField));
final Insets _insets = new Insets(5, 5, 5, 5);
- repositoryPalette = new RegistrantPermissionsPanel();
+ repositoryPalette = new RegistrantPermissionsPanel(RegistrantType.REPOSITORY);
userPalette = new JPalette<String>();
userPalette.setEnabled(settings.supportsTeamMembershipChanges);
@@ -311,9 +312,10 @@ public class EditTeamDialog extends JDialog { public void setRepositories(List<RepositoryModel> repositories, List<RegistrantAccessPermission> permissions) {
List<String> restricted = new ArrayList<String>();
for (RepositoryModel repo : repositories) {
- if (repo.accessRestriction.exceeds(AccessRestrictionType.NONE)) {
+ if (repo.accessRestriction.exceeds(AccessRestrictionType.NONE)
+ && repo.authorizationControl.equals(AuthorizationControl.NAMED)) {
restricted.add(repo.name);
- }
+ }
}
StringUtils.sortRepositorynames(restricted);
diff --git a/src/com/gitblit/client/EditUserDialog.java b/src/com/gitblit/client/EditUserDialog.java index e0966933..070926dd 100644 --- a/src/com/gitblit/client/EditUserDialog.java +++ b/src/com/gitblit/client/EditUserDialog.java @@ -46,6 +46,8 @@ import javax.swing.JTextField; import javax.swing.KeyStroke;
import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
+import com.gitblit.Constants.RegistrantType;
import com.gitblit.Keys;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
@@ -158,7 +160,7 @@ public class EditUserDialog extends JDialog { notFederatedCheckbox));
final Insets _insets = new Insets(5, 5, 5, 5);
- repositoryPalette = new RegistrantPermissionsPanel();
+ repositoryPalette = new RegistrantPermissionsPanel(RegistrantType.REPOSITORY);
teamsPalette = new JPalette<TeamModel>();
teamsPalette.setEnabled(settings.supportsTeamMembershipChanges);
@@ -343,8 +345,12 @@ public class EditUserDialog extends JDialog { public void setRepositories(List<RepositoryModel> repositories, List<RegistrantAccessPermission> permissions) {
List<String> restricted = new ArrayList<String>();
for (RepositoryModel repo : repositories) {
- if (repo.accessRestriction.exceeds(AccessRestrictionType.NONE)) {
- restricted.add(repo.name);
+ // exclude Owner or personal repositories
+ if (!repo.isOwner(username) && !repo.isUsersPersonalRepository(username)) {
+ if (repo.accessRestriction.exceeds(AccessRestrictionType.NONE)
+ && repo.authorizationControl.equals(AuthorizationControl.NAMED)) {
+ restricted.add(repo.name);
+ }
}
}
StringUtils.sortRepositorynames(restricted);
@@ -356,15 +362,15 @@ public class EditUserDialog extends JDialog { list.add("[^~].*");
String lastProject = null;
for (String repo : restricted) {
- String projectPath = StringUtils.getFirstPathElement(repo);
+ String projectPath = StringUtils.getFirstPathElement(repo).toLowerCase();
if (lastProject == null || !lastProject.equalsIgnoreCase(projectPath)) {
lastProject = projectPath;
if (!StringUtils.isEmpty(projectPath)) {
// regex for all repositories within a project
list.add(projectPath + "/.*");
}
- list.add(repo);
}
+ list.add(repo);
}
// remove repositories for which user already has a permission
@@ -372,7 +378,7 @@ public class EditUserDialog extends JDialog { permissions = new ArrayList<RegistrantAccessPermission>();
} else {
for (RegistrantAccessPermission rp : permissions) {
- list.remove(rp.registrant);
+ list.remove(rp.registrant.toLowerCase());
}
}
repositoryPalette.setObjects(list, permissions);
diff --git a/src/com/gitblit/client/GitblitClient.java b/src/com/gitblit/client/GitblitClient.java index 4620fefa..b7047d7f 100644 --- a/src/com/gitblit/client/GitblitClient.java +++ b/src/com/gitblit/client/GitblitClient.java @@ -31,6 +31,7 @@ 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;
@@ -340,6 +341,7 @@ public class GitblitClient implements Serializable { List<UserModel> users = RpcUtils.getUsers(url, account, password);
allUsers.clear();
allUsers.addAll(users);
+ Collections.sort(users);
return allUsers;
}
@@ -347,6 +349,7 @@ public class GitblitClient implements Serializable { List<TeamModel> teams = RpcUtils.getTeams(url, account, password);
allTeams.clear();
allTeams.addAll(teams);
+ Collections.sort(teams);
return allTeams;
}
@@ -475,6 +478,15 @@ public class GitblitClient implements Serializable { public List<UserModel> getUsers() {
return allUsers;
}
+
+ public UserModel getUser(String username) {
+ for (UserModel user : getUsers()) {
+ if (user.username.equalsIgnoreCase(username)) {
+ return user;
+ }
+ }
+ return null;
+ }
public List<String> getUsernames() {
List<String> usernames = new ArrayList<String>();
@@ -496,15 +508,38 @@ public class GitblitClient implements Serializable { }
public List<RegistrantAccessPermission> getUserAccessPermissions(RepositoryModel repository) {
- List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>();
- for (UserModel user : allUsers) {
+ Set<RegistrantAccessPermission> list = new LinkedHashSet<RegistrantAccessPermission>();
+ if (!StringUtils.isEmpty(repository.owner)) {
+ UserModel owner = getUser(repository.owner);
+ if (owner != null) {
+ list.add(new RegistrantAccessPermission(owner.username, AccessPermission.REWIND, PermissionType.OWNER, RegistrantType.USER, false));
+ }
+ }
+ if (repository.isPersonalRepository()) {
+ UserModel owner = getUser(repository.projectPath.substring(1));
+ if (owner != null) {
+ list.add(new RegistrantAccessPermission(owner.username, AccessPermission.REWIND, PermissionType.OWNER, RegistrantType.USER, false));
+ }
+ }
+ for (UserModel user : getUsers()) {
if (user.hasRepositoryPermission(repository.name)) {
AccessPermission ap = user.getRepositoryPermission(repository);
- boolean isExplicit = user.hasExplicitRepositoryPermission(repository.name);
- list.add(new RegistrantAccessPermission(user.username, ap, isExplicit, RegistrantType.USER));
+ PermissionType pType = PermissionType.REGEX;
+ boolean editable = false;
+ if (repository.isOwner(user.username)) {
+ pType = PermissionType.OWNER;
+ } else if (repository.isUsersPersonalRepository(user.username)) {
+ pType = PermissionType.OWNER;
+ } else if (user.hasExplicitRepositoryPermission(repository.name)) {
+ pType = PermissionType.EXPLICIT;
+ editable = true;
+ }
+ list.add(new RegistrantAccessPermission(user.username, ap, pType, RegistrantType.USER, editable));
}
}
- return list;
+ List<RegistrantAccessPermission> raps = new ArrayList<RegistrantAccessPermission>(list);
+ Collections.sort(raps);
+ return raps;
}
public boolean setUserAccessPermissions(RepositoryModel repository, List<RegistrantAccessPermission> permissions) throws IOException {
@@ -539,10 +574,16 @@ public class GitblitClient implements Serializable { for (TeamModel team : allTeams) {
if (team.hasRepositoryPermission(repository.name)) {
AccessPermission ap = team.getRepositoryPermission(repository);
- boolean isExplicit = team.hasExplicitRepositoryPermission(repository.name);
- list.add(new RegistrantAccessPermission(team.name, ap, isExplicit, RegistrantType.TEAM));
+ PermissionType pType = PermissionType.REGEX;
+ boolean editable = false;
+ if (team.hasExplicitRepositoryPermission(repository.name)) {
+ pType = PermissionType.EXPLICIT;
+ editable = true;
+ }
+ list.add(new RegistrantAccessPermission(team.name, ap, pType, RegistrantType.TEAM, editable));
}
}
+ Collections.sort(list);
return list;
}
@@ -566,6 +607,15 @@ public class GitblitClient implements Serializable { public List<RepositoryModel> getRepositories() {
return allRepositories;
}
+
+ public RepositoryModel getRepository(String name) {
+ for (RepositoryModel repository : allRepositories) {
+ if (repository.name.equalsIgnoreCase(name)) {
+ return repository;
+ }
+ }
+ return null;
+ }
public boolean createRepository(RepositoryModel repository, List<RegistrantAccessPermission> userPermissions)
throws IOException {
diff --git a/src/com/gitblit/client/RegistrantPermissionsPanel.java b/src/com/gitblit/client/RegistrantPermissionsPanel.java index 4ea173fc..b8ab9399 100644 --- a/src/com/gitblit/client/RegistrantPermissionsPanel.java +++ b/src/com/gitblit/client/RegistrantPermissionsPanel.java @@ -33,7 +33,10 @@ import javax.swing.SwingConstants; import javax.swing.table.DefaultTableCellRenderer;
import com.gitblit.Constants.AccessPermission;
+import com.gitblit.Constants.PermissionType;
+import com.gitblit.Constants.RegistrantType;
import com.gitblit.models.RegistrantAccessPermission;
+import com.gitblit.utils.StringUtils;
public class RegistrantPermissionsPanel extends JPanel {
@@ -53,16 +56,19 @@ public class RegistrantPermissionsPanel extends JPanel { private JPanel addPanel;
- public RegistrantPermissionsPanel() {
+ public RegistrantPermissionsPanel(final RegistrantType registrantType) {
super(new BorderLayout(5, 5));
tableModel = new RegistrantPermissionsTableModel();
- permissionsTable = new JTable(tableModel);
+ permissionsTable = Utils.newTable(tableModel, Utils.DATE_FORMAT);
+ permissionsTable.setModel(tableModel);
permissionsTable.setPreferredScrollableViewportSize(new Dimension(400, 150));
JScrollPane jsp = new JScrollPane(permissionsTable);
add(jsp, BorderLayout.CENTER);
+ permissionsTable.getColumnModel().getColumn(RegistrantPermissionsTableModel.Columns.Registrant.ordinal())
+ .setCellRenderer(new NameRenderer());
permissionsTable.getColumnModel().getColumn(RegistrantPermissionsTableModel.Columns.Type.ordinal())
- .setCellRenderer(new RegexRenderer());
+ .setCellRenderer(new PermissionTypeRenderer());
permissionsTable.getColumnModel().getColumn(RegistrantPermissionsTableModel.Columns.Permission.ordinal())
.setCellEditor(new AccessPermissionEditor());
@@ -79,9 +85,15 @@ public class RegistrantPermissionsPanel extends JPanel { return;
}
- RegistrantAccessPermission rp = new RegistrantAccessPermission();
+ RegistrantAccessPermission rp = new RegistrantAccessPermission(registrantType);
rp.registrant = registrantSelector.getSelectedItem().toString();
rp.permission = (AccessPermission) permissionSelector.getSelectedItem();
+ if (StringUtils.findInvalidCharacter(rp.registrant) != null) {
+ rp.permissionType = PermissionType.REGEX;
+ } else {
+ rp.permissionType = PermissionType.EXPLICIT;
+ }
+
tableModel.permissions.add(rp);
registrantModel.removeElement(rp.registrant);
@@ -103,7 +115,10 @@ public class RegistrantPermissionsPanel extends JPanel { @Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
- permissionsTable.setEnabled(false);
+ permissionsTable.setEnabled(enabled);
+ registrantSelector.setEnabled(enabled);
+ permissionSelector.setEnabled(enabled);
+ addButton.setEnabled(enabled);
}
public void setObjects(List<String> registrants, List<RegistrantAccessPermission> permissions) {
@@ -117,7 +132,11 @@ public class RegistrantPermissionsPanel extends JPanel { permissions = new ArrayList<RegistrantAccessPermission>();
}
for (RegistrantAccessPermission rp : permissions) {
- filtered.remove(rp.registrant);
+ if (rp.isEditable) {
+ // only remove editable duplicates
+ // this allows for specifying an explicit permission
+ filtered.remove(rp.registrant);
+ }
}
for (String registrant : filtered) {
registrantModel.addElement(registrant);
@@ -138,30 +157,35 @@ public class RegistrantPermissionsPanel extends JPanel { private static final long serialVersionUID = 1L;
public AccessPermissionEditor() {
- super(new JComboBox(AccessPermission.values()));
+ super(new JComboBox(AccessPermission.values()));
}
}
- private class RegexRenderer extends DefaultTableCellRenderer {
+ private class PermissionTypeRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L;
- public RegexRenderer() {
+ public PermissionTypeRenderer() {
super();
setHorizontalAlignment(SwingConstants.CENTER);
}
@Override
protected void setValue(Object value) {
- boolean isExplicit = (Boolean) value;
- if (isExplicit) {
- // explicit permission
- setText("");
- setToolTipText(null);
- } else {
- // regex matched permission
+ PermissionType pType = (PermissionType) value;
+ switch (pType) {
+ case OWNER:
+ setText("owner");
+ setToolTipText(Translation.get("gb.ownerPermission"));
+ break;
+ case REGEX:
setText("regex");
setToolTipText(Translation.get("gb.regexPermission"));
+ break;
+ default:
+ setText("");
+ setToolTipText(null);
+ break;
}
}
}
diff --git a/src/com/gitblit/client/RegistrantPermissionsTableModel.java b/src/com/gitblit/client/RegistrantPermissionsTableModel.java index fcd9c8b4..9ed8db4a 100644 --- a/src/com/gitblit/client/RegistrantPermissionsTableModel.java +++ b/src/com/gitblit/client/RegistrantPermissionsTableModel.java @@ -104,7 +104,7 @@ public class RegistrantPermissionsTableModel extends AbstractTableModel { // and therefore can not be directly manipulated unless the current
// object is the source of the regex (i.e. a user or team with explicit
// regex definition)
- return permissions.get(rowIndex).isExplicit;
+ return permissions.get(rowIndex).isEditable;
}
return false;
}
@@ -117,7 +117,7 @@ public class RegistrantPermissionsTableModel extends AbstractTableModel { case Registrant:
return rp.registrant;
case Type:
- return rp.isExplicit;
+ return rp.permissionType;
case Permission:
return rp.permission;
}
diff --git a/src/com/gitblit/client/UsersPanel.java b/src/com/gitblit/client/UsersPanel.java index 9fcad7bc..cd571b26 100644 --- a/src/com/gitblit/client/UsersPanel.java +++ b/src/com/gitblit/client/UsersPanel.java @@ -40,7 +40,9 @@ import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableRowSorter;
+import com.gitblit.Constants.PermissionType;
import com.gitblit.Constants.RpcRequest;
+import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
@@ -309,6 +311,21 @@ public abstract class UsersPanel extends JPanel { gitblit.getSettings());
dialog.setLocationRelativeTo(UsersPanel.this);
dialog.setUsers(gitblit.getUsers());
+
+ List<RegistrantAccessPermission> permissions = user.getRepositoryPermissions();
+ for (RegistrantAccessPermission permission : permissions) {
+ if (permission.isEditable && 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.
+ boolean isOwner = gitblit.getRepository(permission.registrant).isOwner(user.username);
+ if (isOwner) {
+ permission.permissionType = PermissionType.OWNER;
+ permission.isEditable = false;
+ }
+ }
+ }
+
dialog.setRepositories(gitblit.getRepositories(), user.getRepositoryPermissions());
dialog.setTeams(gitblit.getTeams(), user.teams == null ? null : new ArrayList<TeamModel>(
user.teams));
diff --git a/src/com/gitblit/models/RegistrantAccessPermission.java b/src/com/gitblit/models/RegistrantAccessPermission.java index 4a560d43..7346d310 100644 --- a/src/com/gitblit/models/RegistrantAccessPermission.java +++ b/src/com/gitblit/models/RegistrantAccessPermission.java @@ -18,6 +18,7 @@ package com.gitblit.models; import java.io.Serializable; import com.gitblit.Constants.AccessPermission; +import com.gitblit.Constants.PermissionType; import com.gitblit.Constants.RegistrantType; import com.gitblit.utils.StringUtils; @@ -32,23 +33,27 @@ public class RegistrantAccessPermission implements Serializable, Comparable<Regi public String registrant; public AccessPermission permission; - public RegistrantType type; - public boolean isExplicit; + public RegistrantType registrantType; + public PermissionType permissionType; + public boolean isEditable; - public RegistrantAccessPermission() { - isExplicit = true; + public RegistrantAccessPermission(RegistrantType registrantType) { + this.registrantType = registrantType; + this.permissionType = PermissionType.EXPLICIT; + this.isEditable = true; } - public RegistrantAccessPermission(String registrant, AccessPermission permission, boolean isExplicit, RegistrantType type) { + public RegistrantAccessPermission(String registrant, AccessPermission permission, PermissionType permissionType, RegistrantType registrantType, boolean isEditable) { this.registrant = registrant; this.permission = permission; - this.isExplicit = isExplicit; - this.type = type; + this.permissionType = permissionType; + this.registrantType = registrantType; + this.isEditable = isEditable; } @Override public int compareTo(RegistrantAccessPermission p) { - switch (type) { + switch (registrantType) { case REPOSITORY: return StringUtils.compareRepositoryNames(registrant, p.registrant); default: @@ -57,6 +62,21 @@ public class RegistrantAccessPermission implements Serializable, Comparable<Regi } @Override + public int hashCode() { + return registrant.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof RegistrantAccessPermission) { + RegistrantAccessPermission p = (RegistrantAccessPermission) o; + return registrant.equals(p.registrant); + } + + return false; + } + + @Override public String toString() { return permission.asRole(registrant); } diff --git a/src/com/gitblit/models/TeamModel.java b/src/com/gitblit/models/TeamModel.java index 7d557db9..e5e3b097 100644 --- a/src/com/gitblit/models/TeamModel.java +++ b/src/com/gitblit/models/TeamModel.java @@ -27,6 +27,7 @@ import java.util.Set; import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.PermissionType;
import com.gitblit.Constants.RegistrantType;
import com.gitblit.Constants.Unused;
import com.gitblit.utils.StringUtils;
@@ -98,7 +99,14 @@ public class TeamModel implements Serializable, Comparable<TeamModel> { public List<RegistrantAccessPermission> getRepositoryPermissions() {
List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>();
for (Map.Entry<String, AccessPermission> entry : permissions.entrySet()) {
- list.add(new RegistrantAccessPermission(entry.getKey(), entry.getValue(), true, RegistrantType.REPOSITORY));
+ String registrant = entry.getKey();
+ boolean editable = true;
+ PermissionType pType = PermissionType.EXPLICIT;
+ if (StringUtils.findInvalidCharacter(registrant) != null) {
+ // a regex will have at least 1 invalid character
+ pType = PermissionType.REGEX;
+ }
+ list.add(new RegistrantAccessPermission(registrant, entry.getValue(), pType, RegistrantType.REPOSITORY, editable));
}
Collections.sort(list);
return list;
diff --git a/src/com/gitblit/models/UserModel.java b/src/com/gitblit/models/UserModel.java index d7bc2935..22f250cc 100644 --- a/src/com/gitblit/models/UserModel.java +++ b/src/com/gitblit/models/UserModel.java @@ -28,6 +28,7 @@ import java.util.Set; 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.Constants.Unused;
import com.gitblit.utils.ArrayUtils;
@@ -137,7 +138,17 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel> public List<RegistrantAccessPermission> getRepositoryPermissions() {
List<RegistrantAccessPermission> list = new ArrayList<RegistrantAccessPermission>();
for (Map.Entry<String, AccessPermission> entry : permissions.entrySet()) {
- list.add(new RegistrantAccessPermission(entry.getKey(), entry.getValue(), true, RegistrantType.REPOSITORY));
+ String registrant = entry.getKey();
+ boolean editable = true;
+ PermissionType pType = PermissionType.EXPLICIT;
+ if (isMyPersonalRepository(registrant)) {
+ pType = PermissionType.OWNER;
+ editable = false;
+ } else if (StringUtils.findInvalidCharacter(registrant) != null) {
+ // a regex will have at least 1 invalid character
+ pType = PermissionType.REGEX;
+ }
+ list.add(new RegistrantAccessPermission(registrant, entry.getValue(), pType, RegistrantType.REPOSITORY, editable));
}
Collections.sort(list);
return list;
@@ -494,4 +505,9 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel> // Default UserModel doesn't implement branch-level security. Other Realms (i.e. Gerrit) may override this method.
return hasRepositoryPermission(repositoryName);
}
+
+ public boolean isMyPersonalRepository(String repository) {
+ String projectPath = StringUtils.getFirstPathElement(repository);
+ return !StringUtils.isEmpty(projectPath) && projectPath.equalsIgnoreCase("~" + username);
+ }
}
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties index 62e4817f..c6ceb9fd 100644 --- a/src/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/com/gitblit/wicket/GitBlitWebApp.properties @@ -311,8 +311,8 @@ gb.duration.months = {0} months gb.duration.oneYear = 1 year
gb.duration.years = {0} years
gb.authorizationControl = authorization control
-gb.allowAuthenticatedDescription = grant restricted access to all authenticated users
-gb.allowNamedDescription = grant restricted access to named users or teams
+gb.allowAuthenticatedDescription = grant RW+ permission to all authenticated users
+gb.allowNamedDescription = grant fine-grained permissions to named users or teams
gb.markdownFailure = Failed to parse Markdown content!
gb.clearCache = clear cache
gb.projects = projects
@@ -364,3 +364,4 @@ gb.gcPeriod = GC period gb.gcPeriodDescription = duration between garbage collections
gb.gcThreshold = GC threshold
gb.gcThresholdDescription = minimum total size of loose objects to trigger early garbage collection
+gb.ownerPermission = repository owner
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/BasePage.java b/src/com/gitblit/wicket/pages/BasePage.java index dcca3619..ceeb9120 100644 --- a/src/com/gitblit/wicket/pages/BasePage.java +++ b/src/com/gitblit/wicket/pages/BasePage.java @@ -55,6 +55,7 @@ import org.slf4j.LoggerFactory; import com.gitblit.Constants;
import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.Constants.FederationStrategy;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
@@ -255,6 +256,21 @@ public abstract class BasePage extends WebPage { }
return map;
}
+
+ protected Map<AuthorizationControl, String> getAuthorizationControls() {
+ Map<AuthorizationControl, String> map = new LinkedHashMap<AuthorizationControl, String>();
+ for (AuthorizationControl type : AuthorizationControl.values()) {
+ switch (type) {
+ case AUTHENTICATED:
+ map.put(type, getString("gb.allowAuthenticatedDescription"));
+ break;
+ case NAMED:
+ map.put(type, getString("gb.allowNamedDescription"));
+ break;
+ }
+ }
+ return map;
+ }
protected TimeZone getTimeZone() {
return GitBlit.getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get()
diff --git a/src/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/com/gitblit/wicket/pages/EditRepositoryPage.html index 7bd896cf..638eae90 100644 --- a/src/com/gitblit/wicket/pages/EditRepositoryPage.html +++ b/src/com/gitblit/wicket/pages/EditRepositoryPage.html @@ -49,12 +49,7 @@ <tbody class="settings">
<tr><th><wicket:message key="gb.accessRestriction"></wicket:message></th><td class="edit"><select class="span4" wicket:id="accessRestriction" tabindex="15" /></td></tr>
<tr><th colspan="2"><hr/></th></tr>
- <tr><th><wicket:message key="gb.authorizationControl"></wicket:message></th><td style="padding:2px;">
- <wicket:container wicket:id="authorizationControl">
- <label class="radio"><input type="radio" wicket:id="allowAuthenticated" tabindex="16" /> <span class="help-inline"><wicket:message key="gb.allowAuthenticatedDescription"></wicket:message></span></label>
- <label class="radio"><input type="radio" wicket:id="allowNamed" tabindex="17" /> <span class="help-inline"><wicket:message key="gb.allowNamedDescription"></wicket:message></span></label>
- </wicket:container>
- </td></tr>
+ <tr><th><wicket:message key="gb.authorizationControl"></wicket:message></th><td style="padding:2px;"><span class="authorizationControl" wicket:id="authorizationControl"></span></td></tr>
<tr><th colspan="2"><hr/></th></tr>
<tr><th><wicket:message key="gb.isFrozen"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="isFrozen" tabindex="18" /> <span class="help-inline"><wicket:message key="gb.isFrozenDescription"></wicket:message></span></label></td></tr>
<tr><th><wicket:message key="gb.allowForks"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="allowForks" tabindex="19" /> <span class="help-inline"><wicket:message key="gb.allowForksDescription"></wicket:message></span></label></td></tr>
diff --git a/src/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/com/gitblit/wicket/pages/EditRepositoryPage.java index 1a2e63ce..58fdf66b 100644 --- a/src/com/gitblit/wicket/pages/EditRepositoryPage.java +++ b/src/com/gitblit/wicket/pages/EditRepositoryPage.java @@ -27,6 +27,9 @@ import java.util.Map; import java.util.Set;
import org.apache.wicket.PageParameters;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.behavior.SimpleAttributeModifier;
import org.apache.wicket.extensions.markup.html.form.palette.Palette;
import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -36,8 +39,7 @@ import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
-import org.apache.wicket.markup.html.form.Radio;
-import org.apache.wicket.markup.html.form.RadioGroup;
+import org.apache.wicket.markup.html.form.RadioChoice;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
@@ -51,6 +53,7 @@ import com.gitblit.Constants; import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.Constants.FederationStrategy;
+import com.gitblit.Constants.RegistrantType;
import com.gitblit.GitBlit;
import com.gitblit.GitBlitException;
import com.gitblit.Keys;
@@ -70,6 +73,8 @@ public class EditRepositoryPage extends RootSubPage { private final boolean isCreate;
private boolean isAdmin;
+
+ RepositoryModel repositoryModel;
private IModel<String> mailingLists;
@@ -97,6 +102,7 @@ public class EditRepositoryPage extends RootSubPage { setupPage(model);
setStatelessHint(false);
+ setOutputMarkupId(true);
}
public EditRepositoryPage(PageParameters params) {
@@ -107,9 +113,12 @@ public class EditRepositoryPage extends RootSubPage { RepositoryModel model = GitBlit.self().getRepositoryModel(name);
setupPage(model);
setStatelessHint(false);
+ setOutputMarkupId(true);
}
- protected void setupPage(final RepositoryModel repositoryModel) {
+ protected void setupPage(RepositoryModel model) {
+ this.repositoryModel = model;
+
// ensure this user can create or edit this repository
checkPermissions(repositoryModel);
@@ -145,10 +154,10 @@ public class EditRepositoryPage extends RootSubPage { final String oldName = repositoryModel.name;
- RegistrantPermissionsPanel usersPalette = new RegistrantPermissionsPanel("users",
- GitBlit.self().getAllUsernames(), repositoryUsers, getAccessPermissions());
- RegistrantPermissionsPanel teamsPalette = new RegistrantPermissionsPanel("teams",
- GitBlit.self().getAllTeamnames(), repositoryTeams, getAccessPermissions());
+ final RegistrantPermissionsPanel usersPalette = new RegistrantPermissionsPanel("users",
+ RegistrantType.USER, GitBlit.self().getAllUsernames(), repositoryUsers, getAccessPermissions());
+ final RegistrantPermissionsPanel teamsPalette = new RegistrantPermissionsPanel("teams",
+ RegistrantType.TEAM, GitBlit.self().getAllTeamnames(), repositoryTeams, getAccessPermissions());
// indexed local branches palette
List<String> allLocalBranches = new ArrayList<String>();
@@ -206,9 +215,9 @@ public class EditRepositoryPage extends RootSubPage { };
customFieldsListView.setReuseItems(true);
- CompoundPropertyModel<RepositoryModel> model = new CompoundPropertyModel<RepositoryModel>(
+ CompoundPropertyModel<RepositoryModel> rModel = new CompoundPropertyModel<RepositoryModel>(
repositoryModel);
- Form<RepositoryModel> form = new Form<RepositoryModel>("editForm", model) {
+ Form<RepositoryModel> form = new Form<RepositoryModel>("editForm", rModel) {
private static final long serialVersionUID = 1L;
@@ -366,8 +375,9 @@ public class EditRepositoryPage extends RootSubPage { form.add(new DropDownChoice<String>("owner", GitBlit.self().getAllUsernames())
.setEnabled(GitBlitWebSession.get().canAdmin()));
form.add(new CheckBox("allowForks"));
- form.add(new DropDownChoice<AccessRestrictionType>("accessRestriction", Arrays
- .asList(AccessRestrictionType.values()), new AccessRestrictionRenderer()));
+ DropDownChoice<AccessRestrictionType> accessRestriction = new DropDownChoice<AccessRestrictionType>("accessRestriction", Arrays
+ .asList(AccessRestrictionType.values()), new AccessRestrictionRenderer());
+ form.add(accessRestriction);
form.add(new CheckBox("isFrozen"));
// TODO enable origin definition
form.add(new TextField<String>("origin").setEnabled(false/* isCreate */));
@@ -403,12 +413,10 @@ public class EditRepositoryPage extends RootSubPage { form.add(new TextField<String>("mailingLists", mailingLists));
form.add(indexedBranchesPalette);
- RadioGroup<AuthorizationControl> group = new RadioGroup<AuthorizationControl>("authorizationControl");
- Radio<AuthorizationControl> allowAuthenticated = new Radio<AuthorizationControl>("allowAuthenticated", new Model<AuthorizationControl>(AuthorizationControl.AUTHENTICATED));
- Radio<AuthorizationControl> allowNamed = new Radio<AuthorizationControl>("allowNamed", new Model<AuthorizationControl>(AuthorizationControl.NAMED));
- group.add(allowAuthenticated);
- group.add(allowNamed);
- form.add(group);
+ List<AuthorizationControl> acList = Arrays.asList(AuthorizationControl.values());
+ final RadioChoice<AuthorizationControl> authorizationControl = new RadioChoice<Constants.AuthorizationControl>(
+ "authorizationControl", acList, new AuthorizationControlRenderer());
+ form.add(authorizationControl);
form.add(new CheckBox("verifyCommitter"));
@@ -425,7 +433,69 @@ public class EditRepositoryPage extends RootSubPage { WebMarkupContainer customFieldsSection = new WebMarkupContainer("customFieldsSection");
customFieldsSection.add(customFieldsListView);
form.add(customFieldsSection.setVisible(!GitBlit.getString(Keys.groovy.customFields, "").isEmpty()));
+
+ // initial enable/disable of permission controls
+ if (repositoryModel.accessRestriction.equals(AccessRestrictionType.NONE)) {
+ // anonymous everything, disable all controls
+ usersPalette.setEnabled(false);
+ teamsPalette.setEnabled(false);
+ authorizationControl.setEnabled(false);
+ } else {
+ // authenticated something
+ // enable authorization controls
+ authorizationControl.setEnabled(true);
+
+ boolean allowFineGrainedControls = repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED);
+ usersPalette.setEnabled(allowFineGrainedControls);
+ teamsPalette.setEnabled(allowFineGrainedControls);
+ }
+
+ accessRestriction.add(new AjaxFormComponentUpdatingBehavior("onchange") {
+
+ private static final long serialVersionUID = 1L;
+
+ protected void onUpdate(AjaxRequestTarget target) {
+ // enable/disable permissions panel based on access restriction
+ boolean allowAuthorizationControl = repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE);
+ authorizationControl.setEnabled(allowAuthorizationControl);
+
+ boolean allowFineGrainedControls = allowAuthorizationControl && repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED);
+ usersPalette.setEnabled(allowFineGrainedControls);
+ teamsPalette.setEnabled(allowFineGrainedControls);
+
+ if (allowFineGrainedControls) {
+ repositoryModel.authorizationControl = AuthorizationControl.NAMED;
+ }
+
+ target.addComponent(authorizationControl);
+ target.addComponent(usersPalette);
+ target.addComponent(teamsPalette);
+ }
+ });
+
+ authorizationControl.add(new AjaxFormChoiceComponentUpdatingBehavior() {
+
+ private static final long serialVersionUID = 1L;
+ protected void onUpdate(AjaxRequestTarget target) {
+ // enable/disable permissions panel based on access restriction
+ boolean allowAuthorizationControl = repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE);
+ authorizationControl.setEnabled(allowAuthorizationControl);
+
+ boolean allowFineGrainedControls = allowAuthorizationControl && repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED);
+ usersPalette.setEnabled(allowFineGrainedControls);
+ teamsPalette.setEnabled(allowFineGrainedControls);
+
+ if (allowFineGrainedControls) {
+ repositoryModel.authorizationControl = AuthorizationControl.NAMED;
+ }
+
+ target.addComponent(authorizationControl);
+ target.addComponent(usersPalette);
+ target.addComponent(teamsPalette);
+ }
+ });
+
form.add(new Button("save"));
Button cancel = new Button("cancel") {
private static final long serialVersionUID = 1L;
@@ -528,4 +598,25 @@ public class EditRepositoryPage extends RootSubPage { return Integer.toString(index);
}
}
+
+ private class AuthorizationControlRenderer implements IChoiceRenderer<AuthorizationControl> {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Map<AuthorizationControl, String> map;
+
+ public AuthorizationControlRenderer() {
+ map = getAuthorizationControls();
+ }
+
+ @Override
+ public String getDisplayValue(AuthorizationControl type) {
+ return map.get(type);
+ }
+
+ @Override
+ public String getIdValue(AuthorizationControl type, int index) {
+ return Integer.toString(index);
+ }
+ }
}
diff --git a/src/com/gitblit/wicket/pages/EditTeamPage.java b/src/com/gitblit/wicket/pages/EditTeamPage.java index 8908676e..8ced03c2 100644 --- a/src/com/gitblit/wicket/pages/EditTeamPage.java +++ b/src/com/gitblit/wicket/pages/EditTeamPage.java @@ -38,6 +38,7 @@ import org.apache.wicket.model.util.ListModel; import com.gitblit.GitBlit;
import com.gitblit.GitBlitException;
+import com.gitblit.Constants.RegistrantType;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.TeamModel;
import com.gitblit.utils.StringUtils;
@@ -60,6 +61,7 @@ public class EditTeamPage extends RootSubPage { isCreate = true;
setupPage(new TeamModel(""));
setStatelessHint(false);
+ setOutputMarkupId(true);
}
public EditTeamPage(PageParameters params) {
@@ -70,6 +72,7 @@ public class EditTeamPage extends RootSubPage { TeamModel model = GitBlit.self().getTeamModel(name);
setupPage(model);
setStatelessHint(false);
+ setOutputMarkupId(true);
}
protected void setupPage(final TeamModel teamModel) {
@@ -81,7 +84,7 @@ public class EditTeamPage extends RootSubPage { CompoundPropertyModel<TeamModel> model = new CompoundPropertyModel<TeamModel>(teamModel);
- List<String> repos = getAccessRestrictedRepositoryList(true);
+ List<String> repos = getAccessRestrictedRepositoryList(true, null);
List<String> teamUsers = new ArrayList<String>(teamModel.users);
Collections.sort(teamUsers);
@@ -215,7 +218,8 @@ public class EditTeamPage extends RootSubPage { : StringUtils.flattenStrings(teamModel.mailingLists, " "));
form.add(new TextField<String>("mailingLists", mailingLists));
- form.add(new RegistrantPermissionsPanel("repositories", repos, permissions, getAccessPermissions()));
+ form.add(new RegistrantPermissionsPanel("repositories", RegistrantType.REPOSITORY,
+ repos, permissions, getAccessPermissions()));
form.add(preReceivePalette);
form.add(new BulletListPanel("inheritedPreReceive", "inherited", GitBlit.self()
.getPreReceiveScriptsInherited(null)));
diff --git a/src/com/gitblit/wicket/pages/EditUserPage.java b/src/com/gitblit/wicket/pages/EditUserPage.java index a165305d..19d297b1 100644 --- a/src/com/gitblit/wicket/pages/EditUserPage.java +++ b/src/com/gitblit/wicket/pages/EditUserPage.java @@ -37,6 +37,8 @@ import org.apache.wicket.model.util.ListModel; import com.gitblit.GitBlit;
import com.gitblit.GitBlitException;
import com.gitblit.Keys;
+import com.gitblit.Constants.PermissionType;
+import com.gitblit.Constants.RegistrantType;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
@@ -61,6 +63,7 @@ public class EditUserPage extends RootSubPage { isCreate = true;
setupPage(new UserModel(""));
setStatelessHint(false);
+ setOutputMarkupId(true);
}
public EditUserPage(PageParameters params) {
@@ -71,6 +74,7 @@ public class EditUserPage extends RootSubPage { UserModel model = GitBlit.self().getUserModel(name);
setupPage(model);
setStatelessHint(false);
+ setOutputMarkupId(true);
}
protected void setupPage(final UserModel userModel) {
@@ -85,7 +89,7 @@ public class EditUserPage extends RootSubPage { CompoundPropertyModel<UserModel> model = new CompoundPropertyModel<UserModel>(userModel);
// build list of projects including all repositories wildcards
- List<String> repos = getAccessRestrictedRepositoryList(true);
+ List<String> repos = getAccessRestrictedRepositoryList(true, userModel);
List<String> userTeams = new ArrayList<String>();
for (TeamModel team : userModel.teams) {
@@ -95,6 +99,18 @@ public class EditUserPage extends RootSubPage { final String oldName = userModel.username;
final List<RegistrantAccessPermission> permissions = userModel.getRepositoryPermissions();
+ for (RegistrantAccessPermission permission : permissions) {
+ if (permission.isEditable && 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.
+ boolean isOwner = GitBlit.self().getRepositoryModel(permission.registrant).isOwner(oldName);
+ if (isOwner) {
+ permission.permissionType = PermissionType.OWNER;
+ permission.isEditable = false;
+ }
+ }
+ }
final Palette<String> teams = new Palette<String>("teams", new ListModel<String>(
new ArrayList<String>(userTeams)), new CollectionModel<String>(GitBlit.self()
@@ -228,7 +244,7 @@ public class EditUserPage extends RootSubPage { form.add(new CheckBox("canFork"));
form.add(new CheckBox("canCreate"));
form.add(new CheckBox("excludeFromFederation"));
- form.add(new RegistrantPermissionsPanel("repositories", repos, permissions, getAccessPermissions()));
+ form.add(new RegistrantPermissionsPanel("repositories", RegistrantType.REPOSITORY, repos, permissions, getAccessPermissions()));
form.add(teams.setEnabled(editTeams));
form.add(new Button("save"));
diff --git a/src/com/gitblit/wicket/pages/RootSubPage.java b/src/com/gitblit/wicket/pages/RootSubPage.java index 30d296ed..891c892a 100644 --- a/src/com/gitblit/wicket/pages/RootSubPage.java +++ b/src/com/gitblit/wicket/pages/RootSubPage.java @@ -21,9 +21,11 @@ import java.util.List; import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.basic.Label;
-import com.gitblit.GitBlit;
import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
+import com.gitblit.GitBlit;
import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
/**
@@ -52,7 +54,7 @@ public abstract class RootSubPage extends RootPage { super.setupPage("", pageName);
}
- protected List<String> getAccessRestrictedRepositoryList(boolean includeWildcards) {
+ protected List<String> getAccessRestrictedRepositoryList(boolean includeWildcards, UserModel user) {
// build list of access-restricted projects
String lastProject = null;
List<String> repos = new ArrayList<String>();
@@ -62,19 +64,26 @@ public abstract class RootSubPage extends RootPage { // all repositories excluding personal repositories
repos.add("[^~].*");
}
+
for (String repo : GitBlit.self().getRepositoryList()) {
RepositoryModel repositoryModel = GitBlit.self().getRepositoryModel(repo);
- if (repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE)) {
+ if (repositoryModel.accessRestriction.exceeds(AccessRestrictionType.NONE)
+ && repositoryModel.authorizationControl.equals(AuthorizationControl.NAMED)) {
+ if (user != null &&
+ (repositoryModel.isOwner(user.username) || repositoryModel.isUsersPersonalRepository(user.username))) {
+ // exclude Owner or personal repositories
+ continue;
+ }
if (includeWildcards) {
if (lastProject == null || !lastProject.equalsIgnoreCase(repositoryModel.projectPath)) {
- lastProject = repositoryModel.projectPath;
+ lastProject = repositoryModel.projectPath.toLowerCase();
if (!StringUtils.isEmpty(repositoryModel.projectPath)) {
// regex for all repositories within a project
repos.add(repositoryModel.projectPath + "/.*");
}
}
}
- repos.add(repo);
+ repos.add(repo.toLowerCase());
}
}
return repos;
diff --git a/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html b/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html index 4c8c4efd..31f0b6be 100644 --- a/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html +++ b/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.html @@ -9,7 +9,7 @@ <div 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="span2"><span class="label label-info" wicket:id="regex">[regex]</span></div> <select class="input-medium" wicket:id="permission"></select>
+ <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="span2"><span class="label" wicket:id="pType">[permission type]</span></div> <select class="input-medium" wicket:id="permission"></select>
</div>
</div>
diff --git a/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java b/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java index b6ed890f..27e48fbe 100644 --- a/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java +++ b/src/com/gitblit/wicket/panels/RegistrantPermissionsPanel.java @@ -36,6 +36,7 @@ import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.model.IModel; import com.gitblit.Constants.AccessPermission; +import com.gitblit.Constants.PermissionType; import com.gitblit.Constants.RegistrantType; import com.gitblit.models.RegistrantAccessPermission; import com.gitblit.utils.DeepCopier; @@ -52,8 +53,9 @@ public class RegistrantPermissionsPanel extends BasePanel { private static final long serialVersionUID = 1L; - public RegistrantPermissionsPanel(String wicketId, List<String> allRegistrants, final List<RegistrantAccessPermission> permissions, final Map<AccessPermission, String> translations) { + 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 RefreshingView<RegistrantAccessPermission> dataView = new RefreshingView<RegistrantAccessPermission>("permissionRow") { @@ -80,22 +82,40 @@ public class RegistrantPermissionsPanel extends BasePanel { public void populateItem(final Item<RegistrantAccessPermission> item) { final RegistrantAccessPermission entry = item.getModelObject(); - if (RegistrantType.REPOSITORY.equals(entry.type)) { - // repository, strip .git and show swatch + if (RegistrantType.REPOSITORY.equals(entry.registrantType)) { String repoName = StringUtils.stripDotGit(entry.registrant); - Label registrant = new Label("registrant", repoName); - WicketUtils.setCssClass(registrant, "repositorySwatch"); - WicketUtils.setCssBackground(registrant, repoName); - item.add(registrant); + if (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); + } else { + // likely a regex + Label label = new Label("registrant", entry.registrant); + WicketUtils.setCssStyle(label, "font-weight: bold;"); + item.add(label); + } } else { - item.add(new Label("registrant", entry.registrant)); + // user or team + Label label = new Label("registrant", entry.registrant); + WicketUtils.setCssStyle(label, "font-weight: bold;"); + item.add(label); } - if (entry.isExplicit) { - item.add(new Label("regex", "").setVisible(false)); - } else { - Label regex = new Label("regex", "regex"); + switch (entry.permissionType) { + case OWNER: + Label owner = new Label("pType", "owner"); + WicketUtils.setHtmlTooltip(owner, getString("gb.ownerPermission")); + item.add(owner); + break; + case REGEX: + Label regex = new Label("pType", "regex"); WicketUtils.setHtmlTooltip(regex, getString("gb.regexPermission")); item.add(regex); + break; + default: + item.add(new Label("pType", "").setVisible(false)); + break; } // use ajax to get immediate update of permission level change @@ -106,8 +126,9 @@ public class RegistrantPermissionsPanel extends BasePanel { // only allow changing an explicitly defined permission // this is designed to prevent changing a regex permission in // a repository - permissionChoice.setEnabled(entry.isExplicit); - if (entry.isExplicit) { + permissionChoice.setEnabled(entry.isEditable); + permissionChoice.setOutputMarkupId(true); + if (entry.isEditable) { permissionChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") { private static final long serialVersionUID = 1L; @@ -127,11 +148,15 @@ public class RegistrantPermissionsPanel extends BasePanel { // filter out registrants we already have permissions for final List<String> registrants = new ArrayList<String>(allRegistrants); for (RegistrantAccessPermission rp : permissions) { - registrants.remove(rp.registrant); + if (rp.isEditable) { + // only remove editable duplicates + // this allows for specifying an explicit permission + registrants.remove(rp.registrant); + } } // add new permission form - IModel<RegistrantAccessPermission> addPermissionModel = new CompoundPropertyModel<RegistrantAccessPermission>(new RegistrantAccessPermission()); + IModel<RegistrantAccessPermission> addPermissionModel = new CompoundPropertyModel<RegistrantAccessPermission>(new RegistrantAccessPermission(registrantType)); Form<RegistrantAccessPermission> addPermissionForm = new Form<RegistrantAccessPermission>("addPermissionForm", addPermissionModel); addPermissionForm.add(new DropDownChoice<String>("registrant", registrants)); addPermissionForm.add(new DropDownChoice<AccessPermission>("permission", Arrays @@ -144,7 +169,11 @@ public class RegistrantPermissionsPanel extends BasePanel { protected void onSubmit(AjaxRequestTarget target, Form<?> form) { // add permission to our list RegistrantAccessPermission rp = (RegistrantAccessPermission) form.getModel().getObject(); - permissions.add(DeepCopier.copy(rp)); + RegistrantAccessPermission copy = DeepCopier.copy(rp); + if (StringUtils.findInvalidCharacter(copy.registrant) != null) { + copy.permissionType = PermissionType.REGEX; + } + permissions.add(copy); // remove registrant from available choices registrants.remove(rp.registrant); @@ -159,6 +188,12 @@ public class RegistrantPermissionsPanel extends BasePanel { add(addPermissionForm.setVisible(registrants.size() > 0)); } + protected boolean getStatelessHint() + { + return false; + } + + private class AccessPermissionRenderer implements IChoiceRenderer<AccessPermission> { private static final long serialVersionUID = 1L; diff --git a/tests/com/gitblit/tests/RpcTests.java b/tests/com/gitblit/tests/RpcTests.java index 0be2e02a..3df0ff8e 100644 --- a/tests/com/gitblit/tests/RpcTests.java +++ b/tests/com/gitblit/tests/RpcTests.java @@ -35,6 +35,7 @@ import org.junit.Test; 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.UnauthorizedException;
import com.gitblit.Keys;
@@ -199,7 +200,7 @@ public class RpcTests { List<RegistrantAccessPermission> permissions = RpcUtils.getRepositoryMemberPermissions(retrievedRepository, url, account,
password.toCharArray());
assertEquals("Membership permissions is not empty!", 0, permissions.size());
- permissions.add(new RegistrantAccessPermission(testMember.username, AccessPermission.PUSH, true, RegistrantType.USER));
+ permissions.add(new RegistrantAccessPermission(testMember.username, AccessPermission.PUSH, PermissionType.EXPLICIT, RegistrantType.USER, true));
assertTrue(
"Failed to set member permissions!",
RpcUtils.setRepositoryMemberPermissions(retrievedRepository, permissions, url, account,
@@ -288,7 +289,7 @@ public class RpcTests { // set no teams
List<RegistrantAccessPermission> permissions = new ArrayList<RegistrantAccessPermission>();
for (String team : helloworldTeams) {
- permissions.add(new RegistrantAccessPermission(team, AccessPermission.NONE, true, RegistrantType.TEAM));
+ permissions.add(new RegistrantAccessPermission(team, AccessPermission.NONE, PermissionType.EXPLICIT, RegistrantType.TEAM, true));
}
assertTrue(RpcUtils.setRepositoryTeamPermissions(helloworld, permissions, url, account,
password.toCharArray()));
|