/*******************************************************************************
* ===========================================================
* Ankush : Big Data Cluster Management Solution
* ===========================================================
*
* (C) Copyright 2014, by Impetus Technologies
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License (LGPL v3) as
* published by the Free Software Foundation;
*
* This software is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
******************************************************************************/
package com.impetus.ankush.common.service.impl;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.orm.jpa.JpaSystemException;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.impetus.ankush.AppStoreWrapper;
import com.impetus.ankush.common.dao.UserDao;
import com.impetus.ankush.common.domain.Role;
import com.impetus.ankush.common.domain.User;
import com.impetus.ankush.common.exception.UserExistsException;
import com.impetus.ankush.common.mail.MailManager;
import com.impetus.ankush.common.mail.MailMsg;
import com.impetus.ankush.common.service.AppConfService;
import com.impetus.ankush.common.service.GenericManager;
import com.impetus.ankush.common.service.UserManager;
import com.impetus.ankush.common.utils.PasswordUtil;
import com.impetus.ankush2.logger.AnkushLogger;
/**
* Implementation of UserManager interface.
*
*/
public class UserManagerImpl extends GenericManagerImpl<User, Long> implements
UserManager {
/** The password encoder. */
private PasswordEncoder passwordEncoder;
/** The user dao. */
private UserDao userDao;
/** The role manager. */
private GenericManager<Role, Long> roleManager;
/** The Constant GENERATED_PASSWORD_LENGTH. */
private static final int GENERATED_PASSWORD_LENGTH = 8;
/** The logger. */
private static AnkushLogger logger = new AnkushLogger(UserManagerImpl.class);
/** The app conf service. */
private AppConfService appConfService;
/**
* Sets the app conf service.
*
* @param appConfService
* the new app conf service
*/
@Autowired
public void setAppConfService(AppConfService appConfService) {
this.appConfService = appConfService;
}
/**
* Sets the password encoder.
*
* @param passwordEncoder
* the new password encoder
*/
@Autowired
public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
/**
* Sets the role manager.
*
* @param roleManager
* the role manager
*/
@Autowired
public void setRoleManager(
@Qualifier("roleManager") GenericManager<Role, Long> roleManager) {
this.roleManager = roleManager;
}
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush.common.service.UserManager#setUserDao(com.impetus.
* ankush.common.dao.UserDao)
*/
@Override
@Autowired
public void setUserDao(UserDao userDao) {
this.dao = userDao;
this.userDao = userDao;
}
/**
* {@inheritDoc}
*/
@Override
public User getUser(String userId) {
return userDao.get(Long.valueOf(userId));
}
/**
* {@inheritDoc}
*/
@Override
public List<User> getUsers() {
return userDao.getAllDistinct();
}
/**
* {@inheritDoc}
*/
@Override
public User saveUser(User user) throws UserExistsException {
// lowercase userId
user.setUsername(user.getUsername().toLowerCase());
// Get and prepare password management-related artifacts
boolean passwordChanged = false;
if (passwordEncoder != null) {
// Check whether we have to encrypt (or re-encrypt) the password
if (user.getVersion() == null) {
// New user, always encrypt
passwordChanged = true;
} else {
// Existing user, check password in DB
String currentPassword = null;
try {
currentPassword = userDao.getUserPassword(user
.getUsername());
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
if (currentPassword == null) {
passwordChanged = true;
} else if (!currentPassword.equals(user.getPassword())) {
passwordChanged = true;
}
}
if (passwordChanged) {
// password was changed (or new user), encrypt it
user.setPassword(passwordEncoder.encodePassword(
user.getPassword(), null));
}
} else {
log.warn("PasswordEncoder not set, skipping password encryption...");
}
try {
return userDao.saveUser(user);
} catch (DataIntegrityViolationException e) {
log.warn(e.getMessage());
throw new UserExistsException("User '" + user.getUsername()
+ "' already exists!");
} catch (JpaSystemException e) {
// needed for JPA
logger.error(e.getMessage());
log.warn(e.getMessage());
throw new UserExistsException("User '" + user.getUsername()
+ "' already exists!");
}
}
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush.common.service.UserManager#createUser(com.impetus.
* ankush.common.domain.User, boolean)
*/
@Override
public User createUser(User user, boolean enabled)
throws UserExistsException {
user.setEnabled(enabled);
user.setId(null);
Set<Role> userRole = new HashSet<Role>();
userRole.add(roleManager.get(1L));
user.setRoles(userRole);
user.setForcePasswordChange(true);
String generatedPassword = "";
if ((user.getPassword() == null)
|| (user.getPassword().trim().length() == 0)) {
generatedPassword = PasswordUtil
.getRandomPassword(GENERATED_PASSWORD_LENGTH);
user.setPassword(generatedPassword);
}
user = this.saveUser(user);
MailMsg message = new MailMsg();
message.setTo(user.getEmail());
message.setSubject("Your Ankush Account has been created");
MailManager mm = AppStoreWrapper.getMailManager();
String accessURL = appConfService.getAppAccessPublicURL();
if (accessURL != null) {
accessURL = "at " + accessURL;
}
StringBuilder msgBuff = new StringBuilder();
msgBuff.append(getUserSalutation(user));
msgBuff.append(
"You can now access Ankush " + accessURL
+ ". Your Account Details are as below:").append("\n");
msgBuff.append("User Id: ").append(user.getUsername()).append("\n");
msgBuff.append("Password: ").append(generatedPassword).append("\n");
msgBuff.append(
"\t - The above password is a system generated password. It is recommended that you change it after login. \n");
String msg = msgBuff.toString();
message.setMessage(msg);
try {
message.setContentType("text/plain");
mm.sendSystemMail(message);
} catch (Exception e1) {
log.error(e1.getMessage(), e1);
}
return user;
}
/**
* {@inheritDoc}
*/
@Override
public void removeUser(String userId) {
log.debug("removing user: " + userId);
userDao.remove(Long.valueOf(userId));
}
/**
* {@inheritDoc}
*
* @param username
* the login name of the human
* @return User the populated user object
* @throws UsernameNotFoundException
* thrown when username not found
*/
@Override
public User getUserByUsername(String username)
throws UsernameNotFoundException {
return (User) userDao.loadUserByUsername(username);
}
/**
* {@inheritDoc}
*/
@Override
public List<User> getUsersByRole(Role role) {
return userDao.getUsersByRole(role);
}
/** The Constant PRODUCT_NAME. */
private static final String PRODUCT_NAME = "Ankush";
/**
* Gets the user salutation.
*
* @param user
* the user
* @return the user salutation
*/
private String getUserSalutation(User user) {
StringBuilder content = new StringBuilder();
content.append("Dear ").append(user.getFirstName()).append(" ")
.append(user.getLastName()).append(",\n\n");
return content.toString();
}
/**
* generates new password for user & send it over mail on users mail id
* registered with profile.
*
* @param user
* user for which password needs to be reset
* @return true, if successful
*/
public boolean forgotPassword(User user) {
String newPassword = PasswordUtil
.getRandomPassword(GENERATED_PASSWORD_LENGTH);
user.setPassword(newPassword);
user.setForcePasswordChange(true);
try {
this.saveUser(user);
} catch (UserExistsException e) {
// will not happen
log.error("Should not occur", e);
throw new RuntimeException(e);
}
MailMsg message = new MailMsg();
message.setTo(user.getEmail());
message.setSubject("Ankush Password Reset Request");
StringBuilder content = new StringBuilder();
content.append(getUserSalutation(user));
content.append("A password reset request was received for this Used ID. The new password is as below: \n");
content.append("Password : ").append(newPassword).append("\n");
content.append("\t - The above password is a system generated password. It is recommended that you change it after login. \n");
message.setMessage(content.toString());
message.setContentType("text/plain");
boolean mailStatus = AppStoreWrapper.getMailManager().sendSystemMail(
message);
return mailStatus;
}
/**
* sends mail to user by specifying requested user id for the login account.
*
* @param user
* user to which user ID needs to be notified
* @return true, if successful
*/
public boolean forgotUserId(User user) {
MailMsg message = new MailMsg();
message.setTo(user.getEmail());
message.setSubject("Ankush User ID Details");
StringBuilder content = new StringBuilder();
content.append(getUserSalutation(user));
content.append("Your User ID for ").append(PRODUCT_NAME)
.append(" is '").append(user.getUsername()).append("'")
.append("\n");
content.append(
"If you have forgotten your User ID or Password, you can request for account details/new password at ")
.append(appConfService.getAppAccessPublicURL());
message.setMessage(content.toString());
message.setContentType("text/plain");
boolean mailStatus = AppStoreWrapper.getMailManager().sendSystemMail(
message);
return mailStatus;
}
/**
* changes password for user if user with given user name found with user's
* existing password matching with given current password else throws
* Exception. *
*
* @param userName
* user name of user
* @param currentPassword
* existing password of user
* @param newPassword
* new password
* @throws Exception
* the exception
*/
public void changePassword(String userName, String currentPassword,
String newPassword) throws Exception {
if ((userName == null) || (userName.length() == 0)) {
return;
}
User user = null;
Map<String, Object> queryMap = new HashMap<String, Object>();
queryMap.put("username", userName);
try {
user = userDao.getByPropertyValue(queryMap);
if (user != null) {
currentPassword = passwordEncoder.encodePassword(
currentPassword, null);
if (user.getPassword().equals(currentPassword)) {
user.setPassword(newPassword);
user.setForcePasswordChange(false);
saveUser(user);
} else {
throw new Exception(
"Existing password is wrong. Please specify the correct password.");
}
}
} catch (EmptyResultDataAccessException e) {
logger.error(e.getMessage());
throw new Exception("User does not exists.");
}
}
/**
* removes user with give user id.
*
* @param id
* id for user that needs to be removed
*/
@Override
public void removeUser(Long id) {
User user = this.get(id);
String messageStr;
String subject;
StringBuffer msgBuff = new StringBuffer();
if (user.getRoles().isEmpty()) {
messageStr = "Your ankush account creation request with user id "
+ user.getUsername() + " has been disapproved.";
subject = "Ankush: Account request disapproved";
} else {
msgBuff.append(getUserSalutation(user));
String accessURL = appConfService.getAppAccessPublicURL();
msgBuff.append(
"You can no longer access Ankush at "
+ accessURL
+ " with the User Id: '"
+ user.getUsername()
+ "'. This Used ID has been deleted by the Administrator.")
.append("\n");
messageStr = msgBuff.toString();
subject = "Your Ankush Account has been deleted";
}
MailMsg message = new MailMsg();
message.setTo(user.getEmail());
message.setSubject(subject);
message.setMessage(messageStr);
message.setContentType("text/plain");
boolean userDeleted = true;
try {
this.remove(id);
} catch (Exception e) {
userDeleted = false;
logger.error(e.getMessage());
}
try {
if (userDeleted) {
AppStoreWrapper.getMailManager().sendSystemMail(message);
}
} catch (Exception e) {
logger.error(e.getMessage());
}
}
/*
* (non-Javadoc)
*
* @see com.impetus.ankush.common.service.UserManager#createdUserCount()
*/
@Override
public int createdUserCount() {
return userDao.createdUserCount();
}
/*
* (non-Javadoc)
*
* @see
* com.impetus.ankush.common.service.UserManager#checkUserExistance(com.
* impetus.ankush.common.domain.User)
*/
@Override
public Boolean checkUserExistance(User user) {
boolean userExist = false;
Map<String, Object> param = new HashMap<String, Object>();
param.put("email", user.getEmail());
User loadUser = null;
try {
loadUser = userDao.getByPropertyValue(param);
} catch (Exception e) {
}
if (loadUser != null) {
userExist = true;
} else {
param.clear();
param.put("username", user.getUsername());
try {
loadUser = userDao.getByPropertyValue(param);
if (loadUser != null) {
userExist = true;
}
} catch (Exception e) {
logger.error(e.getMessage());
}
}
return userExist;
}
@Override
public void addAdminUser() {
List<User> users = getUsers();
if (users == null || users.isEmpty()) {
try {
Role role = new Role();
role.setName("ROLE_SUPER_USER");
role = roleManager.save(role);
Set<Role> roles = new HashSet<Role>();
roles.add(role);
User user = new User();
user.setEnabled(true);
user.setId(null);
user.setRoles(roles);
user.setPassword("admin");
user.setUsername("admin");
user.setVersion(1);
user.setAccountExpired(false);
user.setAccountLocked(false);
user.setCreationDate(new Date());
user.setCredentialsExpired(false);
user.setEmail("admin@company.com");
user.setFirstName("Admin");
user.setLastName("User");
user.setForcePasswordChange(true);
user = this.saveUser(user);
} catch (Exception e) {
logger.error("Unable to create 'admin' user.", e);
}
}
}
@Override
public boolean doesPasswordMatch(String userName, String password) throws Exception {
boolean status = false;
if ((userName == null) || (userName.length() == 0)) {
return status;
}
User user = null;
Map<String, Object> queryMap = new HashMap<String, Object>();
queryMap.put("username", userName);
try {
user = userDao.getByPropertyValue(queryMap);
if (user != null) {
password = passwordEncoder.encodePassword(
password, null);
if (user.getPassword().equals(password)) {
status = true;
} else {
throw new Exception(
"Given password is wrong. Please specify the correct password.");
}
}
} catch (EmptyResultDataAccessException e) {
logger.error(e.getMessage(),e);
throw new Exception("User does not exists.");
}
return status;
}
}