summaryrefslogtreecommitdiffstats
path: root/src/com/gitblit
diff options
context:
space:
mode:
authorJames Moger <james.moger@gitblit.com>2011-12-13 08:37:02 -0500
committerJames Moger <james.moger@gitblit.com>2011-12-13 08:37:02 -0500
commitf08aab5c5e632431635e73b47b6096dc47243755 (patch)
tree577b6ec24db75a4d21dbc5ad3a70c44a878a7e62 /src/com/gitblit
parent82df524570e7bf27953b14f4797ff04daf89cc3a (diff)
downloadgitblit-f08aab5c5e632431635e73b47b6096dc47243755.tar.gz
gitblit-f08aab5c5e632431635e73b47b6096dc47243755.zip
Teams JSON-RPC support
Diffstat (limited to 'src/com/gitblit')
-rw-r--r--src/com/gitblit/Constants.java10
-rw-r--r--src/com/gitblit/RpcFilter.java2
-rw-r--r--src/com/gitblit/RpcServlet.java57
-rw-r--r--src/com/gitblit/client/EditRepositoryDialog.java31
-rw-r--r--src/com/gitblit/client/EditTeamDialog.java269
-rw-r--r--src/com/gitblit/client/EditUserDialog.java66
-rw-r--r--src/com/gitblit/client/GitblitClient.java93
-rw-r--r--src/com/gitblit/client/GitblitPanel.java44
-rw-r--r--src/com/gitblit/client/RepositoriesPanel.java22
-rw-r--r--src/com/gitblit/client/TeamsPanel.java378
-rw-r--r--src/com/gitblit/client/TeamsTableModel.java105
-rw-r--r--src/com/gitblit/client/UsersPanel.java38
-rw-r--r--src/com/gitblit/client/UsersTableModel.java13
-rw-r--r--src/com/gitblit/utils/RpcUtils.java130
14 files changed, 1215 insertions, 43 deletions
diff --git a/src/com/gitblit/Constants.java b/src/com/gitblit/Constants.java
index a2b9eebc..32799808 100644
--- a/src/com/gitblit/Constants.java
+++ b/src/com/gitblit/Constants.java
@@ -203,10 +203,12 @@ public class Constants {
public static enum RpcRequest {
// Order is important here. anything above LIST_SETTINGS requires
// administrator privileges and web.allowRpcManagement.
- LIST_REPOSITORIES, LIST_BRANCHES, LIST_SETTINGS, CREATE_REPOSITORY, EDIT_REPOSITORY,
- DELETE_REPOSITORY, LIST_USERS, CREATE_USER, EDIT_USER, DELETE_USER,
- LIST_REPOSITORY_MEMBERS, SET_REPOSITORY_MEMBERS, LIST_FEDERATION_REGISTRATIONS,
- LIST_FEDERATION_RESULTS, LIST_FEDERATION_PROPOSALS, LIST_FEDERATION_SETS,
+ GET_PROTOCOL, LIST_REPOSITORIES, LIST_BRANCHES, LIST_SETTINGS,
+ CREATE_REPOSITORY, EDIT_REPOSITORY, DELETE_REPOSITORY,
+ LIST_USERS, CREATE_USER, EDIT_USER, DELETE_USER,
+ LIST_TEAMS, CREATE_TEAM, EDIT_TEAM, DELETE_TEAM,
+ LIST_REPOSITORY_MEMBERS, SET_REPOSITORY_MEMBERS, LIST_REPOSITORY_TEAMS, SET_REPOSITORY_TEAMS,
+ LIST_FEDERATION_REGISTRATIONS, LIST_FEDERATION_RESULTS, LIST_FEDERATION_PROPOSALS, LIST_FEDERATION_SETS,
EDIT_SETTINGS, LIST_STATUS;
public static RpcRequest fromName(String name) {
diff --git a/src/com/gitblit/RpcFilter.java b/src/com/gitblit/RpcFilter.java
index 2ffb0610..4c0f03df 100644
--- a/src/com/gitblit/RpcFilter.java
+++ b/src/com/gitblit/RpcFilter.java
@@ -135,6 +135,8 @@ public class RpcFilter extends AuthenticationFilter {
private boolean canAccess(UserModel user, RpcRequest requestType) {
switch (requestType) {
+ case GET_PROTOCOL:
+ return true;
case LIST_REPOSITORIES:
return true;
default:
diff --git a/src/com/gitblit/RpcServlet.java b/src/com/gitblit/RpcServlet.java
index 068562e8..115d5536 100644
--- a/src/com/gitblit/RpcServlet.java
+++ b/src/com/gitblit/RpcServlet.java
@@ -33,6 +33,7 @@ import com.gitblit.Constants.RpcRequest;
import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.ServerSettings;
+import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.HttpUtils;
import com.gitblit.utils.JGitUtils;
@@ -48,6 +49,8 @@ public class RpcServlet extends JsonServlet {
private static final long serialVersionUID = 1L;
+ public static final int PROTOCOL_VERSION = 2;
+
public RpcServlet() {
super();
}
@@ -77,7 +80,10 @@ public class RpcServlet extends JsonServlet {
&& GitBlit.getBoolean(Keys.web.enableRpcAdministration, false);
Object result = null;
- if (RpcRequest.LIST_REPOSITORIES.equals(reqType)) {
+ if (RpcRequest.GET_PROTOCOL.equals(reqType)) {
+ // Return the protocol version
+ result = PROTOCOL_VERSION;
+ } else if (RpcRequest.LIST_REPOSITORIES.equals(reqType)) {
// Determine the Gitblit clone url
String gitblitUrl = HttpUtils.getGitblitURL(request);
StringBuilder sb = new StringBuilder();
@@ -128,6 +134,14 @@ public class RpcServlet extends JsonServlet {
users.add(GitBlit.self().getUserModel(name));
}
result = users;
+ } else if (RpcRequest.LIST_TEAMS.equals(reqType)) {
+ // list teams
+ List<String> names = GitBlit.self().getAllTeamnames();
+ List<TeamModel> teams = new ArrayList<TeamModel>();
+ for (String name : names) {
+ teams.add(GitBlit.self().getTeamModel(name));
+ }
+ result = teams;
} else if (RpcRequest.CREATE_REPOSITORY.equals(reqType)) {
// create repository
RepositoryModel model = deserialize(request, response, RepositoryModel.class);
@@ -180,6 +194,33 @@ public class RpcServlet extends JsonServlet {
if (!GitBlit.self().deleteUser(model.username)) {
response.setStatus(failureCode);
}
+ } else if (RpcRequest.CREATE_TEAM.equals(reqType)) {
+ // create team
+ TeamModel model = deserialize(request, response, TeamModel.class);
+ try {
+ GitBlit.self().updateTeamModel(model.name, model, true);
+ } catch (GitBlitException e) {
+ response.setStatus(failureCode);
+ }
+ } else if (RpcRequest.EDIT_TEAM.equals(reqType)) {
+ // edit team
+ TeamModel model = deserialize(request, response, TeamModel.class);
+ // name parameter specifies original team name in event of rename
+ String teamname = objectName;
+ if (teamname == null) {
+ teamname = model.name;
+ }
+ try {
+ GitBlit.self().updateTeamModel(teamname, model, false);
+ } catch (GitBlitException e) {
+ response.setStatus(failureCode);
+ }
+ } else if (RpcRequest.DELETE_TEAM.equals(reqType)) {
+ // delete team
+ TeamModel model = deserialize(request, response, TeamModel.class);
+ if (!GitBlit.self().deleteTeam(model.name)) {
+ response.setStatus(failureCode);
+ }
} else if (RpcRequest.LIST_REPOSITORY_MEMBERS.equals(reqType)) {
// get repository members
RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
@@ -192,6 +233,18 @@ public class RpcServlet extends JsonServlet {
if (!GitBlit.self().setRepositoryUsers(model, users)) {
response.setStatus(failureCode);
}
+ } else if (RpcRequest.LIST_REPOSITORY_TEAMS.equals(reqType)) {
+ // get repository teams
+ RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
+ result = GitBlit.self().getRepositoryTeams(model);
+ } else if (RpcRequest.SET_REPOSITORY_TEAMS.equals(reqType)) {
+ // update repository team access list
+ RepositoryModel model = GitBlit.self().getRepositoryModel(objectName);
+ Collection<String> names = deserialize(request, response, RpcUtils.NAMES_TYPE);
+ List<String> teams = new ArrayList<String>(names);
+ if (!GitBlit.self().setRepositoryTeams(model, teams)) {
+ response.setStatus(failureCode);
+ }
} else if (RpcRequest.LIST_FEDERATION_REGISTRATIONS.equals(reqType)) {
// return the list of federation registrations
if (allowAdmin) {
@@ -233,7 +286,7 @@ public class RpcServlet extends JsonServlet {
keys.add(Keys.web.siteName);
keys.add(Keys.web.mountParameters);
keys.add(Keys.web.syndicationEntries);
-
+
if (allowManagement) {
// keys necessary for repository and/or user management
keys.add(Keys.realm.minPasswordLength);
diff --git a/src/com/gitblit/client/EditRepositoryDialog.java b/src/com/gitblit/client/EditRepositoryDialog.java
index ef0f58ac..0b6ef59a 100644
--- a/src/com/gitblit/client/EditRepositoryDialog.java
+++ b/src/com/gitblit/client/EditRepositoryDialog.java
@@ -52,6 +52,7 @@ import javax.swing.ListCellRenderer;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.FederationStrategy;
import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.TeamModel;
import com.gitblit.utils.StringUtils;
/**
@@ -96,24 +97,26 @@ public class EditRepositoryDialog extends JDialog {
private JComboBox ownerField;
private JPalette<String> usersPalette;
-
+
private JPalette<String> setsPalette;
+
+ private JPalette<String> teamsPalette;
private Set<String> repositoryNames;
- public EditRepositoryDialog() {
- this(new RepositoryModel());
+ public EditRepositoryDialog(int protocolVersion) {
+ this(protocolVersion, new RepositoryModel());
this.isCreate = true;
setTitle(Translation.get("gb.newRepository"));
}
- public EditRepositoryDialog(RepositoryModel aRepository) {
+ public EditRepositoryDialog(int protocolVersion, RepositoryModel aRepository) {
super();
this.repositoryName = aRepository.name;
this.repository = new RepositoryModel();
this.repositoryNames = new HashSet<String>();
this.isCreate = false;
- initialize(aRepository);
+ initialize(protocolVersion, aRepository);
setModal(true);
setResizable(false);
setTitle(Translation.get("gb.edit") + ": " + aRepository.name);
@@ -132,7 +135,7 @@ public class EditRepositoryDialog extends JDialog {
return rootPane;
}
- private void initialize(RepositoryModel anRepository) {
+ private void initialize(int protocolVersion, RepositoryModel anRepository) {
nameField = new JTextField(anRepository.name == null ? "" : anRepository.name, 35);
descriptionField = new JTextField(anRepository.description == null ? ""
: anRepository.description, 35);
@@ -195,6 +198,11 @@ public class EditRepositoryDialog extends JDialog {
accessPanel.add(newFieldPanel(Translation.get("gb.permittedUsers"), usersPalette),
BorderLayout.CENTER);
+ teamsPalette = new JPalette<String>();
+ JPanel teamsPanel = new JPanel(new BorderLayout(5, 5));
+ teamsPanel.add(newFieldPanel(Translation.get("gb.permittedTeams"), teamsPalette),
+ BorderLayout.CENTER);
+
setsPalette = new JPalette<String>();
JPanel federationPanel = new JPanel(new BorderLayout(5, 5));
federationPanel.add(
@@ -206,6 +214,9 @@ public class EditRepositoryDialog extends JDialog {
JTabbedPane panel = new JTabbedPane(JTabbedPane.TOP);
panel.addTab(Translation.get("gb.general"), fieldsPanel);
panel.addTab(Translation.get("gb.accessRestriction"), accessPanel);
+ if (protocolVersion >= 2) {
+ panel.addTab(Translation.get("gb.teams"), teamsPanel);
+ }
panel.addTab(Translation.get("gb.federation"), federationPanel);
JButton createButton = new JButton(Translation.get("gb.save"));
@@ -358,6 +369,10 @@ public class EditRepositoryDialog extends JDialog {
}
usersPalette.setObjects(all, selected);
}
+
+ public void setTeams(List<String> all, List<String> selected) {
+ teamsPalette.setObjects(all, selected);
+ }
public void setRepositories(List<RepositoryModel> repositories) {
repositoryNames.clear();
@@ -385,6 +400,10 @@ public class EditRepositoryDialog extends JDialog {
return usersPalette.getSelections();
}
+ public List<String> getPermittedTeams() {
+ return teamsPalette.getSelections();
+ }
+
/**
* ListCellRenderer to display descriptive text about the access
* restriction.
diff --git a/src/com/gitblit/client/EditTeamDialog.java b/src/com/gitblit/client/EditTeamDialog.java
new file mode 100644
index 00000000..4297599c
--- /dev/null
+++ b/src/com/gitblit/client/EditTeamDialog.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.client;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JRootPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextField;
+import javax.swing.KeyStroke;
+
+import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.ServerSettings;
+import com.gitblit.models.TeamModel;
+import com.gitblit.utils.StringUtils;
+
+public class EditTeamDialog extends JDialog {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String teamname;
+
+ private final TeamModel team;
+
+ private final ServerSettings settings;
+
+ private boolean isCreate;
+
+ private boolean canceled = true;
+
+ private JTextField teamnameField;
+
+ private JPalette<String> repositoryPalette;
+
+ private JPalette<String> userPalette;
+
+ private Set<String> teamnames;
+
+ public EditTeamDialog(int protocolVersion, ServerSettings settings) {
+ this(protocolVersion, new TeamModel(""), settings);
+ this.isCreate = true;
+ setTitle(Translation.get("gb.newTeam"));
+ }
+
+ public EditTeamDialog(int protocolVersion, TeamModel aTeam, ServerSettings settings) {
+ super();
+ this.teamname = aTeam.name;
+ this.team = new TeamModel("");
+ this.settings = settings;
+ this.teamnames = new HashSet<String>();
+ this.isCreate = false;
+ initialize(protocolVersion, aTeam);
+ setModal(true);
+ setTitle(Translation.get("gb.edit") + ": " + aTeam.name);
+ setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());
+ }
+
+ @Override
+ protected JRootPane createRootPane() {
+ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
+ JRootPane rootPane = new JRootPane();
+ rootPane.registerKeyboardAction(new ActionListener() {
+ public void actionPerformed(ActionEvent actionEvent) {
+ setVisible(false);
+ }
+ }, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
+ return rootPane;
+ }
+
+ private void initialize(int protocolVersion, TeamModel aTeam) {
+ teamnameField = new JTextField(aTeam.name == null ? "" : aTeam.name, 25);
+
+ JPanel fieldsPanel = new JPanel(new GridLayout(0, 1));
+ fieldsPanel.add(newFieldPanel(Translation.get("gb.teamName"), teamnameField));
+
+ final Insets _insets = new Insets(5, 5, 5, 5);
+ repositoryPalette = new JPalette<String>();
+ userPalette = new JPalette<String>();
+
+ JPanel fieldsPanelTop = new JPanel(new BorderLayout());
+ fieldsPanelTop.add(fieldsPanel, BorderLayout.NORTH);
+
+ JPanel repositoriesPanel = new JPanel(new BorderLayout()) {
+
+ private static final long serialVersionUID = 1L;
+
+ public Insets getInsets() {
+ return _insets;
+ }
+ };
+ repositoriesPanel.add(repositoryPalette, BorderLayout.CENTER);
+
+ JPanel usersPanel = new JPanel(new BorderLayout()) {
+
+ private static final long serialVersionUID = 1L;
+
+ public Insets getInsets() {
+ return _insets;
+ }
+ };
+ usersPanel.add(userPalette, BorderLayout.CENTER);
+
+ JTabbedPane panel = new JTabbedPane(JTabbedPane.TOP);
+ panel.addTab(Translation.get("gb.general"), fieldsPanelTop);
+ panel.addTab(Translation.get("gb.teamMembers"), usersPanel);
+ panel.addTab(Translation.get("gb.restrictedRepositories"), repositoriesPanel);
+
+
+ JButton createButton = new JButton(Translation.get("gb.save"));
+ createButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent event) {
+ if (validateFields()) {
+ canceled = false;
+ setVisible(false);
+ }
+ }
+ });
+
+ JButton cancelButton = new JButton(Translation.get("gb.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent event) {
+ canceled = true;
+ setVisible(false);
+ }
+ });
+
+ JPanel controls = new JPanel();
+ controls.add(cancelButton);
+ controls.add(createButton);
+
+ JPanel centerPanel = new JPanel(new BorderLayout(5, 5)) {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public Insets getInsets() {
+ return _insets;
+ }
+ };
+ centerPanel.add(panel, BorderLayout.CENTER);
+ centerPanel.add(controls, BorderLayout.SOUTH);
+
+ getContentPane().setLayout(new BorderLayout(5, 5));
+ getContentPane().add(centerPanel, BorderLayout.CENTER);
+ pack();
+ }
+
+ private JPanel newFieldPanel(String label, JComponent comp) {
+ JLabel fieldLabel = new JLabel(label);
+ fieldLabel.setFont(fieldLabel.getFont().deriveFont(Font.BOLD));
+ fieldLabel.setPreferredSize(new Dimension(150, 20));
+ JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0));
+ panel.add(fieldLabel);
+ panel.add(comp);
+ return panel;
+ }
+
+ private boolean validateFields() {
+ String tname = teamnameField.getText();
+ if (StringUtils.isEmpty(tname)) {
+ error("Please enter a team name!");
+ return false;
+ }
+
+ boolean rename = false;
+ // verify teamname uniqueness on create
+ if (isCreate) {
+ if (teamnames.contains(tname.toLowerCase())) {
+ error(MessageFormat.format("Team name ''{0}'' is unavailable.", tname));
+ return false;
+ }
+ } else {
+ // check rename collision
+ rename = !StringUtils.isEmpty(teamname) && !teamname.equalsIgnoreCase(tname);
+ if (rename) {
+ if (teamnames.contains(tname.toLowerCase())) {
+ error(MessageFormat.format(
+ "Failed to rename ''{0}'' because ''{1}'' already exists.", teamname,
+ tname));
+ return false;
+ }
+ }
+ }
+ team.name = tname;
+
+ team.repositories.clear();
+ team.repositories.addAll(repositoryPalette.getSelections());
+
+ team.users.clear();
+ team.users.addAll(userPalette.getSelections());
+ return true;
+ }
+
+ private void error(String message) {
+ JOptionPane.showMessageDialog(EditTeamDialog.this, message, Translation.get("gb.error"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+
+ public void setTeams(List<TeamModel> teams) {
+ teamnames.clear();
+ for (TeamModel team : teams) {
+ teamnames.add(team.name.toLowerCase());
+ }
+ }
+
+ public void setRepositories(List<RepositoryModel> repositories, List<String> selected) {
+ List<String> restricted = new ArrayList<String>();
+ for (RepositoryModel repo : repositories) {
+ if (repo.accessRestriction.exceeds(AccessRestrictionType.NONE)) {
+ restricted.add(repo.name);
+ }
+ }
+ StringUtils.sortRepositorynames(restricted);
+ if (selected != null) {
+ StringUtils.sortRepositorynames(selected);
+ }
+ repositoryPalette.setObjects(restricted, selected);
+ }
+
+ public void setUsers(List<String> users, List<String> selected) {
+ Collections.sort(users);
+ if (selected != null) {
+ Collections.sort(selected);
+ }
+ userPalette.setObjects(users, selected);
+ }
+
+ public TeamModel getTeam() {
+ if (canceled) {
+ return null;
+ }
+ return team;
+ }
+}
diff --git a/src/com/gitblit/client/EditUserDialog.java b/src/com/gitblit/client/EditUserDialog.java
index 246a0777..3f1b9291 100644
--- a/src/com/gitblit/client/EditUserDialog.java
+++ b/src/com/gitblit/client/EditUserDialog.java
@@ -26,6 +26,7 @@ import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -40,6 +41,7 @@ import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JRootPane;
+import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
@@ -47,6 +49,7 @@ import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Keys;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.ServerSettings;
+import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
@@ -75,23 +78,25 @@ public class EditUserDialog extends JDialog {
private JCheckBox notFederatedCheckbox;
private JPalette<String> repositoryPalette;
+
+ private JPalette<TeamModel> teamsPalette;
private Set<String> usernames;
- public EditUserDialog(ServerSettings settings) {
- this(new UserModel(""), settings);
+ public EditUserDialog(int protocolVersion, ServerSettings settings) {
+ this(protocolVersion, new UserModel(""), settings);
this.isCreate = true;
setTitle(Translation.get("gb.newUser"));
}
- public EditUserDialog(UserModel anUser, ServerSettings settings) {
+ public EditUserDialog(int protocolVersion, UserModel anUser, ServerSettings settings) {
super();
this.username = anUser.username;
this.user = new UserModel("");
this.settings = settings;
this.usernames = new HashSet<String>();
this.isCreate = false;
- initialize(anUser);
+ initialize(protocolVersion, anUser);
setModal(true);
setTitle(Translation.get("gb.edit") + ": " + anUser.username);
setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());
@@ -109,7 +114,7 @@ public class EditUserDialog extends JDialog {
return rootPane;
}
- private void initialize(UserModel anUser) {
+ private void initialize(int protocolVersion, UserModel anUser) {
usernameField = new JTextField(anUser.username == null ? "" : anUser.username, 25);
passwordField = new JPasswordField(anUser.password == null ? "" : anUser.password, 25);
confirmPasswordField = new JPasswordField(anUser.password == null ? "" : anUser.password,
@@ -127,11 +132,40 @@ public class EditUserDialog extends JDialog {
fieldsPanel.add(newFieldPanel(Translation.get("gb.excludeFromFederation"),
notFederatedCheckbox));
+ final Insets _insets = new Insets(5, 5, 5, 5);
repositoryPalette = new JPalette<String>();
- JPanel panel = new JPanel(new BorderLayout());
- panel.add(fieldsPanel, BorderLayout.NORTH);
- panel.add(newFieldPanel(Translation.get("gb.restrictedRepositories"), repositoryPalette),
- BorderLayout.CENTER);
+ teamsPalette = new JPalette<TeamModel>();
+
+ JPanel fieldsPanelTop = new JPanel(new BorderLayout());
+ fieldsPanelTop.add(fieldsPanel, BorderLayout.NORTH);
+
+ JPanel repositoriesPanel = new JPanel(new BorderLayout()) {
+
+ private static final long serialVersionUID = 1L;
+
+ public Insets getInsets() {
+ return _insets;
+ }
+ };
+ repositoriesPanel.add(repositoryPalette, BorderLayout.CENTER);
+
+ JPanel teamsPanel = new JPanel(new BorderLayout()) {
+
+ private static final long serialVersionUID = 1L;
+
+ public Insets getInsets() {
+ return _insets;
+ }
+ };
+ teamsPanel.add(teamsPalette, BorderLayout.CENTER);
+
+ JTabbedPane panel = new JTabbedPane(JTabbedPane.TOP);
+ panel.addTab(Translation.get("gb.general"), fieldsPanelTop);
+ if (protocolVersion > 1) {
+ panel.addTab(Translation.get("gb.teamMemberships"), teamsPanel);
+ }
+ panel.addTab(Translation.get("gb.restrictedRepositories"), repositoriesPanel);
+
JButton createButton = new JButton(Translation.get("gb.save"));
createButton.addActionListener(new ActionListener() {
@@ -154,8 +188,7 @@ public class EditUserDialog extends JDialog {
JPanel controls = new JPanel();
controls.add(cancelButton);
controls.add(createButton);
-
- final Insets _insets = new Insets(5, 5, 5, 5);
+
JPanel centerPanel = new JPanel(new BorderLayout(5, 5)) {
private static final long serialVersionUID = 1L;
@@ -259,6 +292,9 @@ public class EditUserDialog extends JDialog {
user.repositories.clear();
user.repositories.addAll(repositoryPalette.getSelections());
+
+ user.teams.clear();
+ user.teams.addAll(teamsPalette.getSelections());
return true;
}
@@ -287,6 +323,14 @@ public class EditUserDialog extends JDialog {
}
repositoryPalette.setObjects(restricted, selected);
}
+
+ public void setTeams(List<TeamModel> teams, List<TeamModel> selected) {
+ Collections.sort(teams);
+ if (selected != null) {
+ Collections.sort(selected);
+ }
+ teamsPalette.setObjects(teams, selected);
+ }
public UserModel getUser() {
if (canceled) {
diff --git a/src/com/gitblit/client/GitblitClient.java b/src/com/gitblit/client/GitblitClient.java
index c027537a..b9444861 100644
--- a/src/com/gitblit/client/GitblitClient.java
+++ b/src/com/gitblit/client/GitblitClient.java
@@ -37,6 +37,7 @@ import com.gitblit.models.FeedModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.ServerSettings;
import com.gitblit.models.ServerStatus;
+import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.RpcUtils;
import com.gitblit.utils.StringUtils;
@@ -63,6 +64,8 @@ public class GitblitClient implements Serializable {
private final char[] password;
+ private volatile int protocolVersion;
+
private volatile boolean allowManagement;
private volatile boolean allowAdministration;
@@ -73,6 +76,8 @@ public class GitblitClient implements Serializable {
private final List<UserModel> allUsers;
+ private final List<TeamModel> allTeams;
+
private final List<FederationModel> federationRegistrations;
private final List<FeedModel> availableFeeds;
@@ -90,6 +95,7 @@ public class GitblitClient implements Serializable {
this.password = reg.password;
this.allUsers = new ArrayList<UserModel>();
+ this.allTeams = new ArrayList<TeamModel>();
this.allRepositories = new ArrayList<RepositoryModel>();
this.federationRegistrations = new ArrayList<FederationModel>();
this.availableFeeds = new ArrayList<FeedModel>();
@@ -98,6 +104,7 @@ public class GitblitClient implements Serializable {
}
public void login() throws IOException {
+ protocolVersion = RpcUtils.getProtocolVersion(url, account, password);
refreshSettings();
refreshAvailableFeeds();
refreshRepositories();
@@ -107,6 +114,9 @@ public class GitblitClient implements Serializable {
// credentials may not have administrator access
// or server may have disabled rpc management
refreshUsers();
+ if (protocolVersion > 1) {
+ refreshTeams();
+ }
allowManagement = true;
} catch (UnauthorizedException e) {
} catch (ForbiddenException e) {
@@ -130,6 +140,10 @@ public class GitblitClient implements Serializable {
}
}
+ public int getProtocolVersion() {
+ return protocolVersion;
+ }
+
public boolean allowManagement() {
return allowManagement;
}
@@ -198,6 +212,13 @@ public class GitblitClient implements Serializable {
return allUsers;
}
+ public List<TeamModel> refreshTeams() throws IOException {
+ List<TeamModel> teams = RpcUtils.getTeams(url, account, password);
+ allTeams.clear();
+ allTeams.addAll(teams);
+ return allTeams;
+ }
+
public ServerSettings refreshSettings() throws IOException {
settings = RpcUtils.getSettings(url, account, password);
return settings;
@@ -253,8 +274,8 @@ public class GitblitClient implements Serializable {
for (FeedModel feed : reg.feeds) {
feed.lastRefreshDate = feed.currentRefreshDate;
feed.currentRefreshDate = new Date();
- List<FeedEntryModel> entries = SyndicationUtils.readFeed(url,
- feed.repository, feed.branch, -1, page, account, password);
+ List<FeedEntryModel> entries = SyndicationUtils.readFeed(url, feed.repository,
+ feed.branch, -1, page, account, password);
allEntries.addAll(entries);
}
}
@@ -301,8 +322,8 @@ public class GitblitClient implements Serializable {
return syndicatedEntries;
}
- public List<FeedEntryModel> log(String repository, String branch, int numberOfEntries,
- int page) throws IOException {
+ public List<FeedEntryModel> log(String repository, String branch, int numberOfEntries, int page)
+ throws IOException {
return SyndicationUtils.readFeed(url, repository, branch, numberOfEntries, page, account,
password);
}
@@ -343,6 +364,29 @@ public class GitblitClient implements Serializable {
return usernames;
}
+ public List<TeamModel> getTeams() {
+ return allTeams;
+ }
+
+ public List<String> getTeamnames() {
+ List<String> teamnames = new ArrayList<String>();
+ for (TeamModel team : this.allTeams) {
+ teamnames.add(team.name);
+ }
+ Collections.sort(teamnames);
+ return teamnames;
+ }
+
+ public List<String> getPermittedTeamnames(RepositoryModel repository) {
+ List<String> teamnames = new ArrayList<String>();
+ for (TeamModel team : this.allTeams) {
+ if (team.repositories.contains(repository.name)) {
+ teamnames.add(team.name);
+ }
+ }
+ return teamnames;
+ }
+
public List<String> getFederationSets() {
return settings.get(Keys.federation.sets).getStrings();
}
@@ -353,23 +397,44 @@ public class GitblitClient implements Serializable {
public boolean createRepository(RepositoryModel repository, List<String> permittedUsers)
throws IOException {
+ return createRepository(repository, permittedUsers, null);
+ }
+
+ public boolean createRepository(RepositoryModel repository, List<String> permittedUsers,
+ List<String> permittedTeams) throws IOException {
boolean success = true;
success &= RpcUtils.createRepository(repository, url, account, password);
- if (permittedUsers.size() > 0) {
+ if (permittedUsers != null && permittedUsers.size() > 0) {
// if new repository has named members, set them
success &= RpcUtils.setRepositoryMembers(repository, permittedUsers, url, account,
password);
}
+ if (permittedTeams != null && permittedTeams.size() > 0) {
+ // if new repository has named teams, set them
+ success &= RpcUtils.setRepositoryTeams(repository, permittedTeams, url, account,
+ password);
+ }
return success;
}
public boolean updateRepository(String name, RepositoryModel repository,
List<String> permittedUsers) throws IOException {
+ return updateRepository(name, repository, permittedUsers, null);
+ }
+
+ public boolean updateRepository(String name, RepositoryModel repository,
+ List<String> permittedUsers, List<String> permittedTeams) throws IOException {
boolean success = true;
success &= RpcUtils.updateRepository(name, repository, url, account, password);
- // always set the repository members
- success &= RpcUtils
- .setRepositoryMembers(repository, permittedUsers, url, account, password);
+ // set the repository members
+ if (permittedUsers != null) {
+ success &= RpcUtils.setRepositoryMembers(repository, permittedUsers, url, account,
+ password);
+ }
+ if (permittedTeams != null) {
+ success &= RpcUtils.setRepositoryTeams(repository, permittedTeams, url, account,
+ password);
+ }
return success;
}
@@ -389,6 +454,18 @@ public class GitblitClient implements Serializable {
return RpcUtils.deleteUser(user, url, account, password);
}
+ public boolean createTeam(TeamModel team) throws IOException {
+ return RpcUtils.createTeam(team, url, account, password);
+ }
+
+ public boolean updateTeam(String name, TeamModel team) throws IOException {
+ return RpcUtils.updateTeam(name, team, url, account, password);
+ }
+
+ public boolean deleteTeam(TeamModel team) throws IOException {
+ return RpcUtils.deleteTeam(team, url, account, password);
+ }
+
public boolean updateSettings(Map<String, String> newSettings) throws IOException {
return RpcUtils.updateSettings(newSettings, url, account, password);
}
diff --git a/src/com/gitblit/client/GitblitPanel.java b/src/com/gitblit/client/GitblitPanel.java
index 0e670ae3..f14ce790 100644
--- a/src/com/gitblit/client/GitblitPanel.java
+++ b/src/com/gitblit/client/GitblitPanel.java
@@ -50,6 +50,8 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
private FeedsPanel feedsPanel;
private UsersPanel usersPanel;
+
+ private TeamsPanel teamsPanel;
private SettingsPanel settingsPanel;
@@ -62,6 +64,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
tabs = new JTabbedPane(JTabbedPane.BOTTOM);
tabs.addTab(Translation.get("gb.repositories"), createRepositoriesPanel());
tabs.addTab(Translation.get("gb.activity"), createFeedsPanel());
+ tabs.addTab(Translation.get("gb.teams"), createTeamsPanel());
tabs.addTab(Translation.get("gb.users"), createUsersPanel());
tabs.addTab(Translation.get("gb.settings"), createSettingsPanel());
tabs.addTab(Translation.get("gb.status"), createStatusPanel());
@@ -89,6 +92,11 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
protected void updateUsersTable() {
usersPanel.updateTable(false);
}
+
+ @Override
+ protected void updateTeamsTable() {
+ teamsPanel.updateTable(false);
+ }
};
return repositoriesPanel;
@@ -107,9 +115,30 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
}
private JPanel createUsersPanel() {
- usersPanel = new UsersPanel(gitblit);
+ usersPanel = new UsersPanel(gitblit) {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void updateTeamsTable() {
+ teamsPanel.updateTable(false);
+ }
+ };
return usersPanel;
}
+
+ private JPanel createTeamsPanel() {
+ teamsPanel = new TeamsPanel(gitblit) {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void updateUsersTable() {
+ usersPanel.updateTable(false);
+ }
+ };
+ return teamsPanel;
+ }
private JPanel createSettingsPanel() {
settingsPanel = new SettingsPanel(gitblit);
@@ -128,6 +157,19 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
feedsPanel.updateTable(true);
if (gitblit.allowManagement()) {
+ if (gitblit.getProtocolVersion() >= 2) {
+ // refresh teams panel
+ teamsPanel.updateTable(false);
+ } else {
+ // remove teams panel
+ String teams = Translation.get("gb.teams");
+ for (int i = 0; i < tabs.getTabCount(); i++) {
+ if (teams.equals(tabs.getTitleAt(i))) {
+ tabs.removeTabAt(i);
+ break;
+ }
+ }
+ }
usersPanel.updateTable(false);
} else {
// user does not have administrator privileges
diff --git a/src/com/gitblit/client/RepositoriesPanel.java b/src/com/gitblit/client/RepositoriesPanel.java
index 70ff6cfb..cd3f46be 100644
--- a/src/com/gitblit/client/RepositoriesPanel.java
+++ b/src/com/gitblit/client/RepositoriesPanel.java
@@ -277,6 +277,8 @@ public abstract class RepositoriesPanel extends JPanel {
protected abstract void subscribeFeeds(List<FeedModel> feeds);
protected abstract void updateUsersTable();
+
+ protected abstract void updateTeamsTable();
protected void disableManagement() {
createRepository.setVisible(false);
@@ -349,14 +351,16 @@ public abstract class RepositoriesPanel extends JPanel {
*
*/
protected void createRepository() {
- EditRepositoryDialog dialog = new EditRepositoryDialog();
+ EditRepositoryDialog dialog = new EditRepositoryDialog(gitblit.getProtocolVersion());
dialog.setLocationRelativeTo(RepositoriesPanel.this);
dialog.setUsers(null, gitblit.getUsernames(), null);
+ dialog.setTeams(gitblit.getTeamnames(), null);
dialog.setRepositories(gitblit.getRepositories());
dialog.setFederationSets(gitblit.getFederationSets(), null);
dialog.setVisible(true);
final RepositoryModel newRepository = dialog.getRepository();
final List<String> permittedUsers = dialog.getPermittedUsers();
+ final List<String> permittedTeams = dialog.getPermittedTeams();
if (newRepository == null) {
return;
}
@@ -365,12 +369,15 @@ public abstract class RepositoriesPanel extends JPanel {
@Override
protected Boolean doRequest() throws IOException {
- boolean success = gitblit.createRepository(newRepository, permittedUsers);
+ boolean success = gitblit.createRepository(newRepository, permittedUsers, permittedTeams);
if (success) {
gitblit.refreshRepositories();
if (permittedUsers.size() > 0) {
gitblit.refreshUsers();
}
+ if (permittedTeams.size() > 0) {
+ gitblit.refreshTeams();
+ }
}
return success;
}
@@ -379,6 +386,7 @@ public abstract class RepositoriesPanel extends JPanel {
protected void onSuccess() {
updateTable(false);
updateUsersTable();
+ updateTeamsTable();
}
@Override
@@ -397,16 +405,18 @@ public abstract class RepositoriesPanel extends JPanel {
* @param repository
*/
protected void editRepository(final RepositoryModel repository) {
- EditRepositoryDialog dialog = new EditRepositoryDialog(repository);
+ EditRepositoryDialog dialog = new EditRepositoryDialog(gitblit.getProtocolVersion(), repository);
dialog.setLocationRelativeTo(RepositoriesPanel.this);
List<String> usernames = gitblit.getUsernames();
List<String> members = gitblit.getPermittedUsernames(repository);
dialog.setUsers(repository.owner, usernames, members);
+ dialog.setTeams(gitblit.getTeamnames(), gitblit.getPermittedTeamnames(repository));
dialog.setRepositories(gitblit.getRepositories());
dialog.setFederationSets(gitblit.getFederationSets(), repository.federationSets);
dialog.setVisible(true);
final RepositoryModel revisedRepository = dialog.getRepository();
final List<String> permittedUsers = dialog.getPermittedUsers();
+ final List<String> permittedTeams = dialog.getPermittedTeams();
if (revisedRepository == null) {
return;
}
@@ -416,10 +426,11 @@ public abstract class RepositoriesPanel extends JPanel {
@Override
protected Boolean doRequest() throws IOException {
boolean success = gitblit.updateRepository(repository.name, revisedRepository,
- permittedUsers);
+ permittedUsers, permittedTeams);
if (success) {
gitblit.refreshRepositories();
gitblit.refreshUsers();
+ gitblit.refreshTeams();
}
return success;
}
@@ -428,6 +439,7 @@ public abstract class RepositoriesPanel extends JPanel {
protected void onSuccess() {
updateTable(false);
updateUsersTable();
+ updateTeamsTable();
}
@Override
@@ -460,6 +472,7 @@ public abstract class RepositoriesPanel extends JPanel {
if (success) {
gitblit.refreshRepositories();
gitblit.refreshUsers();
+ gitblit.refreshTeams();
}
return success;
}
@@ -468,6 +481,7 @@ public abstract class RepositoriesPanel extends JPanel {
protected void onSuccess() {
updateTable(false);
updateUsersTable();
+ updateTeamsTable();
}
@Override
diff --git a/src/com/gitblit/client/TeamsPanel.java b/src/com/gitblit/client/TeamsPanel.java
new file mode 100644
index 00000000..2d1d914a
--- /dev/null
+++ b/src/com/gitblit/client/TeamsPanel.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.client;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.RowFilter;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.table.TableRowSorter;
+
+import com.gitblit.Constants.RpcRequest;
+import com.gitblit.models.TeamModel;
+import com.gitblit.utils.StringUtils;
+
+/**
+ * Users panel displays a list of user accounts and allows management of those
+ * accounts.
+ *
+ * @author James Moger
+ *
+ */
+public abstract class TeamsPanel extends JPanel {
+
+ private static final long serialVersionUID = 1L;
+
+ private final GitblitClient gitblit;
+
+ private HeaderPanel header;
+
+ private JTable table;
+
+ private TeamsTableModel tableModel;
+
+ private TableRowSorter<TeamsTableModel> defaultSorter;
+
+ private JTextField filterTextfield;
+
+ public TeamsPanel(GitblitClient gitblit) {
+ super();
+ this.gitblit = gitblit;
+ initialize();
+ }
+
+ private void initialize() {
+ JButton refreshTeams = new JButton(Translation.get("gb.refresh"));
+ refreshTeams.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ refreshTeams();
+ }
+ });
+
+ JButton createTeam = new JButton(Translation.get("gb.create"));
+ createTeam.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ createTeam();
+ }
+ });
+
+ final JButton editTeam = new JButton(Translation.get("gb.edit"));
+ editTeam.setEnabled(false);
+ editTeam.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ editTeam(getSelectedTeams().get(0));
+ }
+ });
+
+ final JButton delTeam = new JButton(Translation.get("gb.delete"));
+ delTeam.setEnabled(false);
+ delTeam.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ deleteTeams(getSelectedTeams());
+ }
+ });
+
+ NameRenderer nameRenderer = new NameRenderer();
+ tableModel = new TeamsTableModel();
+ defaultSorter = new TableRowSorter<TeamsTableModel>(tableModel);
+ table = Utils.newTable(tableModel, Utils.DATE_FORMAT);
+ String name = table.getColumnName(TeamsTableModel.Columns.Name.ordinal());
+ table.setRowHeight(nameRenderer.getFont().getSize() + 8);
+ table.getColumn(name).setCellRenderer(nameRenderer);
+
+ int w = 125;
+ name = table.getColumnName(TeamsTableModel.Columns.Members.ordinal());
+ table.getColumn(name).setMinWidth(w);
+ table.getColumn(name).setMaxWidth(w);
+ name = table.getColumnName(TeamsTableModel.Columns.Repositories.ordinal());
+ table.getColumn(name).setMinWidth(w);
+ table.getColumn(name).setMaxWidth(w);
+
+ table.setRowSorter(defaultSorter);
+ table.getRowSorter().toggleSortOrder(TeamsTableModel.Columns.Name.ordinal());
+ table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ if (e.getValueIsAdjusting()) {
+ return;
+ }
+ boolean selected = table.getSelectedRow() > -1;
+ boolean singleSelection = table.getSelectedRows().length == 1;
+ editTeam.setEnabled(singleSelection && selected);
+ delTeam.setEnabled(selected);
+ }
+ });
+
+ table.addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2) {
+ editTeam(getSelectedTeams().get(0));
+ }
+ }
+ });
+
+ filterTextfield = new JTextField();
+ filterTextfield.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ filterTeams(filterTextfield.getText());
+ }
+ });
+ filterTextfield.addKeyListener(new KeyAdapter() {
+ public void keyReleased(KeyEvent e) {
+ filterTeams(filterTextfield.getText());
+ }
+ });
+
+ JPanel teamFilterPanel = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN));
+ teamFilterPanel.add(new JLabel(Translation.get("gb.filter")), BorderLayout.WEST);
+ teamFilterPanel.add(filterTextfield, BorderLayout.CENTER);
+
+ JPanel teamTablePanel = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN));
+ teamTablePanel.add(teamFilterPanel, BorderLayout.NORTH);
+ teamTablePanel.add(new JScrollPane(table), BorderLayout.CENTER);
+
+ JPanel teamControls = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));
+ teamControls.add(refreshTeams);
+ teamControls.add(createTeam);
+ teamControls.add(editTeam);
+ teamControls.add(delTeam);
+
+ setLayout(new BorderLayout(Utils.MARGIN, Utils.MARGIN));
+ header = new HeaderPanel(Translation.get("gb.teams"), "users_16x16.png");
+ add(header, BorderLayout.NORTH);
+ add(teamTablePanel, BorderLayout.CENTER);
+ add(teamControls, BorderLayout.SOUTH);
+ }
+
+ @Override
+ public void requestFocus() {
+ filterTextfield.requestFocus();
+ }
+
+ @Override
+ public Insets getInsets() {
+ return Utils.INSETS;
+ }
+
+ protected abstract void updateUsersTable();
+
+ protected void updateTable(boolean pack) {
+ tableModel.list.clear();
+ tableModel.list.addAll(gitblit.getTeams());
+ tableModel.fireTableDataChanged();
+ header.setText(Translation.get("gb.teams") + " (" + gitblit.getTeams().size() + ")");
+ if (pack) {
+ Utils.packColumns(table, Utils.MARGIN);
+ }
+ }
+
+ private void filterTeams(final String fragment) {
+ if (StringUtils.isEmpty(fragment)) {
+ table.setRowSorter(defaultSorter);
+ return;
+ }
+ RowFilter<TeamsTableModel, Object> containsFilter = new RowFilter<TeamsTableModel, Object>() {
+ public boolean include(Entry<? extends TeamsTableModel, ? extends Object> entry) {
+ for (int i = entry.getValueCount() - 1; i >= 0; i--) {
+ if (entry.getStringValue(i).toLowerCase().contains(fragment.toLowerCase())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ TableRowSorter<TeamsTableModel> sorter = new TableRowSorter<TeamsTableModel>(tableModel);
+ sorter.setRowFilter(containsFilter);
+ table.setRowSorter(sorter);
+ }
+
+ private List<TeamModel> getSelectedTeams() {
+ List<TeamModel> teams = new ArrayList<TeamModel>();
+ for (int viewRow : table.getSelectedRows()) {
+ int modelRow = table.convertRowIndexToModel(viewRow);
+ TeamModel model = tableModel.list.get(modelRow);
+ teams.add(model);
+ }
+ return teams;
+ }
+
+ protected void refreshTeams() {
+ GitblitWorker worker = new GitblitWorker(TeamsPanel.this, RpcRequest.LIST_TEAMS) {
+ @Override
+ protected Boolean doRequest() throws IOException {
+ gitblit.refreshTeams();
+ return true;
+ }
+
+ @Override
+ protected void onSuccess() {
+ updateTable(false);
+ }
+ };
+ worker.execute();
+ }
+
+ /**
+ * Displays the create team dialog and fires a SwingWorker to update the
+ * server, if appropriate.
+ *
+ */
+ protected void createTeam() {
+ EditTeamDialog dialog = new EditTeamDialog(gitblit.getProtocolVersion(),
+ gitblit.getSettings());
+ dialog.setLocationRelativeTo(TeamsPanel.this);
+ dialog.setTeams(gitblit.getTeams());
+ dialog.setRepositories(gitblit.getRepositories(), null);
+ dialog.setUsers(gitblit.getUsernames(), null);
+ dialog.setVisible(true);
+ final TeamModel newTeam = dialog.getTeam();
+ if (newTeam == null) {
+ return;
+ }
+
+ GitblitWorker worker = new GitblitWorker(this, RpcRequest.CREATE_TEAM) {
+
+ @Override
+ protected Boolean doRequest() throws IOException {
+ boolean success = gitblit.createTeam(newTeam);
+ if (success) {
+ gitblit.refreshTeams();
+ gitblit.refreshUsers();
+ }
+ return success;
+ }
+
+ @Override
+ protected void onSuccess() {
+ updateTable(false);
+ updateUsersTable();
+ }
+
+ @Override
+ protected void onFailure() {
+ showFailure("Failed to execute request \"{0}\" for team \"{1}\".",
+ getRequestType(), newTeam.name);
+ }
+ };
+ worker.execute();
+ }
+
+ /**
+ * Displays the edit team dialog and fires a SwingWorker to update the
+ * server, if appropriate.
+ *
+ * @param user
+ */
+ protected void editTeam(final TeamModel team) {
+ EditTeamDialog dialog = new EditTeamDialog(gitblit.getProtocolVersion(), team,
+ gitblit.getSettings());
+ dialog.setLocationRelativeTo(TeamsPanel.this);
+ dialog.setTeams(gitblit.getTeams());
+ dialog.setRepositories(gitblit.getRepositories(), new ArrayList<String>(team.repositories));
+ dialog.setUsers(gitblit.getUsernames(), team.users == null ? null : new ArrayList<String>(
+ team.users));
+ dialog.setVisible(true);
+ final TeamModel revisedTeam = dialog.getTeam();
+ if (revisedTeam == null) {
+ return;
+ }
+
+ GitblitWorker worker = new GitblitWorker(this, RpcRequest.EDIT_TEAM) {
+ @Override
+ protected Boolean doRequest() throws IOException {
+ boolean success = gitblit.updateTeam(team.name, revisedTeam);
+ if (success) {
+ gitblit.refreshTeams();
+ gitblit.refreshUsers();
+ }
+ return success;
+ }
+
+ @Override
+ protected void onSuccess() {
+ updateTable(false);
+ updateUsersTable();
+ }
+
+ @Override
+ protected void onFailure() {
+ showFailure("Failed to execute request \"{0}\" for team \"{1}\".",
+ getRequestType(), team.name);
+ }
+ };
+ worker.execute();
+ }
+
+ protected void deleteTeams(final List<TeamModel> teams) {
+ if (teams == null || teams.size() == 0) {
+ return;
+ }
+ StringBuilder message = new StringBuilder("Delete the following teams?\n\n");
+ for (TeamModel team : teams) {
+ message.append(team.name).append("\n");
+ }
+ int result = JOptionPane.showConfirmDialog(TeamsPanel.this, message.toString(),
+ "Delete Teams?", JOptionPane.YES_NO_OPTION);
+ if (result == JOptionPane.YES_OPTION) {
+ GitblitWorker worker = new GitblitWorker(this, RpcRequest.DELETE_TEAM) {
+ @Override
+ protected Boolean doRequest() throws IOException {
+ boolean success = true;
+ for (TeamModel team : teams) {
+ success &= gitblit.deleteTeam(team);
+ }
+ if (success) {
+ gitblit.refreshTeams();
+ gitblit.refreshUsers();
+ }
+ return success;
+ }
+
+ @Override
+ protected void onSuccess() {
+ updateTable(false);
+ updateUsersTable();
+ }
+
+ @Override
+ protected void onFailure() {
+ showFailure("Failed to delete specified teams!");
+ }
+ };
+ worker.execute();
+ }
+ }
+}
diff --git a/src/com/gitblit/client/TeamsTableModel.java b/src/com/gitblit/client/TeamsTableModel.java
new file mode 100644
index 00000000..e6d8a945
--- /dev/null
+++ b/src/com/gitblit/client/TeamsTableModel.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2011 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.client;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.table.AbstractTableModel;
+
+import com.gitblit.models.TeamModel;
+
+/**
+ * Table model of a list of teams.
+ *
+ * @author James Moger
+ *
+ */
+public class TeamsTableModel extends AbstractTableModel {
+
+ private static final long serialVersionUID = 1L;
+
+ List<TeamModel> list;
+
+ enum Columns {
+ Name, Members, Repositories;
+
+ @Override
+ public String toString() {
+ return name().replace('_', ' ');
+ }
+ }
+
+ public TeamsTableModel() {
+ this(new ArrayList<TeamModel>());
+ }
+
+ public TeamsTableModel(List<TeamModel> teams) {
+ this.list = teams;
+ Collections.sort(this.list);
+ }
+
+ @Override
+ public int getRowCount() {
+ return list.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return Columns.values().length;
+ }
+
+ @Override
+ public String getColumnName(int column) {
+ Columns col = Columns.values()[column];
+ switch (col) {
+ case Name:
+ return Translation.get("gb.name");
+ case Members:
+ return Translation.get("gb.teamMembers");
+ case Repositories:
+ return Translation.get("gb.repositories");
+ }
+ return "";
+ }
+
+ /**
+ * Returns <code>Object.class</code> regardless of <code>columnIndex</code>.
+ *
+ * @param columnIndex
+ * the column being queried
+ * @return the Object.class
+ */
+ public Class<?> getColumnClass(int columnIndex) {
+ return String.class;
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ TeamModel model = list.get(rowIndex);
+ Columns col = Columns.values()[columnIndex];
+ switch (col) {
+ case Name:
+ return model.name;
+ case Members:
+ return model.users.size() == 0 ? "" : String.valueOf(model.users.size());
+ case Repositories:
+ return model.repositories.size() == 0 ? "" : String.valueOf(model.repositories.size());
+ }
+ return null;
+ }
+}
diff --git a/src/com/gitblit/client/UsersPanel.java b/src/com/gitblit/client/UsersPanel.java
index 5d31774f..0dfa0434 100644
--- a/src/com/gitblit/client/UsersPanel.java
+++ b/src/com/gitblit/client/UsersPanel.java
@@ -41,6 +41,7 @@ import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableRowSorter;
import com.gitblit.Constants.RpcRequest;
+import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
@@ -51,7 +52,7 @@ import com.gitblit.utils.StringUtils;
* @author James Moger
*
*/
-public class UsersPanel extends JPanel {
+public abstract class UsersPanel extends JPanel {
private static final long serialVersionUID = 1L;
@@ -111,6 +112,18 @@ public class UsersPanel extends JPanel {
String name = table.getColumnName(UsersTableModel.Columns.Name.ordinal());
table.setRowHeight(nameRenderer.getFont().getSize() + 8);
table.getColumn(name).setCellRenderer(nameRenderer);
+
+ int w = 125;
+ name = table.getColumnName(UsersTableModel.Columns.AccessLevel.ordinal());
+ table.getColumn(name).setMinWidth(w);
+ table.getColumn(name).setMaxWidth(w);
+ name = table.getColumnName(UsersTableModel.Columns.Teams.ordinal());
+ table.getColumn(name).setMinWidth(w);
+ table.getColumn(name).setMaxWidth(w);
+ name = table.getColumnName(UsersTableModel.Columns.Repositories.ordinal());
+ table.getColumn(name).setMinWidth(w);
+ table.getColumn(name).setMaxWidth(w);
+
table.setRowSorter(defaultSorter);
table.getRowSorter().toggleSortOrder(UsersTableModel.Columns.Name.ordinal());
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@@ -167,7 +180,7 @@ public class UsersPanel extends JPanel {
add(userTablePanel, BorderLayout.CENTER);
add(userControls, BorderLayout.SOUTH);
}
-
+
@Override
public void requestFocus() {
filterTextfield.requestFocus();
@@ -178,6 +191,8 @@ public class UsersPanel extends JPanel {
return Utils.INSETS;
}
+ protected abstract void updateTeamsTable();
+
protected void updateTable(boolean pack) {
tableModel.list.clear();
tableModel.list.addAll(gitblit.getUsers());
@@ -240,10 +255,12 @@ public class UsersPanel extends JPanel {
*
*/
protected void createUser() {
- EditUserDialog dialog = new EditUserDialog(gitblit.getSettings());
+ EditUserDialog dialog = new EditUserDialog(gitblit.getProtocolVersion(),
+ gitblit.getSettings());
dialog.setLocationRelativeTo(UsersPanel.this);
dialog.setUsers(gitblit.getUsers());
dialog.setRepositories(gitblit.getRepositories(), null);
+ dialog.setTeams(gitblit.getTeams(), null);
dialog.setVisible(true);
final UserModel newUser = dialog.getUser();
if (newUser == null) {
@@ -257,6 +274,9 @@ public class UsersPanel extends JPanel {
boolean success = gitblit.createUser(newUser);
if (success) {
gitblit.refreshUsers();
+ if (newUser.teams.size() > 0) {
+ gitblit.refreshTeams();
+ }
}
return success;
}
@@ -264,6 +284,9 @@ public class UsersPanel extends JPanel {
@Override
protected void onSuccess() {
updateTable(false);
+ if (newUser.teams.size() > 0) {
+ updateTeamsTable();
+ }
}
@Override
@@ -282,10 +305,13 @@ public class UsersPanel extends JPanel {
* @param user
*/
protected void editUser(final UserModel user) {
- EditUserDialog dialog = new EditUserDialog(user, gitblit.getSettings());
+ EditUserDialog dialog = new EditUserDialog(gitblit.getProtocolVersion(), user,
+ gitblit.getSettings());
dialog.setLocationRelativeTo(UsersPanel.this);
dialog.setUsers(gitblit.getUsers());
dialog.setRepositories(gitblit.getRepositories(), new ArrayList<String>(user.repositories));
+ dialog.setTeams(gitblit.getTeams(), user.teams == null ? null : new ArrayList<TeamModel>(
+ user.teams));
dialog.setVisible(true);
final UserModel revisedUser = dialog.getUser();
if (revisedUser == null) {
@@ -298,6 +324,7 @@ public class UsersPanel extends JPanel {
boolean success = gitblit.updateUser(user.username, revisedUser);
if (success) {
gitblit.refreshUsers();
+ gitblit.refreshTeams();
}
return success;
}
@@ -305,6 +332,7 @@ public class UsersPanel extends JPanel {
@Override
protected void onSuccess() {
updateTable(false);
+ updateTeamsTable();
}
@Override
@@ -336,6 +364,7 @@ public class UsersPanel extends JPanel {
}
if (success) {
gitblit.refreshUsers();
+ gitblit.refreshTeams();
}
return success;
}
@@ -343,6 +372,7 @@ public class UsersPanel extends JPanel {
@Override
protected void onSuccess() {
updateTable(false);
+ updateTeamsTable();
}
@Override
diff --git a/src/com/gitblit/client/UsersTableModel.java b/src/com/gitblit/client/UsersTableModel.java
index de282b8e..fa86a13e 100644
--- a/src/com/gitblit/client/UsersTableModel.java
+++ b/src/com/gitblit/client/UsersTableModel.java
@@ -36,7 +36,7 @@ public class UsersTableModel extends AbstractTableModel {
List<UserModel> list;
enum Columns {
- Name, AccessLevel;
+ Name, AccessLevel, Teams, Repositories;
@Override
public String toString() {
@@ -71,6 +71,10 @@ public class UsersTableModel extends AbstractTableModel {
return Translation.get("gb.name");
case AccessLevel:
return Translation.get("gb.accessLevel");
+ case Teams:
+ return Translation.get("gb.teamMemberships");
+ case Repositories:
+ return Translation.get("gb.repositories");
}
return "";
}
@@ -97,6 +101,13 @@ public class UsersTableModel extends AbstractTableModel {
if (model.canAdmin) {
return "administrator";
}
+ return "";
+ case Teams:
+ return (model.teams == null || model.teams.size() == 0) ? "" : String
+ .valueOf(model.teams.size());
+ case Repositories:
+ return (model.repositories == null || model.repositories.size() == 0) ? "" : String
+ .valueOf(model.repositories.size());
}
return null;
}
diff --git a/src/com/gitblit/utils/RpcUtils.java b/src/com/gitblit/utils/RpcUtils.java
index 387433a0..02a63a48 100644
--- a/src/com/gitblit/utils/RpcUtils.java
+++ b/src/com/gitblit/utils/RpcUtils.java
@@ -24,6 +24,7 @@ import java.util.Map;
import com.gitblit.Constants;
import com.gitblit.Constants.RpcRequest;
+import com.gitblit.GitBlitException.UnknownRequestException;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.FederationSet;
@@ -31,6 +32,7 @@ import com.gitblit.models.FeedModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.ServerSettings;
import com.gitblit.models.ServerStatus;
+import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.google.gson.reflect.TypeToken;
@@ -54,6 +56,9 @@ public class RpcUtils {
private static final Type USERS_TYPE = new TypeToken<Collection<UserModel>>() {
}.getType();
+ private static final Type TEAMS_TYPE = new TypeToken<Collection<TeamModel>>() {
+ }.getType();
+
private static final Type REGISTRATIONS_TYPE = new TypeToken<Collection<FederationModel>>() {
}.getType();
@@ -96,7 +101,28 @@ public class RpcUtils {
req = RpcRequest.LIST_REPOSITORIES;
}
return remoteURL + Constants.RPC_PATH + "?req=" + req.name().toLowerCase()
- + (name == null ? "" : ("&name=" + name));
+ + (name == null ? "" : ("&name=" + StringUtils.encodeURL(name)));
+ }
+
+ /**
+ * Returns the version of the RPC protocol on the server.
+ *
+ * @param serverUrl
+ * @param account
+ * @param password
+ * @return the protocol version
+ * @throws IOException
+ */
+ public static int getProtocolVersion(String serverUrl, String account, char[] password)
+ throws IOException {
+ String url = asLink(serverUrl, RpcRequest.GET_PROTOCOL);
+ int protocol = 1;
+ try {
+ protocol = JsonUtils.retrieveJson(url, Integer.class, account, password);
+ } catch (UnknownRequestException e) {
+ // v0.7.0 (protocol 1) did not have this request type
+ }
+ return protocol;
}
/**
@@ -135,6 +161,24 @@ public class RpcUtils {
}
/**
+ * Tries to pull the gitblit team definitions from the remote gitblit
+ * instance.
+ *
+ * @param serverUrl
+ * @param account
+ * @param password
+ * @return a collection of UserModel objects
+ * @throws IOException
+ */
+ public static List<TeamModel> getTeams(String serverUrl, String account, char[] password)
+ throws IOException {
+ String url = asLink(serverUrl, RpcRequest.LIST_TEAMS);
+ Collection<TeamModel> models = JsonUtils.retrieveJson(url, TEAMS_TYPE, account, password);
+ List<TeamModel> list = new ArrayList<TeamModel>(models);
+ return list;
+ }
+
+ /**
* Create a repository on the Gitblit server.
*
* @param repository
@@ -236,6 +280,53 @@ public class RpcUtils {
}
/**
+ * Create a team on the Gitblit server.
+ *
+ * @param team
+ * @param serverUrl
+ * @param account
+ * @param password
+ * @return true if the action succeeded
+ * @throws IOException
+ */
+ public static boolean createTeam(TeamModel team, String serverUrl, String account,
+ char[] password) throws IOException {
+ return doAction(RpcRequest.CREATE_TEAM, null, team, serverUrl, account, password);
+
+ }
+
+ /**
+ * Send a revised version of the team model to the Gitblit server.
+ *
+ * @param team
+ * @param serverUrl
+ * @param account
+ * @param password
+ * @return true if the action succeeded
+ * @throws IOException
+ */
+ public static boolean updateTeam(String teamname, TeamModel team, String serverUrl,
+ String account, char[] password) throws IOException {
+ return doAction(RpcRequest.EDIT_TEAM, teamname, team, serverUrl, account, password);
+
+ }
+
+ /**
+ * Deletes a team from the Gitblit server.
+ *
+ * @param team
+ * @param serverUrl
+ * @param account
+ * @param password
+ * @return true if the action succeeded
+ * @throws IOException
+ */
+ public static boolean deleteTeam(TeamModel team, String serverUrl, String account,
+ char[] password) throws IOException {
+ return doAction(RpcRequest.DELETE_TEAM, null, team, serverUrl, account, password);
+ }
+
+ /**
* Retrieves the list of users that can access the specified repository.
*
* @param repository
@@ -253,7 +344,7 @@ public class RpcUtils {
}
/**
- * Sets the repository membership list.
+ * Sets the repository user membership list.
*
* @param repository
* @param memberships
@@ -271,6 +362,41 @@ public class RpcUtils {
}
/**
+ * Retrieves the list of teams that can access the specified repository.
+ *
+ * @param repository
+ * @param serverUrl
+ * @param account
+ * @param password
+ * @return list of teams
+ * @throws IOException
+ */
+ public static List<String> getRepositoryTeams(RepositoryModel repository, String serverUrl,
+ String account, char[] password) throws IOException {
+ String url = asLink(serverUrl, RpcRequest.LIST_REPOSITORY_TEAMS, repository.name);
+ Collection<String> list = JsonUtils.retrieveJson(url, NAMES_TYPE, account, password);
+ return new ArrayList<String>(list);
+ }
+
+ /**
+ * Sets the repository team membership list.
+ *
+ * @param repository
+ * @param teams
+ * @param serverUrl
+ * @param account
+ * @param password
+ * @return true if the action succeeded
+ * @throws IOException
+ */
+ public static boolean setRepositoryTeams(RepositoryModel repository,
+ List<String> teams, String serverUrl, String account, char[] password)
+ throws IOException {
+ return doAction(RpcRequest.SET_REPOSITORY_TEAMS, repository.name, teams, serverUrl,
+ account, password);
+ }
+
+ /**
* Retrieves the list of federation registrations. These are the list of
* registrations that this Gitblit instance is pulling from.
*