/*
* Copyright 2006-2014 the original author or authors.
*
* 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 org.jrecruiter.service.impl;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.jasypt.digest.StringDigester;
import org.jrecruiter.common.CollectionUtils;
import org.jrecruiter.common.Constants;
import org.jrecruiter.common.Constants.ServerActions;
import org.jrecruiter.common.PasswordGenerator;
import org.jrecruiter.dao.ConfigurationDao;
import org.jrecruiter.dao.RoleDao;
import org.jrecruiter.dao.UserDao;
import org.jrecruiter.model.Role;
import org.jrecruiter.model.ServerSettings;
import org.jrecruiter.model.User;
import org.jrecruiter.model.UserToRole;
import org.jrecruiter.service.NotificationService;
import org.jrecruiter.service.UserService;
import org.jrecruiter.service.exceptions.DuplicateUserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
/**
* Provides user specific services.
*
* @author Dorota Puchala
* @author Gunnar Hillert
*
*/
@Service("userService")
@Transactional
public class UserServiceImpl implements UserService, UserDetailsService {
/**
* Initialize Logging.
*/
private final static Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
private @Autowired NotificationService notificationService;
private @Autowired ServerSettings serverSettings;
private @Autowired MessageSource messageSource;
/**
* User Dao.
*/
private @Autowired UserDao userDao;
/**
* UserRole Dao.
*/
private @Autowired RoleDao roleDao;
/**
* Access to settings.
*/
private @Autowired ConfigurationDao configurationDao;
private @Autowired StringDigester stringDigester;
//~~~~~Business Methods~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/** {@inheritDoc} */
public User addUser(User user) throws DuplicateUserException{
final User savedUser = this.addUser(user, Boolean.FALSE);
return savedUser;
}
/** {@inheritDoc} */
public User addUser(User user, Boolean verificationRequired) throws DuplicateUserException{
if (user == null) {
throw new IllegalArgumentException("User must not be null.");
}
if (verificationRequired == null) {
throw new IllegalArgumentException("verificationRequired must not be null.");
}
final Date registerDate = new Date();
user.setRegistrationDate(registerDate);
user.setUpdateDate(registerDate);
user.setEnabled(Boolean.FALSE);
user.setVerificationKey(this.generateUuid());
if (user.getUsername() == null) {
user.setUsername(user.getEmail());
}
final User duplicateUser = userDao.getUser(user.getUsername());
if (duplicateUser!= null) {
throw new DuplicateUserException("User " + duplicateUser.getUsername()
+ "(Id=" + duplicateUser.getId()
+ ") already exists!");
}
Role role = roleDao.getRole(Constants.Roles.MANAGER.name());
if (role == null) {
throw new IllegalStateException("Role was not found but is required.");
}
final Set<UserToRole> userToRoles = user.getUserToRoles();
UserToRole utr = new UserToRole();
utr.setRole(role);
utr.setUser(user);
userToRoles.add(utr);
final User savedUser = this.saveUser(user);
if (verificationRequired) {
final Map<String, Object> context = CollectionUtils.getHashMap();
context.put("user", savedUser);
context.put("registrationCode", savedUser.getVerificationKey());
context.put("accountValidationUrl", serverSettings.getServerAddress() + ServerActions.ACCOUNT_VERIFICATION.getPath());
final EmailRequest emailRequest = new EmailRequest(
savedUser.getEmail(), messageSource.getMessage("class.UserServiceImpl.addUser.account.validation.subject", null, LocaleContextHolder.getLocale()), context, "account-validation");
notificationService.sendEmail(emailRequest);
}
return savedUser;
}
/** {@inheritDoc} */
public User saveUser(User user) {
return userDao.save(user);
}
/** {@inheritDoc} */
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public User getUser(String username) {
return userDao.getUser(username);
}
/** {@inheritDoc} */
public void updateUser(User user) {
Date updateDate = new Date();
user.setUpdateDate(updateDate);
userDao.save(user);
}
/** {@inheritDoc} */
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public List<User> getAllUsers() {
return userDao.getAllUsers();
}
/** {@inheritDoc} */
public void deleteUser(User user){
userDao.remove(user.getId());
}
/** {@inheritDoc} */
public void resetPassword(final User user) {
final String password = PasswordGenerator.generatePassword();
user.setPassword(this.stringDigester.digest(password));
this.updateUser(user);
final Map<String, Object> context = CollectionUtils.getHashMap();
context.put("user", user);
context.put("password", password);
final EmailRequest emailRequest = new EmailRequest(user.getEmail(),
messageSource.getMessage("class.UserServiceImpl.resetPassword.email.subject",
null,
LocaleContextHolder.getLocale()),
context,
"get-password");
this.notificationService.sendEmail(emailRequest);
LOGGER.info("resetPassword - Email sent to: " + user.getEmail() + "; id: " + user.getId());
}
/** {@inheritDoc} */
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public UserDetails loadUserByUsername(final String emailOrUserName) throws UsernameNotFoundException, DataAccessException {
final User user = userDao.getUserByUsernameOrEmail(emailOrUserName.trim());
if (user==null){
LOGGER.warn("loadUserByUsername() - No user with id " + emailOrUserName + " found.");
throw new UsernameNotFoundException("loadUserByUsername() - No user with id " + emailOrUserName + " found.");
}
LOGGER.info("User {} ({}) loaded.", new Object[] { user.getUsername(), user.getEmail()});
return user;
}
/** {@inheritDoc} */
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public User getUser(Long userId) {
return userDao.get(userId);
}
/** {@inheritDoc} */
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public List<User> getUsers(Integer pageSize, Integer pageNumber, Map<String, String> sortOrders, Map<String, String> userFilters) {
return userDao.getUsers(pageSize, pageNumber, sortOrders, userFilters);
}
/** {@inheritDoc} */
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public Long getUsersCount() {
return userDao.getUsersCount();
}
public String generateUuid() {
return UUID.randomUUID().toString();
}
/** {@inheritDoc} */
@Transactional(readOnly = true, propagation=Propagation.SUPPORTS)
public User getUserByVerificationKey(final String key) {
return userDao.getUserByVerificationKey(key);
}
}