From d03aff630cbcd49f02d51f08ec59ac3cf7f41d0e Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Sun, 23 Oct 2011 10:25:39 -0400
Subject: [PATCH] Separate management from administration in rpc servlet.

---
 src/com/gitblit/GitBlit.java              |   28 ++++++---
 src/com/gitblit/RpcFilter.java            |   17 +++--
 src/com/gitblit/client/GitblitClient.java |   27 +++++++--
 src/com/gitblit/client/GitblitPanel.java  |   32 +++++++---
 src/com/gitblit/utils/RpcUtils.java       |   26 ++++++++
 distrib/gitblit.properties                |   12 +++
 src/com/gitblit/RpcServlet.java           |   16 +++++
 src/com/gitblit/Constants.java            |    2 
 8 files changed, 122 insertions(+), 38 deletions(-)

diff --git a/distrib/gitblit.properties b/distrib/gitblit.properties
index d5e4572..28a6db8 100644
--- a/distrib/gitblit.properties
+++ b/distrib/gitblit.properties
@@ -93,8 +93,16 @@
 # SINCE 0.7.0 
 web.enableRpcServlet = true
 
-# Allows remote clients to administer the Gitblit instance, if the authenticated
-# account has administrator permissions.  Requires *web.enableRpcServlet=true*.
+# Allows remote clients to manage repositories and users of the Gitblit instance,
+# if the authenticated account has administrator permissions.
+# Requires *web.enableRpcServlet=true*.
+#
+# SINCE 0.7.0 
+web.enableRpcManagement = false
+
+# Allows remote clients to control the server settings of the Gitblit instance,
+# if the authenticated account has administrator permissions.
+# Requires *web.enableRpcServlet=true* and *web.enableRpcManagement*.
 #
 # SINCE 0.7.0 
 web.enableRpcAdministration = false
diff --git a/src/com/gitblit/Constants.java b/src/com/gitblit/Constants.java
index 79dfaf6..450c11f 100644
--- a/src/com/gitblit/Constants.java
+++ b/src/com/gitblit/Constants.java
@@ -204,7 +204,7 @@
 		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_SETTINGS,
+		LIST_FEDERATION_PROPOSALS, LIST_FEDERATION_SETS, LIST_SETTINGS, EDIT_SETTINGS,
 		LIST_STATUS;
 
 		public static RpcRequest fromName(String name) {
diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java
index 6f537ec..49f93e4 100644
--- a/src/com/gitblit/GitBlit.java
+++ b/src/com/gitblit/GitBlit.java
@@ -25,6 +25,7 @@
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -67,9 +68,9 @@
 import com.gitblit.models.Metric;
 import com.gitblit.models.ObjectCache;
 import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.ServerSettings;
 import com.gitblit.models.ServerStatus;
 import com.gitblit.models.SettingModel;
-import com.gitblit.models.ServerSettings;
 import com.gitblit.models.UserModel;
 import com.gitblit.utils.ByteFormat;
 import com.gitblit.utils.FederationUtils;
@@ -244,6 +245,17 @@
 	 */
 	public static boolean isDebugMode() {
 		return self().settings.getBoolean(Keys.web.debugMode, false);
+	}
+
+	/**
+	 * Updates the list of server settings.
+	 * 
+	 * @param settings
+	 * @return true if the update succeeded
+	 */
+	public boolean updateSettings(Collection<SettingModel> settings) {
+		// TODO update the settings
+		return false;
 	}
 
 	public ServerStatus getStatus() {
@@ -442,10 +454,9 @@
 			throws GitBlitException {
 		if (!username.equalsIgnoreCase(user.username)) {
 			if (userService.getUserModel(user.username) != null) {
-				throw new GitBlitException(
-						MessageFormat
-								.format("Failed to rename ''{0}'' because ''{1}'' already exists.",
-										username, user.username));
+				throw new GitBlitException(MessageFormat.format(
+						"Failed to rename ''{0}'' because ''{1}'' already exists.", username,
+						user.username));
 			}
 		}
 		if (!userService.updateUserModel(username, user)) {
@@ -735,10 +746,9 @@
 					repository.name += org.eclipse.jgit.lib.Constants.DOT_GIT_EXT;
 				}
 				if (new File(repositoriesFolder, repository.name).exists()) {
-					throw new GitBlitException(
-							MessageFormat
-									.format("Failed to rename ''{0}'' because ''{1}'' already exists.",
-											repositoryName, repository.name));
+					throw new GitBlitException(MessageFormat.format(
+							"Failed to rename ''{0}'' because ''{1}'' already exists.",
+							repositoryName, repository.name));
 				}
 				closeRepository(repositoryName);
 				File folder = new File(repositoriesFolder, repositoryName);
diff --git a/src/com/gitblit/RpcFilter.java b/src/com/gitblit/RpcFilter.java
index 2786f2a..551ca3c 100644
--- a/src/com/gitblit/RpcFilter.java
+++ b/src/com/gitblit/RpcFilter.java
@@ -60,7 +60,7 @@
 		String fullUrl = getFullUrl(httpRequest);
 		RpcRequest requestType = RpcRequest.fromName(httpRequest.getParameter("req"));
 		if (requestType == null) {
-			httpResponse.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);			
+			httpResponse.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
 			return;
 		}
 
@@ -75,22 +75,23 @@
 
 		boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, false);
 		boolean authenticateAdmin = GitBlit.getBoolean(Keys.web.authenticateAdminPages, true);
-		
-		// Wrap the HttpServletRequest with the RpcServletnRequest which
+
+		// Wrap the HttpServletRequest with the RpcServletRequest which
 		// overrides the servlet container user principal methods.
 		AuthenticatedRequest authenticatedRequest = new AuthenticatedRequest(httpRequest);
 		UserModel user = getUser(httpRequest);
 		if (user != null) {
 			authenticatedRequest.setUser(user);
 		}
-		
-		// conditionally reject rpc administration requests
-		if (adminRequest && !GitBlit.getBoolean(Keys.web.enableRpcAdministration, false)) {
-			logger.warn(Keys.web.enableRpcAdministration + " must be set TRUE for administrative rpc requests.");
+
+		// conditionally reject rpc management/administration requests
+		if (adminRequest && !GitBlit.getBoolean(Keys.web.enableRpcManagement, false)) {
+			logger.warn(Keys.web.enableRpcManagement
+					+ " must be set TRUE for management/administrative rpc requests.");
 			httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
 			return;
 		}
-		
+
 		// BASIC authentication challenge and response processing
 		if ((adminRequest && authenticateAdmin) || (!adminRequest && authenticateView)) {
 			if (user == null) {
diff --git a/src/com/gitblit/RpcServlet.java b/src/com/gitblit/RpcServlet.java
index ceed35e..7cf3a59 100644
--- a/src/com/gitblit/RpcServlet.java
+++ b/src/com/gitblit/RpcServlet.java
@@ -29,6 +29,7 @@
 
 import com.gitblit.Constants.RpcRequest;
 import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.SettingModel;
 import com.gitblit.models.UserModel;
 import com.gitblit.utils.HttpUtils;
 import com.gitblit.utils.RpcUtils;
@@ -182,7 +183,20 @@
 			}
 		} else if (RpcRequest.LIST_SETTINGS.equals(reqType)) {
 			// return the server's settings
-			result = GitBlit.self().getSettingsModel();
+			if (GitBlit.getBoolean(Keys.web.enableRpcAdministration, false)) {
+				result = GitBlit.self().getSettingsModel();
+			} else {
+				response.sendError(notAllowedCode);
+			}
+		} else if (RpcRequest.EDIT_SETTINGS.equals(reqType)) {
+			// update settings on the server
+			if (GitBlit.getBoolean(Keys.web.enableRpcAdministration, false)) {
+				Collection<SettingModel> settings = deserialize(request, response,
+						RpcUtils.SETTINGS_TYPE);
+				GitBlit.self().updateSettings(settings);
+			} else {
+				response.sendError(notAllowedCode);
+			}
 		} else if (RpcRequest.LIST_STATUS.equals(reqType)) {
 			// return the server's status information
 			result = GitBlit.self().getStatus();
diff --git a/src/com/gitblit/client/GitblitClient.java b/src/com/gitblit/client/GitblitClient.java
index 76a6731..66675b1 100644
--- a/src/com/gitblit/client/GitblitClient.java
+++ b/src/com/gitblit/client/GitblitClient.java
@@ -48,8 +48,10 @@
 	public final String account;
 
 	private final char[] password;
+	
+	private volatile boolean allowManagement;
 
-	private volatile boolean isAdmin;
+	private volatile boolean allowAdministration;
 
 	private volatile ServerSettings settings;
 
@@ -75,19 +77,32 @@
 		refreshRepositories();
 
 		try {
-			settings = RpcUtils.getSettings(url, account, password);
-			status = RpcUtils.getStatus(url, account, password);
 			refreshUsers();
-			isAdmin = true;
+			allowManagement = true;
 		} catch (UnauthorizedException e) {
 		} catch (ForbiddenException e) {
 		} catch (IOException e) {
 			System.err.println(e.getMessage());
 		}
+
+		try {
+			settings = RpcUtils.getSettings(url, account, password);
+			status = RpcUtils.getStatus(url, account, password);
+			allowAdministration = true;
+		} catch (UnauthorizedException e) {
+		} catch (ForbiddenException e) {
+		} catch (IOException e) {
+			System.err.println(e.getMessage());
+		}
+
 	}
 
-	public boolean allowAdmin() {
-		return isAdmin;
+	public boolean allowManagement() {
+		return allowManagement;
+	}
+	
+	public boolean allowAdministration() {
+		return allowAdministration;
 	}
 
 	public boolean isOwner(RepositoryModel model) {
diff --git a/src/com/gitblit/client/GitblitPanel.java b/src/com/gitblit/client/GitblitPanel.java
index 5737c15..31de44e 100644
--- a/src/com/gitblit/client/GitblitPanel.java
+++ b/src/com/gitblit/client/GitblitPanel.java
@@ -185,7 +185,8 @@
 		repositoriesTable = Utils.newTable(repositoriesModel);
 		repositoriesTable.setRowHeight(nameRenderer.getFont().getSize() + 8);
 		repositoriesTable.setRowSorter(defaultRepositoriesSorter);
-		repositoriesTable.getRowSorter().toggleSortOrder(RepositoriesTableModel.Columns.Name.ordinal());
+		repositoriesTable.getRowSorter().toggleSortOrder(
+				RepositoriesTableModel.Columns.Name.ordinal());
 
 		setRepositoryRenderer(RepositoriesTableModel.Columns.Name, nameRenderer, -1);
 		setRepositoryRenderer(RepositoriesTableModel.Columns.Indicators, typeRenderer, 100);
@@ -208,7 +209,7 @@
 					RepositoryModel model = ((RepositoriesTableModel) repositoriesTable.getModel()).list
 							.get(modelRow);
 					editRepository.setEnabled(singleSelection
-							&& (gitblit.allowAdmin() || gitblit.isOwner(model)));
+							&& (gitblit.allowManagement() || gitblit.isOwner(model)));
 				} else {
 					editRepository.setEnabled(false);
 				}
@@ -217,7 +218,7 @@
 
 		repositoriesTable.addMouseListener(new MouseAdapter() {
 			public void mouseClicked(MouseEvent e) {
-				if (e.getClickCount() == 2 && gitblit.allowAdmin()) {
+				if (e.getClickCount() == 2 && gitblit.allowManagement()) {
 					editRepository(getSelectedRepositories().get(0));
 				}
 			}
@@ -266,8 +267,8 @@
 		return repositoriesPanel;
 	}
 
-	private void setRepositoryRenderer(RepositoriesTableModel.Columns col, TableCellRenderer renderer,
-			int maxWidth) {
+	private void setRepositoryRenderer(RepositoriesTableModel.Columns col,
+			TableCellRenderer renderer, int maxWidth) {
 		String name = repositoriesTable.getColumnName(col.ordinal());
 		repositoriesTable.getColumn(name).setCellRenderer(renderer);
 		if (maxWidth > 0) {
@@ -457,9 +458,8 @@
 		updateRepositoriesTable();
 		Utils.packColumns(repositoriesTable, 2);
 
-		if (gitblit.allowAdmin()) {
+		if (gitblit.allowManagement()) {
 			updateUsersTable();
-			updateSettingsTable();
 		} else {
 			// user does not have administrator privileges
 			// hide admin repository buttons
@@ -468,8 +468,21 @@
 			delRepository.setVisible(false);
 
 			while (tabs.getTabCount() > 1) {
-				// remove admin tabs
+				// remove all management/administration tabs
 				tabs.removeTabAt(1);
+			}
+		}
+
+		if (gitblit.allowAdministration()) {
+			updateSettingsTable();
+		} else {
+			// remove the settings tab
+			String settingsTitle = Translation.get("gb.settings");
+			for (int i= 0; i < tabs.getTabCount(); i++) {
+				if (tabs.getTitleAt(i).equals(settingsTitle)) {
+					tabs.removeTabAt(i);
+					break;
+				}				
 			}
 		}
 	}
@@ -547,7 +560,8 @@
 				return false;
 			}
 		};
-		TableRowSorter<SettingsTableModel> sorter = new TableRowSorter<SettingsTableModel>(settingsModel);
+		TableRowSorter<SettingsTableModel> sorter = new TableRowSorter<SettingsTableModel>(
+				settingsModel);
 		sorter.setRowFilter(containsFilter);
 		settingsTable.setRowSorter(sorter);
 	}
diff --git a/src/com/gitblit/utils/RpcUtils.java b/src/com/gitblit/utils/RpcUtils.java
index 2d409a0..6572cd9 100644
--- a/src/com/gitblit/utils/RpcUtils.java
+++ b/src/com/gitblit/utils/RpcUtils.java
@@ -28,8 +28,9 @@
 import com.gitblit.models.FederationProposal;
 import com.gitblit.models.FederationSet;
 import com.gitblit.models.RepositoryModel;
-import com.gitblit.models.ServerStatus;
 import com.gitblit.models.ServerSettings;
+import com.gitblit.models.ServerStatus;
+import com.gitblit.models.SettingModel;
 import com.gitblit.models.UserModel;
 import com.google.gson.reflect.TypeToken;
 
@@ -42,6 +43,9 @@
 public class RpcUtils {
 
 	public static final Type NAMES_TYPE = new TypeToken<Collection<String>>() {
+	}.getType();
+
+	public static final Type SETTINGS_TYPE = new TypeToken<Collection<SettingModel>>() {
 	}.getType();
 
 	private static final Type REPOSITORIES_TYPE = new TypeToken<Map<String, RepositoryModel>>() {
@@ -344,11 +348,29 @@
 	public static ServerSettings getSettings(String serverUrl, String account, char[] password)
 			throws IOException {
 		String url = asLink(serverUrl, RpcRequest.LIST_SETTINGS);
-		ServerSettings settings = JsonUtils.retrieveJson(url, ServerSettings.class, account, password);
+		ServerSettings settings = JsonUtils.retrieveJson(url, ServerSettings.class, account,
+				password);
 		return settings;
 	}
 
 	/**
+	 * Update the settings on the Gitblit server.
+	 * 
+	 * @param settings
+	 *            the settings to update
+	 * @param serverUrl
+	 * @param account
+	 * @param password
+	 * @return true if the action succeeded
+	 * @throws IOException
+	 */
+	public static boolean updateSettings(Map<String, String> settings, String serverUrl,
+			String account, char[] password) throws IOException {
+		return doAction(RpcRequest.EDIT_SETTINGS, null, settings, serverUrl, account, password);
+
+	}
+
+	/**
 	 * Retrieves the server status object.
 	 * 
 	 * @param serverUrl

--
Gitblit v1.9.1