blob: 2ffea441cf84798c2ebc6dcc324db72e6891bebc [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
*/
package org.eclipse.osbp.authentication.providerimpl;
import java.util.Collection;
import org.apache.shiro.authc.credential.DefaultPasswordService;
import org.apache.shiro.authc.credential.PasswordService;
import org.eclipse.osbp.authentication.account.dtos.UserAccountDto;
import org.eclipse.osbp.dsl.dto.lib.impl.DtoServiceAccess;
import org.eclipse.osbp.dsl.dto.lib.services.IDTOServiceWithMutablePersistence;
import org.eclipse.osbp.dsl.dto.lib.services.Query;
import org.eclipse.osbp.dsl.dto.lib.services.filters.LCompare;
import org.eclipse.osbp.persistence.IPersistenceService;
import org.eclipse.osbp.ui.api.useraccess.IUserAccessService;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Class UserProtocol controls login attempts of users, if successful or
* not. User accounts will be locked on too many unsuccessful login attempts.
* The maximum tries is configured in the preferences.
*/
@Component(service = {}, immediate = true)
public class UserProtocol {
/** The dto user account dto service. */
private static IDTOServiceWithMutablePersistence<UserAccountDto> dtoUserAccountDtoService = null;
/** The find by user name. */
private static boolean findByUserName = true; // false means find by email
/** The Constant LOGGER. */
private static final Logger LOGGER = LoggerFactory.getLogger(UserProtocol.class);
/** The persistence service. */
private IPersistenceService persistenceService;
/** The persistence id. */
private static String persistenceId = "authentication";
/** The password service. */
private static PasswordService passwordService = null;
//
// OSGI Infrastructure
//
/**
* Called by OSGi-DS to activate the service.
*
* @param context
* the context
* @throws Exception
* the exception
*/
protected void activate(ComponentContext context) {
LOGGER.debug("UserProtocol activated");
}
/**
* Internal activate.
*
* @throws InvalidSyntaxException
* the invalid syntax exception
*/
@SuppressWarnings("restriction")
protected static void internalActivate() {
if (UserProtocol.dtoUserAccountDtoService == null) {
UserProtocol.dtoUserAccountDtoService = (IDTOServiceWithMutablePersistence<UserAccountDto>) DtoServiceAccess
.getService(UserAccountDto.class);
}
// for password encryption
if (UserProtocol.passwordService == null) {
UserProtocol.passwordService = new DefaultPasswordService();
}
}
/**
* Called by OSGi-DS to deactivate the service.
*
* @param context
* the context
*/
protected void deactivate(ComponentContext context) {
// NOP
}
/**
* Gets the dto user account dto service.
*
* @return the dto user account dto service
*/
public static IDTOServiceWithMutablePersistence<UserAccountDto> getDtoUserAccountDtoService() {
UserProtocol.internalActivate();
return UserProtocol.dtoUserAccountDtoService;
}
/**
* Gets the password service.
*
* @return the password service
*/
public static PasswordService getPasswordService() {
return UserProtocol.passwordService;
}
/**
* Find user account.
*
* @param username
* the username
* @return the user account dto
*/
// TODO (JCD): New method that ONLY finds a user. That´s all!
public UserAccountDto findUserAccount(String username) {
Collection<UserAccountDto> users = null;
try {
// try to find by username
users = getDtoUserAccountDtoService().find(new Query(new LCompare.Equal("userName", username)));
} catch (Exception e) {
LOGGER.error("Exception while trying to find user", e);
}
if (users != null) {
if (users.size() > 1) {
LOGGER.error("user account is not unique - first match taken");
} else if (users.isEmpty()) {
LOGGER.debug("user account not found");
return null;
}
return users.iterator().next();
}
return null;
}
/**
* Find user account.
*
* @param username
* the username
* @return the user account dto
*/
// TODO (JCD): I changed this method into OLD due to the not knowing heed of
// a method that finds a user by email using the introduced username and
// that creates a new user if it doesn´t exist and that all in a
// find.Method. Very strange!!!!
public UserAccountDto findUserAccount_OLD(String username) {
Collection<UserAccountDto> users = null;
try {
if (isFindByUserName()) {
// try to find by username first
users = getDtoUserAccountDtoService().find(new Query(new LCompare.Equal("userName", username)));
} else {
// try to find by email
users = getDtoUserAccountDtoService().find(new Query(new LCompare.Equal("email", username)));
}
} catch (Exception e) {
LOGGER.error("Exception while trying to find user", e);
}
if (users != null) {
if (users.size() > 1) {
LOGGER.error("user account is not unique - first match taken");
} else if (users.isEmpty()) {
LOGGER.debug("user account not found -create one");
UserAccountDto userAccount = new UserAccountDto();
userAccount.setEnabled(true);
if (isFindByUserName()) {
userAccount.setUserName(username);
} else {
userAccount.setEmail(username);
}
getDtoUserAccountDtoService().update(userAccount);
return userAccount;
}
return users.iterator().next();
}
return null;
}
/**
* Update user account.
*
* @param user
* the user
*/
public void updateUserAccount(UserAccountDto user) {
getDtoUserAccountDtoService().update(user);
}
/**
* Delete user account.
*
* @param user
* the user
*/
public void deleteUserAccount(UserAccountDto user) {
getDtoUserAccountDtoService().delete(user);
}
/**
* Track successful login attempt.
*
* @param username
* the username
*/
public void trackSuccessfulLoginAttempt(String username) {
UserAccountDto user = this.findUserAccount(username);
if (user != null) {
int cnt = user.getSuccessfulAttempt();
cnt++;
user.setSuccessfulAttempt(cnt);
user.setFailedAttempt(0);
updateUserAccount(user);
}
}
/**
* Track failed login attempt.
*
* @param username
* the username
* @return the int
*/
public int trackFailedLoginAttempt(String username) {
if (IUserAccessService.ADMINISTRATOR.equals(username)) {
return 0;
}
UserAccountDto user = findUserAccount(username);
if (user != null) {
int cnt = user.getFailedAttempt();
cnt++;
user.setFailedAttempt(cnt);
updateUserAccount(user);
return cnt;
}
return 0;
}
/**
* Checks if is account locked.
*
* @param username
* the username
* @return true, if is account locked
*/
public boolean isAccountLocked(String username) {
if (IUserAccessService.ADMINISTRATOR.equals(username)) {
return false;
}
UserAccountDto user = findUserAccount(username);
if (user != null) {
return user.getLocked();
}
return false;
}
/**
* Checks if the account is still not registered.
*
* @param username
* the username
* @return true, if the account is still not registered
*/
public boolean isAccountNotRegistered(String username) {
if (IUserAccessService.ADMINISTRATOR.equals(username)) {
return false;
}
UserAccountDto user = findUserAccount(username);
if (user != null) {
return user.getNotRegistered();
}
return false;
}
/**
* Checks if is account enabled.
*
* @param username
* the username
* @return true, if is account enabled
*/
public boolean isAccountEnabled(String username) {
if (IUserAccessService.ADMINISTRATOR.equals(username)) {
return true;
}
UserAccountDto user = findUserAccount(username);
if (user != null) {
return user.getEnabled();
}
return false;
}
/**
* Lock account.
*
* @param username
* the username
* @param locked
* the locked
*/
public void lockAccount(String username, boolean locked) {
UserAccountDto user = findUserAccount(username);
if (user != null) {
user.setLocked(locked);
updateUserAccount(user);
}
}
/**
* Enable account.
*
* @param username
* the username
* @param enabled
* the enabled
*/
public void enableAccount(String username, boolean enabled) {
UserAccountDto user = findUserAccount(username);
if (user != null) {
user.setEnabled(enabled);
updateUserAccount(user);
}
}
/**
* Sets the cookie hash.
*
* @param username
* the username
* @param cookie
* the cookie
*/
public void setCookieHash(String username, String cookie) {
UserAccountDto user = findUserAccount(username);
if (user != null) {
user.setCookieHashCode(hashCodeForCookie(cookie));
updateUserAccount(user);
}
}
/**
* Hash code for cookie.
*
* @param cookie
* the cookie
* @return the int
*/
private int hashCodeForCookie(String cookie) {
return cookie == null ? 0 : cookie.hashCode();
}
/**
* Checks if is cookie valid.
*
* @param username
* the username
* @param cookie
* the cookie
* @return true, if is cookie valid
*/
public boolean isCookieValid(String username, String cookie) {
UserAccountDto user = findUserAccount(username);
if (user != null) {
if (Integer.compareUnsigned(user.getCookieHashCode(), hashCodeForCookie(cookie)) == 0) {
LOGGER.debug("cookie is valid");
return true;
} else {
LOGGER.debug("fraud detected as an invalid cookie was presented. expected:" + user.getCookieHashCode() + " found:"
+ cookie.hashCode());
return false;
}
} else {
LOGGER.error("user '{}' could not be found", username);
return true;
}
}
/**
* Checks if is find by user name.
*
* @return true, if is find by user name
*/
public boolean isFindByUserName() {
return findByUserName;
}
/**
* Gets the persistence service.
*
* @return the persistence service
*/
public IPersistenceService getPersistenceService() {
return persistenceService;
}
/**
* Gets the persistence id.
*
* @return the persistence id
*/
public static String getPersistenceId() {
return persistenceId;
}
/**
* Encrypt password.
*
* @param decryptedPassword
* the decrypted password
* @return the string
*/
public String encryptPassword(String decryptedPassword) {
return UserProtocol.passwordService.encryptPassword(decryptedPassword);
}
/**
* Encrypt passwords.
*/
public void encryptPasswords() {
Query query = new Query(new LCompare.Equal("enabled", 0));
int size = getDtoUserAccountDtoService().size(query);
Collection<UserAccountDto> users = getDtoUserAccountDtoService().getByIndex(0, size, query);
for (UserAccountDto user : users) {
user.setPassword(encryptPassword(user.getPassword()));
user.setEnabled(true);
getDtoUserAccountDtoService().update(user);
}
}
/**
* Bind persistence service.
*
* @param persistenceService
* the persistence service
*/
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC)
public synchronized void bindPersistenceService(final IPersistenceService persistenceService) {
this.persistenceService = persistenceService;
this.persistenceService.registerPersistenceUnit(persistenceId, getClass());
internalActivate();
LOGGER.debug("UserProtocolPersistenceService bound");
}
/**
* Unbind persistence service.
*
* @param persistenceService
* the persistence service
*/
public synchronized void unbindPersistenceService(final IPersistenceService persistenceService) { // NOSONAR
this.persistenceService = null;
LOGGER.debug("UserProtocolPersistenceService unbound");
}
}