From ae0b135ecdbc0e85ba2d612356f4493f2f97bd7a Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Mon, 16 Jan 2012 08:28:37 -0500
Subject: [PATCH] Fixed username case-sensitivity bugs (issue 43)

---
 tests/com/gitblit/tests/UserServiceTest.java   |    5 ++
 docs/04_releases.mkd                           |    5 ++
 src/com/gitblit/ConfigUserService.java         |    6 +-
 src/com/gitblit/wicket/pages/EditUserPage.java |   10 +++--
 src/com/gitblit/client/EditUserDialog.java     |   24 +++++------
 src/com/gitblit/FileUserService.java           |   12 +++---
 6 files changed, 35 insertions(+), 27 deletions(-)

diff --git a/docs/04_releases.mkd b/docs/04_releases.mkd
index c51c2d7..d9177fd 100644
--- a/docs/04_releases.mkd
+++ b/docs/04_releases.mkd
@@ -4,6 +4,11 @@
 
 **%VERSION%** ([go](http://code.google.com/p/gitblit/downloads/detail?name=%GO%) | [war](http://code.google.com/p/gitblit/downloads/detail?name=%WAR%) | [express](http://code.google.com/p/gitblit/downloads/detail?name=%EXPRESS%) | [fedclient](http://code.google.com/p/gitblit/downloads/detail?name=%FEDCLIENT%) | [manager](http://code.google.com/p/gitblit/downloads/detail?name=%MANAGER%) | [api](http://code.google.com/p/gitblit/downloads/detail?name=%API%)) based on [%JGIT%][jgit] &nbsp; *released %BUILDDATE%*
 
+#### fixes 
+- Fixed username case-sensitivity issues (issue 43)
+
+**0.8.2** ([go](http://code.google.com/p/gitblit/downloads/detail?name=gitblit-0.8.2.zip) | [war](http://code.google.com/p/gitblit/downloads/detail?name=gitblit-0.8.2.war) | [express](http://code.google.com/p/gitblit/downloads/detail?name=express-0.8.2.zip) | [fedclient](http://code.google.com/p/gitblit/downloads/detail?name=fedclient-0.8.2.zip) | [manager](http://code.google.com/p/gitblit/downloads/detail?name=manager-0.8.2.zip) | [api](http://code.google.com/p/gitblit/downloads/detail?name=gbapi-0.8.2.zip)) based on [JGit 1.2.0 (201112221803-r)][jgit] &nbsp; *released 2012-01-13*
+
 #### fixes
 
 - Fixed bug when upgrading from users.properties to users.conf (issue 41)
diff --git a/src/com/gitblit/ConfigUserService.java b/src/com/gitblit/ConfigUserService.java
index 5ba49ae..681efd5 100644
--- a/src/com/gitblit/ConfigUserService.java
+++ b/src/com/gitblit/ConfigUserService.java
@@ -746,7 +746,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
@@ -763,8 +763,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
diff --git a/src/com/gitblit/FileUserService.java b/src/com/gitblit/FileUserService.java
index 37ca9a7..dfc4da8 100644
--- a/src/com/gitblit/FileUserService.java
+++ b/src/com/gitblit/FileUserService.java
@@ -165,11 +165,11 @@
 	@Override
 	public UserModel getUserModel(String username) {
 		Properties allUsers = read();
-		String userInfo = allUsers.getProperty(username);
+		String userInfo = allUsers.getProperty(username.toLowerCase());
 		if (userInfo == null) {
 			return null;
 		}
-		UserModel model = new UserModel(username);
+		UserModel model = new UserModel(username.toLowerCase());
 		String[] userValues = userInfo.split(",");
 		model.password = userValues[0];
 		for (int i = 1; i < userValues.length; i++) {
@@ -219,7 +219,7 @@
 	 */
 	@Override
 	public boolean updateUserModel(String username, UserModel model) {
-		try {
+		try {			
 			Properties allUsers = read();
 			UserModel oldUser = getUserModel(username);
 			ArrayList<String> roles = new ArrayList<String>(model.repositories);
@@ -241,8 +241,8 @@
 			}
 			// trim trailing comma
 			sb.setLength(sb.length() - 1);
-			allUsers.remove(username);
-			allUsers.put(model.username, sb.toString());
+			allUsers.remove(username.toLowerCase());
+			allUsers.put(model.username.toLowerCase(), sb.toString());
 
 			// null check on "final" teams because JSON-sourced UserModel
 			// can have a null teams object
@@ -661,7 +661,7 @@
 				} else {
 					// user definition
 					String password = roles[0];
-					cookies.put(StringUtils.getSHA1(username + password), username);
+					cookies.put(StringUtils.getSHA1(username.toLowerCase() + password), username.toLowerCase());
 				}
 			}
 		}
diff --git a/src/com/gitblit/client/EditUserDialog.java b/src/com/gitblit/client/EditUserDialog.java
index 3f1b929..f3665d9 100644
--- a/src/com/gitblit/client/EditUserDialog.java
+++ b/src/com/gitblit/client/EditUserDialog.java
@@ -78,7 +78,7 @@
 	private JCheckBox notFederatedCheckbox;
 
 	private JPalette<String> repositoryPalette;
-	
+
 	private JPalette<TeamModel> teamsPalette;
 
 	private Set<String> usernames;
@@ -135,10 +135,10 @@
 		final Insets _insets = new Insets(5, 5, 5, 5);
 		repositoryPalette = new JPalette<String>();
 		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;
@@ -166,7 +166,6 @@
 		}
 		panel.addTab(Translation.get("gb.restrictedRepositories"), repositoriesPanel);
 
-
 		JButton createButton = new JButton(Translation.get("gb.save"));
 		createButton.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent event) {
@@ -188,7 +187,7 @@
 		JPanel controls = new JPanel();
 		controls.add(cancelButton);
 		controls.add(createButton);
-		
+
 		JPanel centerPanel = new JPanel(new BorderLayout(5, 5)) {
 
 			private static final long serialVersionUID = 1L;
@@ -217,16 +216,15 @@
 	}
 
 	private boolean validateFields() {
-		String uname = usernameField.getText();
-		if (StringUtils.isEmpty(uname)) {
+		if (StringUtils.isEmpty(usernameField.getText())) {
 			error("Please enter a username!");
 			return false;
 		}
-
+		String uname = usernameField.getText().toLowerCase();
 		boolean rename = false;
 		// verify username uniqueness on create
 		if (isCreate) {
-			if (usernames.contains(uname.toLowerCase())) {
+			if (usernames.contains(uname)) {
 				error(MessageFormat.format("Username ''{0}'' is unavailable.", uname));
 				return false;
 			}
@@ -234,7 +232,7 @@
 			// check rename collision
 			rename = !StringUtils.isEmpty(username) && !username.equalsIgnoreCase(uname);
 			if (rename) {
-				if (usernames.contains(uname.toLowerCase())) {
+				if (usernames.contains(uname)) {
 					error(MessageFormat.format(
 							"Failed to rename ''{0}'' because ''{1}'' already exists.", username,
 							uname));
@@ -274,7 +272,7 @@
 			} else if (type.equalsIgnoreCase("combined-md5")) {
 				// store MD5 digest of username+password
 				user.password = StringUtils.COMBINED_MD5_TYPE
-						+ StringUtils.getMD5(username.toLowerCase() + password);
+						+ StringUtils.getMD5(user.username + password);
 			} else {
 				// plain-text password
 				user.password = password;
@@ -292,7 +290,7 @@
 
 		user.repositories.clear();
 		user.repositories.addAll(repositoryPalette.getSelections());
-		
+
 		user.teams.clear();
 		user.teams.addAll(teamsPalette.getSelections());
 		return true;
@@ -323,7 +321,7 @@
 		}
 		repositoryPalette.setObjects(restricted, selected);
 	}
-	
+
 	public void setTeams(List<TeamModel> teams, List<TeamModel> selected) {
 		Collections.sort(teams);
 		if (selected != null) {
diff --git a/src/com/gitblit/wicket/pages/EditUserPage.java b/src/com/gitblit/wicket/pages/EditUserPage.java
index 799cf01..142a542 100644
--- a/src/com/gitblit/wicket/pages/EditUserPage.java
+++ b/src/com/gitblit/wicket/pages/EditUserPage.java
@@ -108,11 +108,13 @@
 			 */
 			@Override
 			protected void onSubmit() {
-				String username = userModel.username;
-				if (StringUtils.isEmpty(username)) {
+				if (StringUtils.isEmpty(userModel.username)) {
 					error("Please enter a username!");
 					return;
 				}
+				// force username to lower-case
+				userModel.username = userModel.username.toLowerCase();
+				String username = userModel.username;
 				if (isCreate) {
 					UserModel model = GitBlit.self().getUserModel(username);
 					if (model != null) {
@@ -151,7 +153,7 @@
 					} else if (type.equalsIgnoreCase("combined-md5")) {
 						// store MD5 digest of username+password
 						userModel.password = StringUtils.COMBINED_MD5_TYPE
-								+ StringUtils.getMD5(username.toLowerCase() + userModel.password);
+								+ StringUtils.getMD5(username + userModel.password);
 					}
 				} else if (rename
 						&& password.toUpperCase().startsWith(StringUtils.COMBINED_MD5_TYPE)) {
@@ -177,7 +179,7 @@
 					userModel.teams.add(team);
 				}
 
-				try {
+				try {					
 					GitBlit.self().updateUserModel(oldName, userModel, isCreate);
 				} catch (GitBlitException e) {
 					error(e.getMessage());
diff --git a/tests/com/gitblit/tests/UserServiceTest.java b/tests/com/gitblit/tests/UserServiceTest.java
index b1f0247..03051bd 100644
--- a/tests/com/gitblit/tests/UserServiceTest.java
+++ b/tests/com/gitblit/tests/UserServiceTest.java
@@ -80,12 +80,15 @@
 		service.updateUserModel(newUser);
 
 		// add one more new user and then test reload of first new user
-		newUser = new UserModel("garbage");
+		newUser = new UserModel("GARBAGE");
 		newUser.password = "garbage";
 		service.updateUserModel(newUser);
 
 		// confirm all added users
 		assertEquals(3, service.getAllUsernames().size());
+		assertTrue(service.getUserModel("garbage") != null);
+		assertTrue(service.getUserModel("GaRbAgE") != null);
+		assertTrue(service.getUserModel("GARBAGE") != null);
 
 		// confirm reloaded test user
 		newUser = service.getUserModel("test");

--
Gitblit v1.9.1