Remove obsolete and deprecated FileUserService

Change-Id: I92d1d742e286643e1e1ab47a410b3fda146d1741
diff --git a/src/main/java/com/gitblit/FileUserService.java b/src/main/java/com/gitblit/FileUserService.java
deleted file mode 100644
index 32c24cc..0000000
--- a/src/main/java/com/gitblit/FileUserService.java
+++ /dev/null
@@ -1,1146 +0,0 @@
-/*

- * 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;

-

-import java.io.File;

-import java.io.FileWriter;

-import java.io.IOException;

-import java.text.MessageFormat;

-import java.util.ArrayList;

-import java.util.Collection;

-import java.util.Collections;

-import java.util.HashSet;

-import java.util.List;

-import java.util.Map;

-import java.util.Properties;

-import java.util.Set;

-import java.util.concurrent.ConcurrentHashMap;

-

-import org.slf4j.Logger;

-import org.slf4j.LoggerFactory;

-

-import com.gitblit.Constants.AccessPermission;

-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;

-

-/**

- * FileUserService is Gitblit's original default user service implementation.

- * 

- * Users and their repository memberships are stored in a simple properties file

- * which is cached and dynamically reloaded when modified.

- * 

- * This class was deprecated in Gitblit 0.8.0 in favor of ConfigUserService

- * which is still a human-readable, editable, plain-text file but it is more

- * flexible for storing additional fields.

- * 

- * @author James Moger

- * 

- */

-@Deprecated

-public class FileUserService extends FileSettings implements IUserService {

-

-	private final Logger logger = LoggerFactory.getLogger(FileUserService.class);

-

-	private final Map<String, String> cookies = new ConcurrentHashMap<String, String>();

-

-	private final Map<String, TeamModel> teams = new ConcurrentHashMap<String, TeamModel>();

-

-	public FileUserService(File realmFile) {

-		super(realmFile.getAbsolutePath());

-	}

-

-	/**

-	 * Setup the user service.

-	 * 

-	 * @param settings

-	 * @since 0.7.0

-	 */

-	@Override

-	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 user display name?

-	 * 

-	 * @return true or false

-	 * @since 1.0.0

-	 */

-	@Override

-	public boolean supportsDisplayNameChanges() {

-		return false;

-	}

-

-	/**

-	 * Does the user service support changes to user email address?

-	 * 

-	 * @return true or false

-	 * @since 1.0.0

-	 */

-	@Override

-	public boolean supportsEmailAddressChanges() {

-		return false;

-	}

-

-	/**

-	 * 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?

-	 * 

-	 * @return true or false

-	 */

-	@Override

-	public boolean supportsCookies() {

-		return true;

-	}

-

-	/**

-	 * Returns the cookie value for the specified user.

-	 * 

-	 * @param model

-	 * @return cookie value

-	 */

-	@Override

-	public String getCookie(UserModel model) {

-		if (!StringUtils.isEmpty(model.cookie)) {

-			return model.cookie;

-		}

-		Properties allUsers = super.read();

-		String value = allUsers.getProperty(model.username);

-		String[] roles = value.split(",");

-		String password = roles[0];

-		String cookie = StringUtils.getSHA1(model.username + password);

-		return cookie;

-	}

-

-	/**

-	 * Authenticate a user based on their cookie.

-	 * 

-	 * @param cookie

-	 * @return a user object or null

-	 */

-	@Override

-	public UserModel authenticate(char[] cookie) {

-		String hash = new String(cookie);

-		if (StringUtils.isEmpty(hash)) {

-			return null;

-		}

-		read();

-		UserModel model = null;

-		if (cookies.containsKey(hash)) {

-			String username = cookies.get(hash);

-			model = getUserModel(username);

-		}

-		return model;

-	}

-

-	/**

-	 * Authenticate a user based on a username and password.

-	 * 

-	 * @param username

-	 * @param password

-	 * @return a user object or null

-	 */

-	@Override

-	public UserModel authenticate(String username, char[] password) {

-		Properties allUsers = read();

-		String userInfo = allUsers.getProperty(username);

-		if (StringUtils.isEmpty(userInfo)) {

-			return null;

-		}

-		UserModel returnedUser = null;

-		UserModel user = getUserModel(username);

-		if (user.password.startsWith(StringUtils.MD5_TYPE)) {

-			// password digest

-			String md5 = StringUtils.MD5_TYPE + StringUtils.getMD5(new String(password));

-			if (user.password.equalsIgnoreCase(md5)) {

-				returnedUser = user;

-			}

-		} else if (user.password.startsWith(StringUtils.COMBINED_MD5_TYPE)) {

-			// username+password digest

-			String md5 = StringUtils.COMBINED_MD5_TYPE

-					+ StringUtils.getMD5(username.toLowerCase() + new String(password));

-			if (user.password.equalsIgnoreCase(md5)) {

-				returnedUser = user;

-			}

-		} else if (user.password.equals(new String(password))) {

-			// plain-text password

-			returnedUser = user;

-		}

-		return returnedUser;

-	}

-

-	/**

-	 * Logout a user.

-	 * 

-	 * @param user

-	 */

-	@Override

-	public void logout(UserModel user) {	

-	}

-

-	/**

-	 * Retrieve the user object for the specified username.

-	 * 

-	 * @param username

-	 * @return a user object or null

-	 */

-	@Override

-	public UserModel getUserModel(String username) {

-		Properties allUsers = read();

-		String userInfo = allUsers.getProperty(username.toLowerCase());

-		if (userInfo == null) {

-			return null;

-		}

-		UserModel model = new UserModel(username.toLowerCase());

-		String[] userValues = userInfo.split(",");

-		model.password = userValues[0];

-		for (int i = 1; i < userValues.length; i++) {

-			String role = userValues[i];

-			switch (role.charAt(0)) {

-			case '#':

-				// Permissions

-				if (role.equalsIgnoreCase(Constants.ADMIN_ROLE)) {

-					model.canAdmin = true;

-				} else if (role.equalsIgnoreCase(Constants.FORK_ROLE)) {

-					model.canFork = true;

-				} else if (role.equalsIgnoreCase(Constants.CREATE_ROLE)) {

-					model.canCreate = true;

-				} else if (role.equalsIgnoreCase(Constants.NOT_FEDERATED_ROLE)) {

-					model.excludeFromFederation = true;

-				}

-				break;

-			default:

-				model.addRepositoryPermission(role);

-			}

-		}

-		// set the teams for the user

-		for (TeamModel team : teams.values()) {

-			if (team.hasUser(username)) {

-				model.teams.add(DeepCopier.copy(team));

-			}

-		}

-		return model;

-	}

-

-	/**

-	 * Updates/writes a complete user object.

-	 * 

-	 * @param model

-	 * @return true if update is successful

-	 */

-	@Override

-	public boolean updateUserModel(UserModel model) {

-		return updateUserModel(model.username, model);

-	}

-

-	/**

-	 * Updates/writes all specified user objects.

-	 * 

-	 * @param models a list of user models

-	 * @return true if update is successful

-	 * @since 1.2.0

-	 */

-	@Override

-	public boolean updateUserModels(Collection<UserModel> models) {

-		try {			

-			Properties allUsers = read();

-			for (UserModel model : models) {

-				updateUserCache(allUsers, model.username, model);

-			}

-			write(allUsers);

-			return true;

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to update {0} user models!", models.size()),

-					t);

-		}

-		return false;

-	}

-

-	/**

-	 * Updates/writes and replaces a complete user object keyed by username.

-	 * This method allows for renaming a user.

-	 * 

-	 * @param username

-	 *            the old username

-	 * @param model

-	 *            the user object to use for username

-	 * @return true if update is successful

-	 */

-	@Override

-	public boolean updateUserModel(String username, UserModel model) {

-		try {			

-			Properties allUsers = read();

-			updateUserCache(allUsers, username, model);

-			write(allUsers);

-			return true;

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to update user model {0}!", model.username),

-					t);

-		}

-		return false;

-	}

-	

-	/**

-	 * Updates/writes and replaces a complete user object keyed by username.

-	 * This method allows for renaming a user.

-	 * 

-	 * @param username

-	 *            the old username

-	 * @param model

-	 *            the user object to use for username

-	 * @return true if update is successful

-	 */

-	private boolean updateUserCache(Properties allUsers, String username, UserModel model) {

-		try {			

-			UserModel oldUser = getUserModel(username);

-			List<String> roles;

-			if (model.permissions == null) {

-				roles = new ArrayList<String>();

-			} else {

-				// discrete repository permissions

-				roles = new ArrayList<String>();

-				for (Map.Entry<String, AccessPermission> entry : model.permissions.entrySet()) {

-					if (entry.getValue().exceeds(AccessPermission.NONE)) {

-						// code:repository (e.g. RW+:~james/myrepo.git

-						roles.add(entry.getValue().asRole(entry.getKey()));

-					}

-				}

-			}

-

-			// Permissions

-			if (model.canAdmin) {

-				roles.add(Constants.ADMIN_ROLE);

-			}

-			if (model.canFork) {

-				roles.add(Constants.FORK_ROLE);

-			}

-			if (model.canCreate) {

-				roles.add(Constants.CREATE_ROLE);

-			}

-			if (model.excludeFromFederation) {

-				roles.add(Constants.NOT_FEDERATED_ROLE);

-			}

-

-			StringBuilder sb = new StringBuilder();

-			if (!StringUtils.isEmpty(model.password)) {

-				sb.append(model.password);

-			}

-			sb.append(',');

-			for (String role : roles) {

-				sb.append(role);

-				sb.append(',');

-			}

-			// trim trailing comma

-			sb.setLength(sb.length() - 1);

-			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

-			if (model.teams != null) {

-				// update team cache

-				for (TeamModel team : model.teams) {

-					TeamModel t = getTeamModel(team.name);

-					if (t == null) {

-						// new team

-						t = team;

-					}

-					t.removeUser(username);

-					t.addUser(model.username);

-					updateTeamCache(allUsers, t.name, t);

-				}

-

-				// check for implicit team removal

-				if (oldUser != null) {

-					for (TeamModel team : oldUser.teams) {

-						if (!model.isTeamMember(team.name)) {

-							team.removeUser(username);

-							updateTeamCache(allUsers, team.name, team);

-						}

-					}

-				}

-			}

-			return true;

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to update user model {0}!", model.username),

-					t);

-		}

-		return false;

-	}

-

-	/**

-	 * Deletes the user object from the user service.

-	 * 

-	 * @param model

-	 * @return true if successful

-	 */

-	@Override

-	public boolean deleteUserModel(UserModel model) {

-		return deleteUser(model.username);

-	}

-

-	/**

-	 * Delete the user object with the specified username

-	 * 

-	 * @param username

-	 * @return true if successful

-	 */

-	@Override

-	public boolean deleteUser(String username) {

-		try {

-			// Read realm file

-			Properties allUsers = read();

-			UserModel user = getUserModel(username);

-			allUsers.remove(username);

-			for (TeamModel team : user.teams) {

-				TeamModel t = getTeamModel(team.name);

-				if (t == null) {

-					// new team

-					t = team;

-				}

-				t.removeUser(username);

-				updateTeamCache(allUsers, t.name, t);

-			}

-			write(allUsers);

-			return true;

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to delete user {0}!", username), t);

-		}

-		return false;

-	}

-

-	/**

-	 * Returns the list of all users available to the login service.

-	 * 

-	 * @return list of all usernames

-	 */

-	@Override

-	public List<String> getAllUsernames() {

-		Properties allUsers = read();

-		List<String> list = new ArrayList<String>();

-		for (String user : allUsers.stringPropertyNames()) {

-			if (user.charAt(0) == '@') {

-				// skip team user definitions

-				continue;

-			}

-			list.add(user);

-		}

-		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>();

-		for (String username : getAllUsernames()) {

-			list.add(getUserModel(username));

-		}

-		Collections.sort(list);

-		return list;

-	}

-

-	/**

-	 * Returns the list of all users who are allowed to bypass the access

-	 * restriction placed on the specified repository.

-	 * 

-	 * @param role

-	 *            the repository name

-	 * @return list of all usernames that can bypass the access restriction

-	 */

-	@Override

-	public List<String> getUsernamesForRepositoryRole(String role) {

-		List<String> list = new ArrayList<String>();

-		try {

-			Properties allUsers = read();

-			for (String username : allUsers.stringPropertyNames()) {

-				if (username.charAt(0) == '@') {

-					continue;

-				}

-				String value = allUsers.getProperty(username);

-				String[] values = value.split(",");

-				// skip first value (password)

-				for (int i = 1; i < values.length; i++) {

-					String r = values[i];

-					if (r.equalsIgnoreCase(role)) {

-						list.add(username);

-						break;

-					}

-				}

-			}

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to get usernames for role {0}!", role), t);

-		}

-		Collections.sort(list);

-		return list;

-	}

-

-	/**

-	 * Sets the list of all users who are allowed to bypass the access

-	 * restriction placed on the specified repository.

-	 * 

-	 * @param role

-	 *            the repository name

-	 * @param usernames

-	 * @return true if successful

-	 */

-	@Override

-	public boolean setUsernamesForRepositoryRole(String role, List<String> usernames) {

-		try {

-			Set<String> specifiedUsers = new HashSet<String>(usernames);

-			Set<String> needsAddRole = new HashSet<String>(specifiedUsers);

-			Set<String> needsRemoveRole = new HashSet<String>();

-

-			// identify users which require add and remove role

-			Properties allUsers = read();

-			for (String username : allUsers.stringPropertyNames()) {

-				String value = allUsers.getProperty(username);

-				String[] values = value.split(",");

-				// skip first value (password)

-				for (int i = 1; i < values.length; i++) {

-					String r = values[i];

-					if (r.equalsIgnoreCase(role)) {

-						// user has role, check against revised user list

-						if (specifiedUsers.contains(username)) {

-							needsAddRole.remove(username);

-						} else {

-							// remove role from user

-							needsRemoveRole.add(username);

-						}

-						break;

-					}

-				}

-			}

-

-			// add roles to users

-			for (String user : needsAddRole) {

-				String userValues = allUsers.getProperty(user);

-				userValues += "," + role;

-				allUsers.put(user, userValues);

-			}

-

-			// remove role from user

-			for (String user : needsRemoveRole) {

-				String[] values = allUsers.getProperty(user).split(",");

-				String password = values[0];

-				StringBuilder sb = new StringBuilder();

-				sb.append(password);

-				sb.append(',');

-

-				// skip first value (password)

-				for (int i = 1; i < values.length; i++) {

-					String value = values[i];

-					if (!value.equalsIgnoreCase(role)) {

-						sb.append(value);

-						sb.append(',');

-					}

-				}

-				sb.setLength(sb.length() - 1);

-

-				// update properties

-				allUsers.put(user, sb.toString());

-			}

-

-			// persist changes

-			write(allUsers);

-			return true;

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to set usernames for role {0}!", role), t);

-		}

-		return false;

-	}

-

-	/**

-	 * Renames a repository role.

-	 * 

-	 * @param oldRole

-	 * @param newRole

-	 * @return true if successful

-	 */

-	@Override

-	public boolean renameRepositoryRole(String oldRole, String newRole) {

-		try {

-			Properties allUsers = read();

-			Set<String> needsRenameRole = new HashSet<String>();

-

-			// identify users which require role rename

-			for (String username : allUsers.stringPropertyNames()) {

-				String value = allUsers.getProperty(username);

-				String[] roles = value.split(",");

-				// skip first value (password)

-				for (int i = 1; i < roles.length; i++) {

-					String repository = AccessPermission.repositoryFromRole(roles[i]);

-					if (repository.equalsIgnoreCase(oldRole)) {

-						needsRenameRole.add(username);

-						break;

-					}

-				}

-			}

-

-			// rename role for identified users

-			for (String user : needsRenameRole) {

-				String userValues = allUsers.getProperty(user);

-				String[] values = userValues.split(",");

-				String password = values[0];

-				StringBuilder sb = new StringBuilder();

-				sb.append(password);

-				sb.append(',');

-				sb.append(newRole);

-				sb.append(',');

-

-				// skip first value (password)

-				for (int i = 1; i < values.length; i++) {

-					String repository = AccessPermission.repositoryFromRole(values[i]);

-					if (repository.equalsIgnoreCase(oldRole)) {

-						AccessPermission permission = AccessPermission.permissionFromRole(values[i]);

-						sb.append(permission.asRole(newRole));

-						sb.append(',');

-					} else {

-						sb.append(values[i]);

-						sb.append(',');

-					}

-				}

-				sb.setLength(sb.length() - 1);

-

-				// update properties

-				allUsers.put(user, sb.toString());

-			}

-

-			// persist changes

-			write(allUsers);

-			return true;

-		} catch (Throwable t) {

-			logger.error(

-					MessageFormat.format("Failed to rename role {0} to {1}!", oldRole, newRole), t);

-		}

-		return false;

-	}

-

-	/**

-	 * Removes a repository role from all users.

-	 * 

-	 * @param role

-	 * @return true if successful

-	 */

-	@Override

-	public boolean deleteRepositoryRole(String role) {

-		try {

-			Properties allUsers = read();

-			Set<String> needsDeleteRole = new HashSet<String>();

-

-			// identify users which require role rename

-			for (String username : allUsers.stringPropertyNames()) {

-				String value = allUsers.getProperty(username);

-				String[] roles = value.split(",");

-				// skip first value (password)

-				for (int i = 1; i < roles.length; i++) {					

-					String repository = AccessPermission.repositoryFromRole(roles[i]);

-					if (repository.equalsIgnoreCase(role)) {

-						needsDeleteRole.add(username);

-						break;

-					}

-				}

-			}

-

-			// delete role for identified users

-			for (String user : needsDeleteRole) {

-				String userValues = allUsers.getProperty(user);

-				String[] values = userValues.split(",");

-				String password = values[0];

-				StringBuilder sb = new StringBuilder();

-				sb.append(password);

-				sb.append(',');

-				// skip first value (password)

-				for (int i = 1; i < values.length; i++) {					

-					String repository = AccessPermission.repositoryFromRole(values[i]);

-					if (!repository.equalsIgnoreCase(role)) {

-						sb.append(values[i]);

-						sb.append(',');

-					}

-				}

-				sb.setLength(sb.length() - 1);

-

-				// update properties

-				allUsers.put(user, sb.toString());

-			}

-

-			// persist changes

-			write(allUsers);

-			return true;

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to delete role {0}!", role), t);

-		}

-		return false;

-	}

-

-	/**

-	 * Writes the properties file.

-	 * 

-	 * @param properties

-	 * @throws IOException

-	 */

-	private void write(Properties properties) throws IOException {

-		// Write a temporary copy of the users file

-		File realmFileCopy = new File(propertiesFile.getAbsolutePath() + ".tmp");

-		FileWriter writer = new FileWriter(realmFileCopy);

-		properties

-				.store(writer,

-						" Gitblit realm file format:\n   username=password,\\#permission,repository1,repository2...\n   @teamname=!username1,!username2,!username3,repository1,repository2...");

-		writer.close();

-		// If the write is successful, delete the current file and rename

-		// the temporary copy to the original filename.

-		if (realmFileCopy.exists() && realmFileCopy.length() > 0) {

-			if (propertiesFile.exists()) {

-				if (!propertiesFile.delete()) {

-					throw new IOException(MessageFormat.format("Failed to delete {0}!",

-							propertiesFile.getAbsolutePath()));

-				}

-			}

-			if (!realmFileCopy.renameTo(propertiesFile)) {

-				throw new IOException(MessageFormat.format("Failed to rename {0} to {1}!",

-						realmFileCopy.getAbsolutePath(), propertiesFile.getAbsolutePath()));

-			}

-		} else {

-			throw new IOException(MessageFormat.format("Failed to save {0}!",

-					realmFileCopy.getAbsolutePath()));

-		}

-	}

-

-	/**

-	 * Reads the properties file and rebuilds the in-memory cookie lookup table.

-	 */

-	@Override

-	protected synchronized Properties read() {

-		long lastRead = lastModified();

-		boolean reload = forceReload();

-		Properties allUsers = super.read();

-		if (reload || (lastRead != lastModified())) {

-			// reload hash cache

-			cookies.clear();

-			teams.clear();

-

-			for (String username : allUsers.stringPropertyNames()) {

-				String value = allUsers.getProperty(username);

-				String[] roles = value.split(",");

-				if (username.charAt(0) == '@') {

-					// team definition

-					TeamModel team = new TeamModel(username.substring(1));

-					List<String> repositories = new ArrayList<String>();

-					List<String> users = new ArrayList<String>();

-					List<String> mailingLists = new ArrayList<String>();

-					List<String> preReceive = new ArrayList<String>();

-					List<String> postReceive = new ArrayList<String>();

-					for (String role : roles) {

-						if (role.charAt(0) == '!') {

-							users.add(role.substring(1));

-						} else if (role.charAt(0) == '&') {

-							mailingLists.add(role.substring(1));

-						} else if (role.charAt(0) == '^') {

-							preReceive.add(role.substring(1));

-						} else if (role.charAt(0) == '%') {

-							postReceive.add(role.substring(1));

-						} else {

-							switch (role.charAt(0)) {

-							case '#':

-								// Permissions

-								if (role.equalsIgnoreCase(Constants.ADMIN_ROLE)) {

-									team.canAdmin = true;

-								} else if (role.equalsIgnoreCase(Constants.FORK_ROLE)) {

-									team.canFork = true;

-								} else if (role.equalsIgnoreCase(Constants.CREATE_ROLE)) {

-									team.canCreate = true;

-								}

-								break;

-							default:

-								repositories.add(role);

-							}

-							repositories.add(role);

-						}

-					}

-					if (!team.canAdmin) {

-						// only read permissions for non-admin teams

-						team.addRepositoryPermissions(repositories);

-					}

-					team.addUsers(users);

-					team.addMailingLists(mailingLists);

-					team.preReceiveScripts.addAll(preReceive);

-					team.postReceiveScripts.addAll(postReceive);

-					teams.put(team.name.toLowerCase(), team);

-				} else {

-					// user definition

-					String password = roles[0];

-					cookies.put(StringUtils.getSHA1(username.toLowerCase() + password), username.toLowerCase());

-				}

-			}

-		}

-		return allUsers;

-	}

-

-	@Override

-	public String toString() {

-		return getClass().getSimpleName() + "(" + propertiesFile.getAbsolutePath() + ")";

-	}

-

-	/**

-	 * Returns the list of all teams available to the login service.

-	 * 

-	 * @return list of all teams

-	 * @since 0.8.0

-	 */

-	@Override

-	public List<String> getAllTeamNames() {

-		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() {

-		List<TeamModel> list = new ArrayList<TeamModel>(teams.values());

-		list = DeepCopier.copy(list);

-		Collections.sort(list);

-		return list;

-	}

-

-	/**

-	 * Returns the list of all teams who are allowed to bypass the access

-	 * restriction placed on the specified repository.

-	 * 

-	 * @param role

-	 *            the repository name

-	 * @return list of all teamnames that can bypass the access restriction

-	 */

-	@Override

-	public List<String> getTeamnamesForRepositoryRole(String role) {

-		List<String> list = new ArrayList<String>();

-		try {

-			Properties allUsers = read();

-			for (String team : allUsers.stringPropertyNames()) {

-				if (team.charAt(0) != '@') {

-					// skip users

-					continue;

-				}

-				String value = allUsers.getProperty(team);

-				String[] values = value.split(",");

-				for (int i = 0; i < values.length; i++) {

-					String r = values[i];

-					if (r.equalsIgnoreCase(role)) {

-						// strip leading @

-						list.add(team.substring(1));

-						break;

-					}

-				}

-			}

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to get teamnames for role {0}!", role), t);

-		}

-		Collections.sort(list);

-		return list;

-	}

-

-	/**

-	 * Sets the list of all teams who are allowed to bypass the access

-	 * restriction placed on the specified repository.

-	 * 

-	 * @param role

-	 *            the repository name

-	 * @param teamnames

-	 * @return true if successful

-	 */

-	@Override

-	public boolean setTeamnamesForRepositoryRole(String role, List<String> teamnames) {

-		try {

-			Set<String> specifiedTeams = new HashSet<String>(teamnames);

-			Set<String> needsAddRole = new HashSet<String>(specifiedTeams);

-			Set<String> needsRemoveRole = new HashSet<String>();

-

-			// identify teams which require add and remove role

-			Properties allUsers = read();

-			for (String team : allUsers.stringPropertyNames()) {

-				if (team.charAt(0) != '@') {

-					// skip users

-					continue;

-				}

-				String name = team.substring(1);

-				String value = allUsers.getProperty(team);

-				String[] values = value.split(",");

-				for (int i = 0; i < values.length; i++) {

-					String r = values[i];

-					if (r.equalsIgnoreCase(role)) {

-						// team has role, check against revised team list

-						if (specifiedTeams.contains(name)) {

-							needsAddRole.remove(name);

-						} else {

-							// remove role from team

-							needsRemoveRole.add(name);

-						}

-						break;

-					}

-				}

-			}

-

-			// add roles to teams

-			for (String name : needsAddRole) {

-				String team = "@" + name;

-				String teamValues = allUsers.getProperty(team);

-				teamValues += "," + role;

-				allUsers.put(team, teamValues);

-			}

-

-			// remove role from team

-			for (String name : needsRemoveRole) {

-				String team = "@" + name;

-				String[] values = allUsers.getProperty(team).split(",");

-				StringBuilder sb = new StringBuilder();

-				for (int i = 0; i < values.length; i++) {

-					String value = values[i];

-					if (!value.equalsIgnoreCase(role)) {

-						sb.append(value);

-						sb.append(',');

-					}

-				}

-				sb.setLength(sb.length() - 1);

-

-				// update properties

-				allUsers.put(team, sb.toString());

-			}

-

-			// persist changes

-			write(allUsers);

-			return true;

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to set teamnames for role {0}!", role), t);

-		}

-		return false;

-	}

-

-	/**

-	 * Retrieve the team object for the specified team name.

-	 * 

-	 * @param teamname

-	 * @return a team object or null

-	 * @since 0.8.0

-	 */

-	@Override

-	public TeamModel getTeamModel(String teamname) {

-		read();

-		TeamModel team = teams.get(teamname.toLowerCase());

-		if (team != null) {

-			// clone the model, otherwise all changes to this object are

-			// live and unpersisted

-			team = DeepCopier.copy(team);

-		}

-		return team;

-	}

-

-	/**

-	 * Updates/writes a complete team object.

-	 * 

-	 * @param model

-	 * @return true if update is successful

-	 * @since 0.8.0

-	 */

-	@Override

-	public boolean updateTeamModel(TeamModel model) {

-		return updateTeamModel(model.name, model);

-	}

-	

-	/**

-	 * Updates/writes all specified team objects.

-	 * 

-	 * @param models a list of team models

-	 * @return true if update is successful

-	 * @since 1.2.0

-	 */

-	public boolean updateTeamModels(Collection<TeamModel> models) {

-		try {

-			Properties allUsers = read();

-			for (TeamModel model : models) {

-				updateTeamCache(allUsers, model.name, model);

-			}

-			write(allUsers);

-			return true;

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to update {0} team models!", models.size()), t);

-		}

-		return false;

-	}

-

-	/**

-	 * Updates/writes and replaces a complete team object keyed by teamname.

-	 * This method allows for renaming a team.

-	 * 

-	 * @param teamname

-	 *            the old teamname

-	 * @param model

-	 *            the team object to use for teamname

-	 * @return true if update is successful

-	 * @since 0.8.0

-	 */

-	@Override

-	public boolean updateTeamModel(String teamname, TeamModel model) {

-		try {

-			Properties allUsers = read();

-			updateTeamCache(allUsers, teamname, model);

-			write(allUsers);

-			return true;

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to update team model {0}!", model.name), t);

-		}

-		return false;

-	}

-

-	private void updateTeamCache(Properties allUsers, String teamname, TeamModel model) {

-		StringBuilder sb = new StringBuilder();

-		List<String> roles;

-		if (model.permissions == null) {

-			// legacy, use repository list

-			if (model.repositories != null) {

-				roles = new ArrayList<String>(model.repositories);

-			} else {

-				roles = new ArrayList<String>();

-			}

-		} else {

-			// discrete repository permissions

-			roles = new ArrayList<String>();

-			for (Map.Entry<String, AccessPermission> entry : model.permissions.entrySet()) {

-				if (entry.getValue().exceeds(AccessPermission.NONE)) {

-					// code:repository (e.g. RW+:~james/myrepo.git

-					roles.add(entry.getValue().asRole(entry.getKey()));

-				}

-			}

-		}

-		

-		// Permissions

-		if (model.canAdmin) {

-			roles.add(Constants.ADMIN_ROLE);

-		}

-		if (model.canFork) {

-			roles.add(Constants.FORK_ROLE);

-		}

-		if (model.canCreate) {

-			roles.add(Constants.CREATE_ROLE);

-		}

-

-		for (String role : roles) {

-				sb.append(role);

-				sb.append(',');

-		}

-		

-		if (!ArrayUtils.isEmpty(model.users)) {

-			for (String user : model.users) {

-				sb.append('!');

-				sb.append(user);

-				sb.append(',');

-			}

-		}

-		if (!ArrayUtils.isEmpty(model.mailingLists)) {

-			for (String address : model.mailingLists) {

-				sb.append('&');

-				sb.append(address);

-				sb.append(',');

-			}

-		}

-		if (!ArrayUtils.isEmpty(model.preReceiveScripts)) {

-			for (String script : model.preReceiveScripts) {

-				sb.append('^');

-				sb.append(script);

-				sb.append(',');

-			}

-		}

-		if (!ArrayUtils.isEmpty(model.postReceiveScripts)) {

-			for (String script : model.postReceiveScripts) {

-				sb.append('%');

-				sb.append(script);

-				sb.append(',');

-			}

-		}

-		// trim trailing comma

-		sb.setLength(sb.length() - 1);

-		allUsers.remove("@" + teamname);

-		allUsers.put("@" + model.name, sb.toString());

-

-		// update team cache

-		teams.remove(teamname.toLowerCase());

-		teams.put(model.name.toLowerCase(), model);

-	}

-

-	/**

-	 * Deletes the team object from the user service.

-	 * 

-	 * @param model

-	 * @return true if successful

-	 * @since 0.8.0

-	 */

-	@Override

-	public boolean deleteTeamModel(TeamModel model) {

-		return deleteTeam(model.name);

-	}

-

-	/**

-	 * Delete the team object with the specified teamname

-	 * 

-	 * @param teamname

-	 * @return true if successful

-	 * @since 0.8.0

-	 */

-	@Override

-	public boolean deleteTeam(String teamname) {

-		Properties allUsers = read();

-		teams.remove(teamname.toLowerCase());

-		allUsers.remove("@" + teamname);

-		try {

-			write(allUsers);

-			return true;

-		} catch (Throwable t) {

-			logger.error(MessageFormat.format("Failed to delete team {0}!", teamname), t);

-		}

-		return false;

-	}

-}

diff --git a/src/main/java/com/gitblit/GitblitUserService.java b/src/main/java/com/gitblit/GitblitUserService.java
index 658404b..677d63a 100644
--- a/src/main/java/com/gitblit/GitblitUserService.java
+++ b/src/main/java/com/gitblit/GitblitUserService.java
@@ -33,25 +33,25 @@
 /**

  * This class wraps the default user service and is recommended as the starting

  * point for custom user service implementations.

- * 

+ *

  * This does seem a little convoluted, but the idea is to allow IUserService to

  * evolve with new methods and implementations without breaking custom

  * authentication implementations.

- * 

+ *

  * The most common implementation of a custom IUserService is to only override

  * authentication and then delegate all other functionality to one of Gitblit's

  * user services. This class optimizes that use-case.

- * 

+ *

  * Extending GitblitUserService allows for authentication customization without

  * having to keep-up-with IUSerService API changes.

- * 

+ *

  * @author James Moger

- * 

+ *

  */

 public class GitblitUserService implements IUserService {

 

 	protected IUserService serviceImpl;

-	

+

 	private final Logger logger = LoggerFactory.getLogger(GitblitUserService.class);

 

 	public GitblitUserService() {

@@ -64,13 +64,9 @@
 		logger.info("GUS delegating to " + serviceImpl.toString());

 	}

 

-	@SuppressWarnings("deprecation")

 	protected IUserService createUserService(File realmFile) {

 		IUserService service = null;

-		if (realmFile.getName().toLowerCase().endsWith(".properties")) {

-			// v0.5.0 - v0.7.0 properties-based realm file

-			service = new FileUserService(realmFile);

-		} else if (realmFile.getName().toLowerCase().endsWith(".conf")) {

+		if (realmFile.getName().toLowerCase().endsWith(".conf")) {

 			// v0.8.0+ config-based realm file

 			service = new ConfigUserService(realmFile);

 		}

@@ -91,25 +87,9 @@
 			service.updateUserModel(admin);

 		}

 

-		if (service instanceof FileUserService) {

-			// automatically create a users.conf realm file from the original

-			// users.properties file

-			File usersConfig = new File(realmFile.getParentFile(), "users.conf");

-			if (!usersConfig.exists()) {

-				logger.info(MessageFormat.format("Automatically creating {0} based on {1}",

-						usersConfig.getAbsolutePath(), realmFile.getAbsolutePath()));

-				ConfigUserService configService = new ConfigUserService(usersConfig);

-				for (String username : service.getAllUsernames()) {

-					UserModel userModel = service.getUserModel(username);

-					configService.updateUserModel(userModel);

-				}

-			}

-			// issue suggestion about switching to users.conf

-			logger.warn("Please consider using \"users.conf\" instead of the deprecated \"users.properties\" file");

-		}

 		return service;

 	}

-	

+

 	@Override

 	public String toString() {

 		return getClass().getSimpleName();

@@ -158,7 +138,7 @@
 		setAccountType(user);

 		return user;

 	}

-	

+

 	@Override

 	public void logout(UserModel user) {

 		serviceImpl.logout(user);

@@ -187,7 +167,7 @@
 			if (!model.isLocalAccount() && !supportsTeamMembershipChanges()) {

 				//  teams are externally controlled - copy from original model

 				UserModel existingModel = getUserModel(username);

-				

+

 				model = DeepCopier.copy(model);

 				model.teams.clear();

 				model.teams.addAll(existingModel.teams);

@@ -200,7 +180,7 @@
 			if (!model.isLocalAccount() && !supportsTeamMembershipChanges()) {

 				//  teams are externally controlled- copy from original model

 				UserModel existingModel = getUserModel(username);

-				

+

 				model = DeepCopier.copy(model);

 				model.teams.clear();

 				model.teams.addAll(existingModel.teams);

@@ -231,7 +211,7 @@
     	for (UserModel user : users) {

     		setAccountType(user);

     	}

-		return users; 

+		return users;

 	}

 

 	@Override

@@ -275,7 +255,7 @@
 		if (!supportsTeamMembershipChanges()) {

 			// teams are externally controlled - copy from original model

 			TeamModel existingModel = getTeamModel(teamname);

-			

+

 			model = DeepCopier.copy(model);

 			model.users.clear();

 			model.users.addAll(existingModel.users);

@@ -313,12 +293,12 @@
 	public boolean deleteRepositoryRole(String role) {

 		return serviceImpl.deleteRepositoryRole(role);

 	}

-	

+

 	protected boolean isLocalAccount(String username) {

 		UserModel user = getUserModel(username);

 		return user != null && user.isLocalAccount();

 	}

-	

+

 	protected void setAccountType(UserModel user) {

 		if (user != null) {

 			if (!StringUtils.isEmpty(user.password)

@@ -330,7 +310,7 @@
 			}

 		}

 	}

-	

+

 	protected AccountType getAccountType() {

 		return AccountType.LOCAL;

 	}

diff --git a/src/test/java/com/gitblit/tests/UserServiceTest.java b/src/test/java/com/gitblit/tests/UserServiceTest.java
index 710d1f3..f6cdd6a 100644
--- a/src/test/java/com/gitblit/tests/UserServiceTest.java
+++ b/src/test/java/com/gitblit/tests/UserServiceTest.java
@@ -26,7 +26,6 @@
 

 import com.gitblit.ConfigUserService;

 import com.gitblit.Constants.AccessRestrictionType;

-import com.gitblit.FileUserService;

 import com.gitblit.IUserService;

 import com.gitblit.models.RepositoryModel;

 import com.gitblit.models.TeamModel;

@@ -35,16 +34,6 @@
 public class UserServiceTest {

 

 	@Test

-	public void testFileUserService() throws IOException {

-		File file = new File("us-test.properties");

-		file.delete();

-		IUserService service = new FileUserService(file);

-		testUsers(service);

-		testTeams(service);

-		file.delete();

-	}

-

-	@Test

 	public void testConfigUserService() throws IOException {

 		File file = new File("us-test.conf");

 		file.delete();

@@ -62,13 +51,13 @@
 		// add admin and admins team

 		TeamModel admins = new TeamModel("admins");

 		admins.mailingLists.add("admins@localhost.com");

-		

+

 		admin = new UserModel("admin");

 		admin.password = "password";

 		admin.canAdmin = true;

 		admin.excludeFromFederation = true;

 		admin.teams.add(admins);

-		

+

 		service.updateUserModel(admin);

 		admin = null;

 		admins = null;

@@ -125,7 +114,7 @@
 		// confirm we have 1 team (admins)

 		assertEquals(1, service.getAllTeamNames().size());

 		assertEquals("admins", service.getAllTeamNames().get(0));

-		

+

 		RepositoryModel newrepo1 = new RepositoryModel("newrepo1", null, null, null);

 		newrepo1.accessRestriction = AccessRestrictionType.VIEW;

 		RepositoryModel NEWREPO1 = new RepositoryModel("NEWREPO1", null, null, null);

@@ -168,7 +157,7 @@
 		newrepo2.accessRestriction = AccessRestrictionType.VIEW;

 		RepositoryModel NEWREPO2 = new RepositoryModel("NEWREPO2", null, null, null);

 		NEWREPO2.accessRestriction = AccessRestrictionType.VIEW;

-		

+

 		team.addRepositoryPermission(newrepo2.name);

 		team.name = "testteam2";

 		service.updateTeamModel("testteam", team);

@@ -233,11 +222,11 @@
 		// delete both teams

 		service.deleteTeam("testteam");

 		service.deleteTeam("nextteam");

-		

+

 		// assert we still have the admins team

 		assertEquals(1, service.getAllTeamNames().size());

 		assertEquals("admins", service.getAllTeamNames().get(0));

-		

+

 		team = service.getTeamModel("admins");

 		assertEquals(1, team.mailingLists.size());

 		assertTrue(team.mailingLists.contains("admins@localhost.com"));