From 04a98505a4ab8f48aee22800fcac193d9367d0ae Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Fri, 29 Nov 2013 11:05:51 -0500 Subject: [PATCH] Refactor user services and separate authentication (issue-281) --- src/main/java/com/gitblit/manager/UserManager.java | 221 +++++++++++++----------------------------------------- 1 files changed, 54 insertions(+), 167 deletions(-) diff --git a/src/main/java/com/gitblit/manager/UserManager.java b/src/main/java/com/gitblit/manager/UserManager.java index 90b9d1e..3ca62e2 100644 --- a/src/main/java/com/gitblit/manager/UserManager.java +++ b/src/main/java/com/gitblit/manager/UserManager.java @@ -20,20 +20,19 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.gitblit.ConfigUserService; -import com.gitblit.Constants; -import com.gitblit.Constants.AccountType; import com.gitblit.IStoredSettings; import com.gitblit.IUserService; import com.gitblit.Keys; import com.gitblit.models.TeamModel; import com.gitblit.models.UserModel; -import com.gitblit.utils.DeepCopier; import com.gitblit.utils.StringUtils; /** @@ -50,37 +49,68 @@ private final IRuntimeManager runtimeManager; + private final Map<String, String> legacyBackingServices; + private IUserService userService; public UserManager(IRuntimeManager runtimeManager) { this.settings = runtimeManager.getSettings(); this.runtimeManager = runtimeManager; + + // map of legacy realm backing user services + legacyBackingServices = new HashMap<String, String>(); + legacyBackingServices.put("com.gitblit.HtpasswdUserService", "realm.htpasswd.backingUserService"); + legacyBackingServices.put("com.gitblit.LdapUserService", "realm.ldap.backingUserService"); + legacyBackingServices.put("com.gitblit.PAMUserService", "realm.pam.backingUserService"); + legacyBackingServices.put("com.gitblit.RedmineUserService", "realm.redmine.backingUserService"); + legacyBackingServices.put("com.gitblit.SalesforceUserService", "realm.salesforce.backingUserService"); + legacyBackingServices.put("com.gitblit.WindowsUserService", "realm.windows.backingUserService"); } /** - * Set the user service. The user service authenticates local users and is - * responsible for persisting and retrieving users and teams. + * Set the user service. The user service authenticates *local* users and is + * responsible for persisting and retrieving all users and all teams. * * @param userService */ public void setUserService(IUserService userService) { - logger.info("UserService: " + userService.toString()); + logger.info(userService.toString()); this.userService = userService; this.userService.setup(runtimeManager); } @Override + public void setup(IRuntimeManager runtimeManager) { + // NOOP + } + + @Override public UserManager start() { if (this.userService == null) { - String realm = settings.getString(Keys.realm.userService, "${baseFolder}/users.properties"); + String realm = settings.getString(Keys.realm.userService, "${baseFolder}/users.conf"); IUserService service = null; - try { - // check to see if this "file" is a login service class - Class<?> realmClass = Class.forName(realm); - service = (IUserService) realmClass.newInstance(); - } catch (Throwable t) { - File realmFile = runtimeManager.getFileOrFolder(Keys.realm.userService, "${baseFolder}/users.conf"); + if (legacyBackingServices.containsKey(realm)) { + // create the user service from the legacy config + String realmKey = legacyBackingServices.get(realm); + logger.warn(""); + logger.warn("#################################################################"); + logger.warn(" Key '{}' is obsolete!", realmKey); + logger.warn(" Please set '{}={}'", Keys.realm.userService, settings.getString(realmKey, "${baseFolder}/users.conf")); + logger.warn("#################################################################"); + logger.warn(""); + File realmFile = runtimeManager.getFileOrFolder(realmKey, "${baseFolder}/users.conf"); service = createUserService(realmFile); + } else { + // either a file path OR a custom user service + try { + // check to see if this "file" is a custom user service class + Class<?> realmClass = Class.forName(realm); + service = (IUserService) realmClass.newInstance(); + } catch (Throwable t) { + // typical file path configuration + File realmFile = runtimeManager.getFileOrFolder(Keys.realm.userService, "${baseFolder}/users.conf"); + service = createUserService(realmFile); + } } setUserService(service); } @@ -90,7 +120,7 @@ protected IUserService createUserService(File realmFile) { IUserService service = null; if (realmFile.getName().toLowerCase().endsWith(".conf")) { - // v0.8.0+ config-based realm file + // config-based realm file service = new ConfigUserService(realmFile); } @@ -118,74 +148,6 @@ return this; } - @Override - public boolean supportsAddUser() { - return supportsCredentialChanges(new UserModel("")); - } - - /** - * Returns true if the user's credentials can be changed. - * - * @param user - * @return true if the user service supports credential changes - */ - @Override - public boolean supportsCredentialChanges(UserModel user) { - if (user == null) { - return false; - } else if (AccountType.LOCAL.equals(user.accountType)) { - // local account, we can change credentials - return true; - } else { - // external account, ask user service - return userService.supportsCredentialChanges(); - } - } - - /** - * Returns true if the user's display name can be changed. - * - * @param user - * @return true if the user service supports display name changes - */ - @Override - public boolean supportsDisplayNameChanges(UserModel user) { - return (user != null && user.isLocalAccount()) || userService.supportsDisplayNameChanges(); - } - - /** - * Returns true if the user's email address can be changed. - * - * @param user - * @return true if the user service supports email address changes - */ - @Override - public boolean supportsEmailAddressChanges(UserModel user) { - return (user != null && user.isLocalAccount()) || userService.supportsEmailAddressChanges(); - } - - /** - * Returns true if the user's team memberships can be changed. - * - * @param user - * @return true if the user service supports team membership changes - */ - @Override - public boolean supportsTeamMembershipChanges(UserModel user) { - return (user != null && user.isLocalAccount()) || userService.supportsTeamMembershipChanges(); - } - - /** - * Allow to understand if GitBlit supports and is configured to allow - * cookie-based authentication. - * - * @return status of Cookie authentication enablement. - */ - @Override - public boolean supportsCookies() { - return settings.getBoolean(Keys.web.allowCookieAuthentication, true) && userService.supportsCookies(); - } - /** * Returns the cookie value for the specified user. * @@ -198,44 +160,15 @@ } /** - * 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) { - UserModel user = userService.authenticate(username, password); - setAccountType(user); - return user; - } - - /** - * Authenticate a user based on their cookie. + * Retrieve the user object for the specified cookie. * * @param cookie * @return a user object or null */ @Override - public UserModel authenticate(char[] cookie) { - UserModel user = userService.authenticate(cookie); - setAccountType(user); + public UserModel getUserModel(char[] cookie) { + UserModel user = userService.getUserModel(cookie); return user; - } - - /** - * Logout a user. - * - * @param user - */ - @Override - public void logout(UserModel user) { - if (userService == null) { - return; - } - userService.logout(user); } /** @@ -251,7 +184,6 @@ } String usernameDecoded = StringUtils.decodeUsername(username); UserModel user = userService.getUserModel(usernameDecoded); - setAccountType(user); return user; } @@ -290,32 +222,7 @@ */ @Override public boolean updateUserModel(String username, UserModel model) { - if (model.isLocalAccount() || userService.supportsCredentialChanges()) { - if (!model.isLocalAccount() && !userService.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); - } - return userService.updateUserModel(username, model); - } - if (model.username.equals(username)) { - // passwords are not persisted by the backing user service - model.password = null; - if (!model.isLocalAccount() && !userService.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); - } - return userService.updateUserModel(username, model); - } - logger.error("Users can not be renamed!"); - return false; + return userService.updateUserModel(username, model); } /** @@ -364,9 +271,6 @@ @Override public List<UserModel> getAllUsers() { List<UserModel> users = userService.getAllUsers(); - for (UserModel user : users) { - setAccountType(user); - } return users; } @@ -378,7 +282,8 @@ */ @Override public List<String> getAllTeamNames() { - return userService.getAllTeamNames(); + List<String> teams = userService.getAllTeamNames(); + return teams; } /** @@ -404,7 +309,8 @@ */ @Override public List<String> getTeamNamesForRepositoryRole(String role) { - return userService.getTeamNamesForRepositoryRole(role); + List<String> teams = userService.getTeamNamesForRepositoryRole(role); + return teams; } /** @@ -416,7 +322,8 @@ */ @Override public TeamModel getTeamModel(String teamname) { - return userService.getTeamModel(teamname); + TeamModel team = userService.getTeamModel(teamname); + return team; } /** @@ -456,14 +363,6 @@ */ @Override public boolean updateTeamModel(String teamname, TeamModel model) { - if (!userService.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); - } return userService.updateTeamModel(teamname, model); } @@ -526,17 +425,5 @@ @Override public boolean deleteRepositoryRole(String role) { return userService.deleteRepositoryRole(role); - } - - protected void setAccountType(UserModel user) { - if (user != null) { - if (!StringUtils.isEmpty(user.password) - && !Constants.EXTERNAL_ACCOUNT.equalsIgnoreCase(user.password) - && !"StoredInLDAP".equalsIgnoreCase(user.password)) { - user.accountType = AccountType.LOCAL; - } else { - user.accountType = userService.getAccountType(); - } - } } } -- Gitblit v1.9.1