Browse Source

RPC Client: Create/Edit Repository & User. Partially working.

Added new request type to retrieve Gitblit settings to implement the
password preferences (minLength, storage type) and federation sets.
tags/v0.7.0
James Moger 12 years ago
parent
commit
da0269b4bd

+ 1
- 0
docs/02_rpc.mkd View File

@@ -30,6 +30,7 @@ The Gitblit RPC mechanism, like the Gitblit JGit servlet, syndication/feed servl
<tr><td>LIST_FEDERATION_RESULTS</td><td>-</td><td><em>admin</em></td><td>-</td><td>List FederationModel</td></tr>
<tr><td>LIST_FEDERATION_PROPOSALS</td><td>-</td><td><em>admin</em></td><td>-</td><td>List FederationProposal </td></tr>
<tr><td>LIST_FEDERATION_SETS</td><td>-</td><td><em>admin</em></td><td>-</td><td>List FederationSet </td></tr>
<tr><td>LIST_SETTINGS</td><td>-</td><td><em>admin</em></td><td>-</td><td>Properties</td></tr>
</table>
### RPC Client

+ 1
- 1
src/com/gitblit/Constants.java View File

@@ -204,7 +204,7 @@ public class Constants {
LIST_REPOSITORIES, 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;
LIST_FEDERATION_PROPOSALS, LIST_FEDERATION_SETS, LIST_SETTINGS;
public static RpcRequest fromName(String name) {
for (RpcRequest type : values()) {

+ 12
- 0
src/com/gitblit/RpcServlet.java View File

@@ -22,6 +22,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -163,6 +164,17 @@ public class RpcServlet extends JsonServlet {
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
} else if (RpcRequest.LIST_SETTINGS.equals(reqType)) {
// return the server's settings
Properties settings = new Properties();
List<String> keys = GitBlit.getAllKeys(null);
for (String key:keys) {
String value = GitBlit.getString(key, null);
if (value != null) {
settings.put(key, value);
}
}
result = settings;
}
// send the result of the request

+ 224
- 0
src/com/gitblit/client/EditRepositoryDialog.java View File

@@ -0,0 +1,224 @@
/*
* 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.util.List;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.FederationStrategy;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
public class EditRepositoryDialog extends JDialog {
private static final long serialVersionUID = 1L;
private final RepositoryModel repository;
private boolean canceled = true;
private JTextField nameField;
private JTextField descriptionField;
private JCheckBox useTickets;
private JCheckBox useDocs;
private JCheckBox showRemoteBranches;
private JCheckBox showReadme;
private JCheckBox isFrozen;
private JComboBox accessRestriction;
private JComboBox federationStrategy;
private JComboBox owner;
private JPalette<String> usersPalette;
private JPalette<String> setsPalette;
public EditRepositoryDialog(List<UserModel> allusers) {
this(new RepositoryModel(), allusers);
setTitle("Create Repository");
}
public EditRepositoryDialog(RepositoryModel aRepository, List<UserModel> allUsers) {
super();
this.repository = new RepositoryModel();
initialize(aRepository, allUsers);
setModal(true);
setTitle("Edit Repository: " + aRepository.name);
setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());
}
private void initialize(RepositoryModel anRepository, List<UserModel> allUsers) {
nameField = new JTextField(anRepository.name == null ? "" : anRepository.name, 35);
descriptionField = new JTextField(anRepository.description == null ? ""
: anRepository.description, 35);
owner = new JComboBox(allUsers.toArray());
if (!StringUtils.isEmpty(anRepository.owner)) {
UserModel currentOwner = null;
for (UserModel user : allUsers) {
if (user.username.equalsIgnoreCase(anRepository.owner)) {
currentOwner = user;
break;
}
}
owner.setSelectedItem(currentOwner);
}
useTickets = new JCheckBox("distributed Ticgit issues", anRepository.useTickets);
useDocs = new JCheckBox("enumerates Markdown documentation in repository",
anRepository.useDocs);
showRemoteBranches = new JCheckBox("show remote branches", anRepository.showRemoteBranches);
showReadme = new JCheckBox("show a \"readme\" Markdown file on the summary page",
anRepository.showReadme);
isFrozen = new JCheckBox("deny push operations", anRepository.isFrozen);
accessRestriction = new JComboBox(AccessRestrictionType.values());
accessRestriction.setSelectedItem(anRepository.accessRestriction);
federationStrategy = new JComboBox(FederationStrategy.values());
federationStrategy.setSelectedItem(anRepository.federationStrategy);
JPanel fieldsPanel = new JPanel(new GridLayout(0, 1));
fieldsPanel.add(newFieldPanel("name", nameField));
fieldsPanel.add(newFieldPanel("description", descriptionField));
fieldsPanel.add(newFieldPanel("owner", owner));
fieldsPanel.add(newFieldPanel("enable tickets", useTickets));
fieldsPanel.add(newFieldPanel("enable docs", useDocs));
fieldsPanel.add(newFieldPanel("show remote branches", showRemoteBranches));
fieldsPanel.add(newFieldPanel("show readme", showReadme));
fieldsPanel.add(newFieldPanel("is frozen", isFrozen));
usersPalette = new JPalette<String>();
JPanel accessPanel = new JPanel(new BorderLayout(5, 5));
accessPanel.add(newFieldPanel("access restriction", accessRestriction), BorderLayout.NORTH);
accessPanel.add(newFieldPanel("permitted users", usersPalette), BorderLayout.CENTER);
setsPalette = new JPalette<String>();
JPanel federationPanel = new JPanel(new BorderLayout(5, 5));
federationPanel.add(newFieldPanel("federation strategy", federationStrategy),
BorderLayout.NORTH);
federationPanel.add(newFieldPanel("federation sets", setsPalette), BorderLayout.CENTER);
JPanel panel = new JPanel(new BorderLayout(5, 5));
panel.add(fieldsPanel, BorderLayout.NORTH);
panel.add(accessPanel, BorderLayout.CENTER);
panel.add(federationPanel, BorderLayout.SOUTH);
JButton createButton = new JButton("Save");
createButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
if (validateFields()) {
canceled = false;
setVisible(false);
}
}
});
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
canceled = true;
setVisible(false);
}
});
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;
@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();
setLocationRelativeTo(null);
}
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() {
// TODO validate input and populate model
return true;
}
private void showValidationError(String message) {
JOptionPane.showMessageDialog(EditRepositoryDialog.this, message, "Validation Error",
JOptionPane.ERROR_MESSAGE);
}
public void setUsers(List<String> all, List<String> selected) {
usersPalette.setObjects(all, selected);
}
public void setFederationSets(List<String> all, List<String> selected) {
setsPalette.setObjects(all, selected);
}
public RepositoryModel getRepository() {
if (canceled) {
return null;
}
return repository;
}
}

+ 237
- 0
src/com/gitblit/client/EditUserDialog.java View File

@@ -0,0 +1,237 @@
/*
* 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.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
public class EditUserDialog extends JDialog {
private static final long serialVersionUID = 1L;
private final UserModel user;
private final IStoredSettings settings;
private boolean canceled = true;
private JTextField usernameField;
private JPasswordField passwordField;
private JPasswordField confirmPasswordField;
private JCheckBox canAdminCheckbox;
private JCheckBox notFederatedCheckbox;
private JPalette<String> repositoryPalette;
public EditUserDialog(IStoredSettings settings) {
this(new UserModel(""), settings);
setTitle("Create User");
}
public EditUserDialog(UserModel anUser, IStoredSettings settings) {
super();
this.user = new UserModel("");
this.settings = settings;
initialize(anUser);
setModal(true);
setTitle("Edit User: " + anUser.username);
setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());
}
private void initialize(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,
25);
canAdminCheckbox = new JCheckBox("can administer Gitblit server", anUser.canAdmin);
notFederatedCheckbox = new JCheckBox(
"block federated Gitblit instances from pulling this account",
anUser.excludeFromFederation);
JPanel fieldsPanel = new JPanel(new GridLayout(0, 1));
fieldsPanel.add(newFieldPanel("username", usernameField));
fieldsPanel.add(newFieldPanel("password", passwordField));
fieldsPanel.add(newFieldPanel("confirm password", confirmPasswordField));
fieldsPanel.add(newFieldPanel("can admin", canAdminCheckbox));
fieldsPanel.add(newFieldPanel("exclude from federation", notFederatedCheckbox));
repositoryPalette = new JPalette<String>();
JPanel panel = new JPanel(new BorderLayout());
panel.add(fieldsPanel, BorderLayout.NORTH);
panel.add(newFieldPanel("restricted repositories", repositoryPalette), BorderLayout.CENTER);
JButton createButton = new JButton("Save");
createButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
if (validateFields()) {
canceled = false;
setVisible(false);
}
}
});
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
canceled = true;
setVisible(false);
}
});
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;
@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();
setLocationRelativeTo(null);
}
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 uname = usernameField.getText();
if (StringUtils.isEmpty(uname)) {
showValidationError("Please enter a username!");
return false;
}
// TODO verify username uniqueness on create
// if (isCreate) {
// UserModel model = GitBlit.self().getUserModel(username);
// if (model != null) {
// error(MessageFormat.format("Username ''{0}'' is unavailable.",
// username));
// return;
// }
// }
int minLength = settings.getInteger(Keys.realm.minPasswordLength, 5);
if (minLength < 4) {
minLength = 4;
}
char[] pw = passwordField.getPassword();
if (pw == null || pw.length < minLength) {
showValidationError(MessageFormat.format(
"Password is too short. Minimum length is {0} characters.", minLength));
return false;
}
char[] cpw = confirmPasswordField.getPassword();
if (cpw == null || cpw.length != pw.length) {
showValidationError("Please confirm the password!");
return false;
}
if (!Arrays.equals(pw, cpw)) {
showValidationError("Passwords do not match!");
return false;
}
user.username = uname;
String type = settings.getString(Keys.realm.passwordStorage, "md5");
if (type.equalsIgnoreCase("md5")) {
// store MD5 digest of password
user.password = StringUtils.MD5_TYPE + StringUtils.getMD5(new String(pw));
} else {
user.password = new String(pw);
}
user.canAdmin = canAdminCheckbox.isSelected();
user.excludeFromFederation = notFederatedCheckbox.isSelected();
user.repositories.clear();
user.repositories.addAll(repositoryPalette.getSelections());
return true;
}
private void showValidationError(String message) {
JOptionPane.showMessageDialog(EditUserDialog.this, message, "Validation Error",
JOptionPane.ERROR_MESSAGE);
}
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 UserModel getUser() {
if (canceled) {
return null;
}
return user;
}
}

+ 5
- 3
src/com/gitblit/client/GitblitClient.java View File

@@ -148,13 +148,13 @@ public class GitblitClient extends JFrame {
}
reg = new GitblitRegistration(nameField.getText(), url, accountField.getText(),
passwordField.getPassword());
login(reg);
boolean success = login(reg);
registrations.add(0, reg);
rebuildRecentMenu();
return true;
return success;
}
private void login(GitblitRegistration reg) {
private boolean login(GitblitRegistration reg) {
try {
GitblitPanel panel = new GitblitPanel(reg);
panel.login();
@@ -163,10 +163,12 @@ public class GitblitClient extends JFrame {
serverTabs.setSelectedIndex(idx);
serverTabs.setTabComponentAt(idx, new ClosableTabComponent(reg.name, null, serverTabs,
panel));
return true;
} catch (IOException e) {
JOptionPane.showMessageDialog(GitblitClient.this, e.getMessage(), "Error",
JOptionPane.ERROR_MESSAGE);
}
return false;
}
private void rebuildRecentMenu() {

+ 8
- 0
src/com/gitblit/client/GitblitClientLauncher.java View File

@@ -25,6 +25,7 @@ import java.io.IOException;
import java.util.Collections;
import java.util.List;
import com.gitblit.Constants;
import com.gitblit.Launcher;
import com.gitblit.build.Build;
import com.gitblit.build.Build.DownloadListener;
@@ -82,6 +83,8 @@ public class GitblitClientLauncher {
if (g != null) {
// Splash is 320x120
FontMetrics fm = g.getFontMetrics();
// paint startup status
g.setColor(Color.darkGray);
int h = fm.getHeight() + fm.getMaxDescent();
int x = 5;
@@ -93,6 +96,11 @@ public class GitblitClientLauncher {
g.setColor(Color.WHITE);
int xw = fm.stringWidth(string);
g.drawString(string, x + ((w - xw) / 2), y - 5);
// paint version
String ver = "v" + Constants.VERSION;
int vw = g.getFontMetrics().stringWidth(ver);
g.drawString(ver, 320 - vw - 5, 34);
g.dispose();
splash.update();
}

+ 376
- 23
src/com/gitblit/client/GitblitPanel.java View File

@@ -20,6 +20,7 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -27,6 +28,7 @@ import java.io.IOException;
import java.net.URI;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -34,6 +36,7 @@ import java.util.Map;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
@@ -41,6 +44,7 @@ import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
@@ -49,7 +53,11 @@ import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableRowSorter;
import com.gitblit.Constants.RpcRequest;
import com.gitblit.GitBlitException.ForbiddenException;
import com.gitblit.GitBlitException.UnauthorizedException;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.client.ClosableTabComponent.CloseTabListener;
import com.gitblit.models.FederationModel;
import com.gitblit.models.RepositoryModel;
@@ -72,13 +80,17 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
private final Insets insets = new Insets(margin, margin, margin, margin);
private String url;
private final String url;
private String account;
private final String account;
private char[] password;
private final char[] password;
private boolean isAdmin;
private volatile boolean isAdmin;
private volatile List<UserModel> allUsers;
private volatile IStoredSettings settings;
private JTabbedPane tabs;
@@ -104,6 +116,8 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
private TableRowSorter<RepositoriesModel> defaultSorter;
private List<RepositoryModel> allRepositories;
public GitblitPanel(GitblitRegistration reg) {
this(reg.url, reg.account, reg.password);
}
@@ -128,10 +142,25 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
}
});
JButton refreshRepositories = new JButton("Refresh");
refreshRepositories.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
refreshRepositoriesTable();
} catch (ForbiddenException x) {
explainForbidden(RpcRequest.LIST_REPOSITORIES);
} catch (UnauthorizedException x) {
explainUnauthorized(RpcRequest.LIST_REPOSITORIES);
} catch (Throwable t) {
showException(t);
}
}
});
createRepository = new JButton("Create");
createRepository.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("TODO Create Repository");
createRepository();
}
});
@@ -139,9 +168,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
editRepository.setEnabled(false);
editRepository.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (RepositoryModel model : getSelectedRepositories()) {
System.out.println("TODO Edit " + model);
}
editRepository(getSelectedRepositories().get(0));
}
});
@@ -149,9 +176,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
delRepository.setEnabled(false);
delRepository.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (RepositoryModel model : getSelectedRepositories()) {
System.out.println("TODO Delete " + model);
}
deleteRepositories(getSelectedRepositories());
}
});
@@ -165,7 +190,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
}
});
nameRenderer = new NameRenderer(Color.gray, new Color(0x00, 0x69, 0xD6));
nameRenderer = new NameRenderer();
typeRenderer = new TypeRenderer();
sizeRenderer = new DefaultTableCellRenderer();
@@ -246,10 +271,25 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
repositoriesPanel.add(tablePanel, BorderLayout.CENTER);
repositoriesPanel.add(repositoryControls, BorderLayout.SOUTH);
JButton refreshUsers = new JButton("Refresh");
refreshUsers.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
refreshUsersTable();
} catch (ForbiddenException x) {
explainForbidden(RpcRequest.LIST_USERS);
} catch (UnauthorizedException x) {
explainUnauthorized(RpcRequest.LIST_USERS);
} catch (Throwable t) {
showException(t);
}
}
});
JButton createUser = new JButton("Create");
createUser.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("TODO Create User");
createUser();
}
});
@@ -257,9 +297,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
editUser.setEnabled(false);
editUser.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (UserModel user : getSelectedUsers()) {
System.out.println("TODO Edit " + user);
}
editUser(getSelectedUsers().get(0));
}
});
@@ -267,9 +305,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
delUser.setEnabled(false);
delUser.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (UserModel user : getSelectedUsers()) {
System.out.println("TODO Delete " + user);
}
deleteUsers(getSelectedUsers());
}
});
@@ -288,7 +324,8 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
}
});
JPanel userControls = new JPanel();
JPanel userControls = new JPanel(new GridLayout(0, 2));
userControls.add(refreshUsers);
userControls.add(createUser);
userControls.add(editUser);
userControls.add(delUser);
@@ -327,6 +364,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
try {
refreshUsersTable();
refreshSettings();
isAdmin = true;
refreshFederationPanel();
} catch (ForbiddenException e) {
@@ -348,8 +386,10 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
private void refreshRepositoriesTable() throws IOException {
Map<String, RepositoryModel> repositories = RpcUtils
.getRepositories(url, account, password);
allRepositories = new ArrayList<RepositoryModel>(repositories.values());
Collections.sort(allRepositories);
repositoriesModel.list.clear();
repositoriesModel.list.addAll(repositories.values());
repositoriesModel.list.addAll(allRepositories);
repositoriesModel.fireTableDataChanged();
packColumns(repositoriesTable, 2);
}
@@ -360,8 +400,12 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
}
private void refreshUsersTable() throws IOException {
List<UserModel> users = RpcUtils.getUsers(url, account, password);
usersList.setListData(users.toArray());
allUsers = RpcUtils.getUsers(url, account, password);
usersList.setListData(allUsers.toArray());
}
private void refreshSettings() throws IOException {
settings = RpcUtils.getSettings(url, account, password);
}
private void refreshFederationPanel() throws IOException {
@@ -465,4 +509,313 @@ public class GitblitPanel extends JPanel implements CloseTabListener {
@Override
public void closeTab(Component c) {
}
/**
* Displays the create repository dialog and fires a SwingWorker to update
* the server, if appropriate.
*
*/
protected void createRepository() {
EditRepositoryDialog dialog = new EditRepositoryDialog(allUsers);
dialog.setVisible(true);
final RepositoryModel newRepository = dialog.getRepository();
if (newRepository == null) {
return;
}
final RpcRequest request = RpcRequest.CREATE_REPOSITORY;
SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws IOException {
return RpcUtils.createRepository(newRepository, url, account, password);
}
@Override
protected void done() {
try {
boolean success = get();
if (success) {
refreshRepositoriesTable();
} else {
String msg = MessageFormat.format(
"Failed to execute request \"{0}\" for repository \"{1}\".",
request.name(), newRepository.name);
JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
JOptionPane.ERROR_MESSAGE);
}
} catch (ForbiddenException e) {
explainForbidden(request);
} catch (UnauthorizedException e) {
explainUnauthorized(request);
} catch (Throwable t) {
showException(t);
}
}
};
worker.execute();
}
/**
* Displays the edit repository dialog and fires a SwingWorker to update the
* server, if appropriate.
*
* @param repository
*/
protected void editRepository(final RepositoryModel repository) {
EditRepositoryDialog dialog = new EditRepositoryDialog(repository, allUsers);
List<String> usernames = new ArrayList<String>();
for (UserModel user : this.allUsers) {
usernames.add(user.username);
}
Collections.sort(usernames);
dialog.setUsers(usernames, null);
dialog.setFederationSets(settings.getStrings(Keys.federation.sets),
repository.federationSets);
dialog.setVisible(true);
final RepositoryModel revisedRepository = dialog.getRepository();
if (revisedRepository == null) {
return;
}
final RpcRequest request = RpcRequest.EDIT_REPOSITORY;
SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws IOException {
return RpcUtils.updateRepository(repository.name, revisedRepository, url, account,
password);
}
@Override
protected void done() {
try {
boolean success = get();
if (success) {
refreshRepositoriesTable();
} else {
String msg = MessageFormat.format(
"Failed to execute request \"{0}\" for repository \"{1}\".",
request.name(), repository.name);
JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
JOptionPane.ERROR_MESSAGE);
}
} catch (ForbiddenException e) {
explainForbidden(request);
} catch (UnauthorizedException e) {
explainUnauthorized(request);
} catch (Throwable t) {
showException(t);
}
}
};
worker.execute();
}
protected void deleteRepositories(final List<RepositoryModel> repositories) {
if (repositories == null || repositories.size() == 0) {
return;
}
StringBuilder message = new StringBuilder("Delete the following repositories?\n\n");
for (RepositoryModel repository : repositories) {
message.append(repository.name).append("\n");
}
int result = JOptionPane.showConfirmDialog(GitblitPanel.this, message.toString(),
"Delete Repositories?", JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION) {
final RpcRequest request = RpcRequest.DELETE_REPOSITORY;
SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
boolean success = true;
for (RepositoryModel repository : repositories) {
success &= RpcUtils.deleteRepository(repository, url, account, password);
}
return success;
}
@Override
protected void done() {
try {
boolean success = get();
if (success) {
refreshRepositoriesTable();
} else {
String msg = "Failed to delete specified repositories!";
JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
JOptionPane.ERROR_MESSAGE);
}
} catch (ForbiddenException e) {
explainForbidden(request);
} catch (UnauthorizedException e) {
explainUnauthorized(request);
} catch (Throwable t) {
showException(t);
}
}
};
worker.execute();
}
}
/**
* Displays the create user dialog and fires a SwingWorker to update the
* server, if appropriate.
*
*/
protected void createUser() {
EditUserDialog dialog = new EditUserDialog(settings);
dialog.setRepositories(allRepositories, null);
dialog.setVisible(true);
final UserModel newUser = dialog.getUser();
if (newUser == null) {
return;
}
final RpcRequest request = RpcRequest.CREATE_USER;
SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws IOException {
return RpcUtils.createUser(newUser, url, account, password);
}
@Override
protected void done() {
try {
boolean success = get();
if (success) {
refreshUsersTable();
} else {
String msg = MessageFormat.format(
"Failed to execute request \"{0}\" for user \"{1}\".",
request.name(), newUser.username);
JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
JOptionPane.ERROR_MESSAGE);
}
} catch (ForbiddenException e) {
explainForbidden(request);
} catch (UnauthorizedException e) {
explainUnauthorized(request);
} catch (Throwable t) {
showException(t);
}
}
};
worker.execute();
}
/**
* Displays the edit user dialog and fires a SwingWorker to update the
* server, if appropriate.
*
* @param user
*/
protected void editUser(final UserModel user) {
EditUserDialog dialog = new EditUserDialog(user, settings);
dialog.setRepositories(allRepositories, new ArrayList<String>(user.repositories));
dialog.setVisible(true);
final UserModel revisedUser = dialog.getUser();
if (revisedUser == null) {
return;
}
final RpcRequest request = RpcRequest.EDIT_USER;
SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws IOException {
return RpcUtils.updateUser(user.username, revisedUser, url, account, password);
}
@Override
protected void done() {
try {
boolean success = get();
if (success) {
refreshUsersTable();
} else {
String msg = MessageFormat.format(
"Failed to execute request \"{0}\" for user \"{1}\".",
request.name(), user.username);
JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
JOptionPane.ERROR_MESSAGE);
}
} catch (ForbiddenException e) {
explainForbidden(request);
} catch (UnauthorizedException e) {
explainUnauthorized(request);
} catch (Throwable t) {
showException(t);
}
}
};
worker.execute();
}
protected void deleteUsers(final List<UserModel> users) {
if (users == null || users.size() == 0) {
return;
}
StringBuilder message = new StringBuilder("Delete the following users?\n\n");
for (UserModel user : users) {
message.append(user.username).append("\n");
}
int result = JOptionPane.showConfirmDialog(GitblitPanel.this, message.toString(),
"Delete Users?", JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION) {
final RpcRequest request = RpcRequest.DELETE_USER;
SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
boolean success = true;
for (UserModel user : users) {
success &= RpcUtils.deleteUser(user, url, account, password);
}
return success;
}
@Override
protected void done() {
try {
boolean success = get();
if (success) {
refreshUsersTable();
} else {
String msg = "Failed to delete specified users!";
JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Error!",
JOptionPane.ERROR_MESSAGE);
}
} catch (ForbiddenException e) {
explainForbidden(request);
} catch (UnauthorizedException e) {
explainUnauthorized(request);
} catch (Throwable t) {
showException(t);
}
}
};
worker.execute();
}
}
private void explainForbidden(RpcRequest request) {
String msg = MessageFormat.format(
"The request \"{0}\" has been forbidden by the Gitblit server @ {1}.",
request.name(), url);
JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Forbidden",
JOptionPane.ERROR_MESSAGE);
}
private void explainUnauthorized(RpcRequest request) {
String msg = MessageFormat.format(
"The account \"{0}\" is not authorized to execute the request \"{1}\".", account,
request.name());
JOptionPane.showMessageDialog(GitblitPanel.this, msg, "Unauthorized",
JOptionPane.ERROR_MESSAGE);
}
private void showException(Throwable t) {
// TODO show the unexpected exception
}
}

+ 177
- 0
src/com/gitblit/client/JPalette.java View File

@@ -0,0 +1,177 @@
/*
* 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.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
public class JPalette<T> extends JPanel {
private static final long serialVersionUID = 1L;
private PaletteModel<T> availableModel;
private PaletteModel<T> selectedModel;
public JPalette() {
super(new BorderLayout(5, 5));
availableModel = new PaletteModel<T>();
selectedModel = new PaletteModel<T>();
final JTable available = new JTable(availableModel);
final JTable selected = new JTable(selectedModel);
JButton add = new JButton("->");
add.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
List<T> move = new ArrayList<T>();
if (available.getSelectedRowCount() <= 0) {
return;
}
for (int row : available.getSelectedRows()) {
int modelIndex = available.convertRowIndexToModel(row);
T item = (T) availableModel.list.get(modelIndex);
move.add(item);
}
availableModel.list.removeAll(move);
selectedModel.list.addAll(move);
availableModel.fireTableDataChanged();
selectedModel.fireTableDataChanged();
}
});
JButton subtract = new JButton("<-");
subtract.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
List<T> move = new ArrayList<T>();
if (selected.getSelectedRowCount() <= 0) {
return;
}
for (int row : selected.getSelectedRows()) {
int modelIndex = selected.convertRowIndexToModel(row);
T item = (T) selectedModel.list.get(modelIndex);
move.add(item);
}
selectedModel.list.removeAll(move);
availableModel.list.addAll(move);
selectedModel.fireTableDataChanged();
availableModel.fireTableDataChanged();
}
});
JPanel controls = new JPanel(new GridLayout(0, 1, 0, 5));
controls.add(add);
controls.add(subtract);
JPanel center = new JPanel(new GridBagLayout());
center.add(controls);
add(newListPanel("Available", available), BorderLayout.WEST);
add(center, BorderLayout.CENTER);
add(newListPanel("Selected", selected), BorderLayout.EAST);
}
private JPanel newListPanel(String label, JTable table) {
NameRenderer nameRenderer = new NameRenderer();
table.setCellSelectionEnabled(false);
table.setRowSelectionAllowed(true);
table.setRowHeight(nameRenderer.getFont().getSize() + 8);
table.getTableHeader().setReorderingAllowed(false);
table.setGridColor(new Color(0xd9d9d9));
table.setBackground(Color.white);
table.getColumn(table.getColumnName(0)).setCellRenderer(nameRenderer);
JScrollPane jsp = new JScrollPane(table);
jsp.setPreferredSize(new Dimension(225, 175));
JPanel panel = new JPanel(new BorderLayout());
panel.add(new JLabel(label), BorderLayout.NORTH);
panel.add(jsp, BorderLayout.CENTER);
return panel;
}
public void setObjects(List<T> all, List<T> selected) {
List<T> available = new ArrayList<T>(all);
if (selected != null) {
available.removeAll(selected);
}
availableModel.list.clear();
availableModel.list.addAll(available);
availableModel.fireTableDataChanged();
if (selected != null) {
selectedModel.list.clear();
selectedModel.list.addAll(selected);
selectedModel.fireTableDataChanged();
}
}
public List<T> getSelections() {
return new ArrayList<T>(selectedModel.list);
}
public class PaletteModel<K> extends AbstractTableModel {
private static final long serialVersionUID = 1L;
List<K> list;
public PaletteModel() {
this(new ArrayList<K>());
}
public PaletteModel(List<K> list) {
this.list = new ArrayList<K>(list);
}
@Override
public int getRowCount() {
return list.size();
}
@Override
public int getColumnCount() {
return 1;
}
@Override
public String getColumnName(int column) {
return "Name";
}
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
K o = list.get(rowIndex);
return o.toString();
}
}
}

+ 4
- 0
src/com/gitblit/client/NameRenderer.java View File

@@ -34,6 +34,10 @@ public class NameRenderer extends DefaultTableCellRenderer {
final String groupSpan;
public NameRenderer() {
this(Color.gray, new Color(0x00, 0x69, 0xD6));
}
public NameRenderer(Color group, Color repo) {
groupSpan = "<span style='color:" + getHexColor(group) + "'>";
setForeground(repo);

+ 19
- 0
src/com/gitblit/utils/JsonUtils.java View File

@@ -157,6 +157,25 @@ public class JsonUtils {
}
return gson().fromJson(json, type);
}
/**
* Reads a gson object from the specified url.
*
* @param url
* @param clazz
* @param username
* @param password
* @return the deserialized object
* @throws {@link IOException}
*/
public static <X> X retrieveJson(String url, Class<X> clazz, String username, char[] password)
throws IOException {
String json = retrieveJsonString(url, username, password);
if (StringUtils.isEmpty(json)) {
return null;
}
return gson().fromJson(json, clazz);
}
/**
* Retrieves a JSON message.

+ 53
- 8
src/com/gitblit/utils/RpcUtils.java View File

@@ -21,9 +21,11 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import com.gitblit.Constants;
import com.gitblit.Constants.RpcRequest;
import com.gitblit.IStoredSettings;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.FederationSet;
@@ -294,7 +296,7 @@ public class RpcUtils {
List<FederationModel> list = new ArrayList<FederationModel>(registrations);
return list;
}
/**
* Retrieves the list of federation proposals.
*
@@ -304,15 +306,15 @@ public class RpcUtils {
* @return a collection of FederationProposal objects
* @throws IOException
*/
public static List<FederationProposal> getFederationProposals(String serverUrl,
String account, char[] password) throws IOException {
public static List<FederationProposal> getFederationProposals(String serverUrl, String account,
char[] password) throws IOException {
String url = asLink(serverUrl, RpcRequest.LIST_FEDERATION_PROPOSALS);
Collection<FederationProposal> proposals = JsonUtils.retrieveJson(url, PROPOSALS_TYPE,
account, password);
List<FederationProposal> list = new ArrayList<FederationProposal>(proposals);
return list;
}
/**
* Retrieves the list of federation repository sets.
*
@@ -322,15 +324,31 @@ public class RpcUtils {
* @return a collection of FederationSet objects
* @throws IOException
*/
public static List<FederationSet> getFederationSets(String serverUrl,
String account, char[] password) throws IOException {
public static List<FederationSet> getFederationSets(String serverUrl, String account,
char[] password) throws IOException {
String url = asLink(serverUrl, RpcRequest.LIST_FEDERATION_SETS);
Collection<FederationSet> sets = JsonUtils.retrieveJson(url, SETS_TYPE,
account, password);
Collection<FederationSet> sets = JsonUtils.retrieveJson(url, SETS_TYPE, account, password);
List<FederationSet> list = new ArrayList<FederationSet>(sets);
return list;
}
/**
* Retrieves the settings of the Gitblit server.
*
* @param serverUrl
* @param account
* @param password
* @return an IStoredSettings object
* @throws IOException
*/
public static IStoredSettings getSettings(String serverUrl, String account, char[] password)
throws IOException {
String url = asLink(serverUrl, RpcRequest.LIST_SETTINGS);
Properties props = JsonUtils.retrieveJson(url, Properties.class, account, password);
RpcSettings settings = new RpcSettings(props);
return settings;
}
/**
* Do the specified administrative action on the Gitblit server.
*
@@ -351,4 +369,31 @@ public class RpcUtils {
int resultCode = JsonUtils.sendJsonString(url, json, account, password);
return resultCode == 200;
}
/**
* Settings implementation that wraps a retrieved properties instance. This
* class is used for RPC communication.
*
* @author James Moger
*
*/
private static class RpcSettings extends IStoredSettings {
private final Properties properties = new Properties();
public RpcSettings(Properties props) {
super(RpcSettings.class);
properties.putAll(props);
}
@Override
protected Properties read() {
return properties;
}
@Override
public String toString() {
return "RpcSettings";
}
}
}

+ 2
- 2
src/com/gitblit/wicket/GitBlitWebApp.properties View File

@@ -92,7 +92,7 @@ gb.isFrozen = is frozen
gb.isFrozenDescription = deny push operations
gb.zip = zip
gb.showReadme = show readme
gb.showReadmeDescription = show a \"readme\" markdown file on the summary page
gb.showReadmeDescription = show a \"readme\" Markdown file on the summary page
gb.nameDescription = use '/' to group repositories. e.g. libraries/mycoollib.git
gb.ownerDescription = the owner may edit repository settings
gb.blob = blob
@@ -106,7 +106,7 @@ gb.isFederated = is federated
gb.federateThis = federate this repository
gb.federateOrigin = federate the origin
gb.excludeFromFederation = exclude from federation
gb.excludeFromFederationDescription = block federated Gitblit instances from pulling this object
gb.excludeFromFederationDescription = block federated Gitblit instances from pulling this account
gb.tokens = federation tokens
gb.tokenAllDescription = all repositories, users, & settings
gb.tokenUnrDescription = all repositories & users

+ 6
- 0
tests/com/gitblit/tests/RpcTests.java View File

@@ -23,6 +23,7 @@ import junit.framework.TestCase;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.GitBlitException.UnauthorizedException;
import com.gitblit.IStoredSettings;
import com.gitblit.models.FederationModel;
import com.gitblit.models.FederationProposal;
import com.gitblit.models.FederationSet;
@@ -203,4 +204,9 @@ public class RpcTests extends TestCase {
List<FederationSet> sets = RpcUtils.getFederationSets(url, account, password.toCharArray());
assertTrue("No federation sets were retrieved!", sets.size() > 0);
}
public void testSettings() throws Exception {
IStoredSettings settings = RpcUtils.getSettings(url, account, password.toCharArray());
assertTrue("No settings were retrieved!", settings.getAllKeys(null).size() > 0);
}
}

Loading…
Cancel
Save