/** * Manually log out the specified user * * @param sUserID The user ID to log out * @return {@link EChange} if something changed */ @Nonnull public EChange logoutUser(@Nullable final String sUserID) { m_aRWLock.writeLock().lock(); LoginInfo aInfo; try { aInfo = m_aLoggedInUsers.remove(sUserID); if (aInfo == null) { AuditHelper.onAuditExecuteSuccess("logout", sUserID, "user-not-logged-in"); return EChange.UNCHANGED; } // Ensure that the SessionUser is empty. This is only relevant if user is // manually logged out without destructing the underlying session final SessionUserHolder aSUH = SessionUserHolder.getInstanceIfInstantiatedInScope(aInfo.getSessionScope()); if (aSUH != null) aSUH._reset(); // Set logout time - in case somebody has a strong reference to the // LoginInfo object aInfo.setLogoutDTNow(); } finally { m_aRWLock.writeLock().unlock(); } s_aLogger.info( "Logged out user '" + sUserID + "' after " + new Period(aInfo.getLoginDT(), aInfo.getLogoutDT()).toString()); AuditHelper.onAuditExecuteSuccess("logout", sUserID); // Execute callback as the very last action for (final IUserLogoutCallback aUserLogoutCallback : m_aUserLogoutCallbacks.getAllCallbacks()) try { aUserLogoutCallback.onUserLogout(aInfo); } catch (final Throwable t) { s_aLogger.error( "Failed to invoke onUserLogout callback on " + aUserLogoutCallback.toString() + "(" + aInfo.toString() + ")", t); } return EChange.CHANGED; }
/** * Login the passed user and require a set of certain roles, the used needs to have to login here. * * @param aUser The user to log-in. May be <code>null</code>. When the user is <code>null</code> * the login must fail. * @param sPlainTextPassword Plain text password to use. May be <code>null</code>. * @param aRequiredRoleIDs A set of required role IDs, the user needs to have. May be <code>null * </code>. * @return Never <code>null</code> login status. */ @Nonnull public ELoginResult loginUser( @Nullable final IUser aUser, @Nullable final String sPlainTextPassword, @Nullable final Collection<String> aRequiredRoleIDs) { if (aUser == null) return ELoginResult.USER_NOT_EXISTING; final String sUserID = aUser.getID(); // Deleted user? if (aUser.isDeleted()) { AuditHelper.onAuditExecuteFailure("login", sUserID, "user-is-deleted"); return _onLoginError(sUserID, ELoginResult.USER_IS_DELETED); } // Disabled user? if (aUser.isDisabled()) { AuditHelper.onAuditExecuteFailure("login", sUserID, "user-is-disabled"); return _onLoginError(sUserID, ELoginResult.USER_IS_DISABLED); } // Are all roles present? if (!SecurityHelper.hasUserAllRoles(sUserID, aRequiredRoleIDs)) { AuditHelper.onAuditExecuteFailure( "login", sUserID, "user-is-missing-required-roles", StringHelper.getToString(aRequiredRoleIDs)); return _onLoginError(sUserID, ELoginResult.USER_IS_MISSING_ROLE); } // Check the password final UserManager aUserMgr = PhotonSecurityManager.getUserMgr(); if (!aUserMgr.areUserIDAndPasswordValid(sUserID, sPlainTextPassword)) { AuditHelper.onAuditExecuteFailure("login", sUserID, "invalid-password"); return _onLoginError(sUserID, ELoginResult.INVALID_PASSWORD); } // Check if the password hash needs to be updated final String sExistingPasswordHashAlgorithmName = aUser.getPasswordHash().getAlgorithmName(); final String sDefaultPasswordHashAlgorithmName = GlobalPasswordSettings.getPasswordHashCreatorManager() .getDefaultPasswordHashCreatorAlgorithmName(); if (!sExistingPasswordHashAlgorithmName.equals(sDefaultPasswordHashAlgorithmName)) { // This implicitly implies using the default hash creator algorithm // This automatically saves the file aUserMgr.setUserPassword(sUserID, sPlainTextPassword); s_aLogger.info( "Updated password hash of user '" + sUserID + "' from algorithm '" + sExistingPasswordHashAlgorithmName + "' to '" + sDefaultPasswordHashAlgorithmName + "'"); } boolean bLoggedOutUser = false; LoginInfo aInfo; m_aRWLock.writeLock().lock(); try { if (m_aLoggedInUsers.containsKey(sUserID)) { // The user is already logged in if (isLogoutAlreadyLoggedInUser()) { // Explicitly log out logoutUser(sUserID); // Just a short check if (m_aLoggedInUsers.containsKey(sUserID)) throw new IllegalStateException("Failed to logout '" + sUserID + "'"); AuditHelper.onAuditExecuteSuccess("logout-in-login", sUserID); bLoggedOutUser = true; } else { AuditHelper.onAuditExecuteFailure("login", sUserID, "user-already-logged-in"); return _onLoginError(sUserID, ELoginResult.USER_ALREADY_LOGGED_IN); } } final SessionUserHolder aSUH = SessionUserHolder.getInstance(); if (aSUH.hasUser()) { // This session already has a user s_aLogger.warn( "The session user holder already has the user ID '" + aSUH.getUserID() + "' so the new ID '" + sUserID + "' will not be set!"); AuditHelper.onAuditExecuteFailure("login", sUserID, "session-already-has-user"); return _onLoginError(sUserID, ELoginResult.SESSION_ALREADY_HAS_USER); } aInfo = new LoginInfo(aUser, ScopeManager.getSessionScope()); m_aLoggedInUsers.put(sUserID, aInfo); aSUH.setUser(this, aUser); } finally { m_aRWLock.writeLock().unlock(); } s_aLogger.info( "Logged in user '" + sUserID + "' with login name '" + aUser.getLoginName() + "'"); AuditHelper.onAuditExecuteSuccess("login", sUserID, aUser.getLoginName()); // Execute callback as the very last action for (final IUserLoginCallback aUserLoginCallback : m_aUserLoginCallbacks.getAllCallbacks()) try { aUserLoginCallback.onUserLogin(aInfo); } catch (final Throwable t) { s_aLogger.error( "Failed to invoke onUserLogin callback on " + aUserLoginCallback.toString() + "(" + aInfo.toString() + ")", t); } return bLoggedOutUser ? ELoginResult.SUCCESS_WITH_LOGOUT : ELoginResult.SUCCESS; }