From 668663dffb73722e2fae12d9f737d80cd54b3f03 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Tue, 24 Apr 2012 17:56:23 -0400
Subject: [PATCH] Updated the key generator to build nested key classes

---
 src/com/gitblit/ConfigUserService.java |  110 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 97 insertions(+), 13 deletions(-)

diff --git a/src/com/gitblit/ConfigUserService.java b/src/com/gitblit/ConfigUserService.java
index b899d92..828ba76 100644
--- a/src/com/gitblit/ConfigUserService.java
+++ b/src/com/gitblit/ConfigUserService.java
@@ -20,6 +20,7 @@
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -34,6 +35,7 @@
 
 import com.gitblit.models.TeamModel;
 import com.gitblit.models.UserModel;
+import com.gitblit.utils.ArrayUtils;
 import com.gitblit.utils.DeepCopier;
 import com.gitblit.utils.StringUtils;
 
@@ -62,8 +64,12 @@
 	private static final String REPOSITORY = "repository";
 
 	private static final String ROLE = "role";
-	
+
 	private static final String MAILINGLIST = "mailingList";
+
+	private static final String PRERECEIVE = "preReceiveScript";
+
+	private static final String POSTRECEIVE = "postReceiveScript";
 
 	private final File realmFile;
 
@@ -76,6 +82,8 @@
 	private final Map<String, TeamModel> teams = new ConcurrentHashMap<String, TeamModel>();
 
 	private volatile long lastModified;
+	
+	private volatile boolean forceReload;
 
 	public ConfigUserService(File realmFile) {
 		this.realmFile = realmFile;
@@ -91,6 +99,27 @@
 	public void setup(IStoredSettings settings) {
 	}
 
+	/**
+	 * Does the user service support changes to credentials?
+	 * 
+	 * @return true or false
+	 * @since 1.0.0
+	 */
+	@Override
+	public boolean supportsCredentialChanges() {
+		return true;
+	}
+	
+	/**
+	 * Does the user service support changes to team memberships?
+	 * 
+	 * @return true or false
+	 * @since 1.0.0
+	 */	
+	public boolean supportsTeamMembershipChanges() {
+		return true;
+	}
+	
 	/**
 	 * Does the user service support cookie authentication?
 	 * 
@@ -303,6 +332,22 @@
 	public List<String> getAllTeamNames() {
 		read();
 		List<String> list = new ArrayList<String>(teams.keySet());
+		Collections.sort(list);
+		return list;
+	}
+
+	/**
+	 * Returns the list of all teams available to the login service.
+	 * 
+	 * @return list of all teams
+	 * @since 0.8.0
+	 */
+	@Override
+	public List<TeamModel> getAllTeams() {
+		read();
+		List<TeamModel> list = new ArrayList<TeamModel>(teams.values());
+		list = DeepCopier.copy(list);
+		Collections.sort(list);
 		return list;
 	}
 
@@ -328,6 +373,7 @@
 		} catch (Throwable t) {
 			logger.error(MessageFormat.format("Failed to get teamnames for role {0}!", role), t);
 		}
+		Collections.sort(list);
 		return list;
 	}
 
@@ -468,8 +514,23 @@
 	public List<String> getAllUsernames() {
 		read();
 		List<String> list = new ArrayList<String>(users.keySet());
+		Collections.sort(list);
 		return list;
 	}
+	
+	/**
+	 * Returns the list of all users available to the login service.
+	 * 
+	 * @return list of all usernames
+	 */
+	@Override
+	public List<UserModel> getAllUsers() {
+		read();
+		List<UserModel> list = new ArrayList<UserModel>(users.values());
+		list = DeepCopier.copy(list);
+		Collections.sort(list);
+		return list;
+	}	
 
 	/**
 	 * Returns the list of all users who are allowed to bypass the access
@@ -493,6 +554,7 @@
 		} catch (Throwable t) {
 			logger.error(MessageFormat.format("Failed to get usernames for role {0}!", role), t);
 		}
+		Collections.sort(list);
 		return list;
 	}
 
@@ -615,7 +677,9 @@
 
 		// write users
 		for (UserModel model : users.values()) {
-			config.setString(USER, model.username, PASSWORD, model.password);
+			if (!StringUtils.isEmpty(model.password)) {
+				config.setString(USER, model.username, PASSWORD, model.password);
+			}
 
 			// user roles
 			List<String> roles = new ArrayList<String>();
@@ -630,7 +694,7 @@
 			// repository memberships
 			// null check on "final" repositories because JSON-sourced UserModel
 			// can have a null repositories object
-			if (model.repositories != null) {
+			if (!ArrayUtils.isEmpty(model.repositories)) {
 				config.setStringList(USER, model.username, REPOSITORY, new ArrayList<String>(
 						model.repositories));
 			}
@@ -640,27 +704,41 @@
 		for (TeamModel model : teams.values()) {
 			// null check on "final" repositories because JSON-sourced TeamModel
 			// can have a null repositories object
-			if (model.repositories != null) {
+			if (!ArrayUtils.isEmpty(model.repositories)) {
 				config.setStringList(TEAM, model.name, REPOSITORY, new ArrayList<String>(
 						model.repositories));
 			}
 
 			// null check on "final" users because JSON-sourced TeamModel
 			// can have a null users object
-			if (model.users != null) {
+			if (!ArrayUtils.isEmpty(model.users)) {
 				config.setStringList(TEAM, model.name, USER, new ArrayList<String>(model.users));
 			}
 
 			// null check on "final" mailing lists because JSON-sourced
-			// TeamModel
-			// can have a null users object
-			if (model.mailingLists != null) {
+			// TeamModel can have a null users object
+			if (!ArrayUtils.isEmpty(model.mailingLists)) {
 				config.setStringList(TEAM, model.name, MAILINGLIST, new ArrayList<String>(
 						model.mailingLists));
+			}
+
+			// null check on "final" preReceiveScripts because JSON-sourced
+			// TeamModel can have a null preReceiveScripts object
+			if (!ArrayUtils.isEmpty(model.preReceiveScripts)) {
+				config.setStringList(TEAM, model.name, PRERECEIVE, model.preReceiveScripts);
+			}
+
+			// null check on "final" postReceiveScripts because JSON-sourced
+			// TeamModel can have a null postReceiveScripts object
+			if (!ArrayUtils.isEmpty(model.postReceiveScripts)) {
+				config.setStringList(TEAM, model.name, POSTRECEIVE, model.postReceiveScripts);
 			}
 		}
 
 		config.save();
+		// manually set the forceReload flag because not all JVMs support real
+		// millisecond resolution of lastModified. (issue-55)
+		forceReload = true;
 
 		// If the write is successful, delete the current file and rename
 		// the temporary copy to the original filename.
@@ -685,7 +763,8 @@
 	 * Reads the realm file and rebuilds the in-memory lookup tables.
 	 */
 	protected synchronized void read() {
-		if (realmFile.exists() && (realmFile.lastModified() > lastModified)) {
+		if (realmFile.exists() && (forceReload || (realmFile.lastModified() != lastModified))) {
+			forceReload = false;
 			lastModified = realmFile.lastModified();
 			users.clear();
 			cookies.clear();
@@ -696,7 +775,7 @@
 				config.load();
 				Set<String> usernames = config.getSubsections(USER);
 				for (String username : usernames) {
-					UserModel user = new UserModel(username);
+					UserModel user = new UserModel(username.toLowerCase());
 					user.password = config.getString(USER, username, PASSWORD);
 
 					// user roles
@@ -713,8 +792,8 @@
 					}
 
 					// update cache
-					users.put(username, user);
-					cookies.put(StringUtils.getSHA1(username + user.password), user);
+					users.put(user.username, user);
+					cookies.put(StringUtils.getSHA1(user.username + user.password), user);
 				}
 
 				// load the teams
@@ -724,7 +803,12 @@
 					team.addRepositories(Arrays.asList(config.getStringList(TEAM, teamname,
 							REPOSITORY)));
 					team.addUsers(Arrays.asList(config.getStringList(TEAM, teamname, USER)));
-					team.addMailingLists(Arrays.asList(config.getStringList(TEAM, teamname, MAILINGLIST)));
+					team.addMailingLists(Arrays.asList(config.getStringList(TEAM, teamname,
+							MAILINGLIST)));
+					team.preReceiveScripts.addAll(Arrays.asList(config.getStringList(TEAM,
+							teamname, PRERECEIVE)));
+					team.postReceiveScripts.addAll(Arrays.asList(config.getStringList(TEAM,
+							teamname, POSTRECEIVE)));
 
 					teams.put(team.name.toLowerCase(), team);
 

--
Gitblit v1.9.1