Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.eurodyn.qlack.fuse.aaa.service.UserService Maven / Gradle / Ivy
package com.eurodyn.qlack.fuse.aaa.service;
import com.eurodyn.qlack.fuse.aaa.criteria.UserSearchCriteria;
import com.eurodyn.qlack.fuse.aaa.criteria.UserSearchCriteria.UserAttributeCriteria;
import com.eurodyn.qlack.fuse.aaa.criteria.UserSearchCriteria.UserAttributeCriteria.Type;
import com.eurodyn.qlack.fuse.aaa.dto.SessionDTO;
import com.eurodyn.qlack.fuse.aaa.dto.UserAttributeDTO;
import com.eurodyn.qlack.fuse.aaa.dto.UserDTO;
import com.eurodyn.qlack.fuse.aaa.mappers.SessionMapper;
import com.eurodyn.qlack.fuse.aaa.mappers.UserAttributeMapper;
import com.eurodyn.qlack.fuse.aaa.mappers.UserDetailsMapper;
import com.eurodyn.qlack.fuse.aaa.mappers.UserGroupHasOperationMapper;
import com.eurodyn.qlack.fuse.aaa.mappers.UserMapper;
import com.eurodyn.qlack.fuse.aaa.model.UserGroup;
import com.eurodyn.qlack.fuse.aaa.model.QSession;
import com.eurodyn.qlack.fuse.aaa.model.QUser;
import com.eurodyn.qlack.fuse.aaa.model.QUserAttribute;
import com.eurodyn.qlack.fuse.aaa.model.Session;
import com.eurodyn.qlack.fuse.aaa.model.User;
import com.eurodyn.qlack.fuse.aaa.model.UserAttribute;
import com.eurodyn.qlack.fuse.aaa.repository.UserGroupRepository;
import com.eurodyn.qlack.fuse.aaa.repository.SessionRepository;
import com.eurodyn.qlack.fuse.aaa.repository.UserAttributeRepository;
import com.eurodyn.qlack.fuse.aaa.repository.UserRepository;
import com.eurodyn.qlack.fuse.aaa.util.Md5PasswordEncoder;
import com.eurodyn.qlack.util.data.SpringBeansUtils;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import lombok.extern.java.Log;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@Log
@Primary
@Service
@Validated
@Transactional
public class UserService implements UserDetailsService {
private static final Logger LOGGER = Logger.getLogger(UserService.class.getName());
// Service REFs
private AccountingService accountingService;
private LdapUserUtil ldapUserUtil;
// Repositories
private final UserRepository userRepository;
private final UserAttributeRepository userAttributeRepository;
private final SessionRepository sessionRepository;
private final UserGroupRepository userGroupRepository;
// Mappers
private final UserMapper userMapper;
private final SessionMapper sessionMapper;
private final UserAttributeMapper userAttributeMapper;
private final UserDetailsMapper userDetailsMapper;
private final UserGroupHasOperationMapper userGroupHasOperationMapper;
//QueryDSL helpers
private QUser qUser = QUser.user;
private QSession qSession = QSession.session;
private final PasswordEncoder passwordEncoder;
private static final int SALT_LENGTH = 16;
public UserService(AccountingService accountingService, LdapUserUtil ldapUserUtil,
UserRepository userRepository, UserAttributeRepository userAttributeRepository,
SessionRepository sessionRepository, UserGroupRepository userGroupRepository, UserMapper userMapper,
SessionMapper sessionMapper, UserAttributeMapper userAttributeMapper,
UserDetailsMapper userDetailsMapper, @Lazy PasswordEncoder passwordEncoder,
UserGroupHasOperationMapper userGroupHasOperationMapper) {
this.accountingService = accountingService;
this.ldapUserUtil = ldapUserUtil;
this.userRepository = userRepository;
this.userAttributeRepository = userAttributeRepository;
this.sessionRepository = sessionRepository;
this.userGroupRepository = userGroupRepository;
this.userMapper = userMapper;
this.sessionMapper = sessionMapper;
this.userAttributeMapper = userAttributeMapper;
this.userDetailsMapper = userDetailsMapper;
this.passwordEncoder = passwordEncoder;
this.userGroupHasOperationMapper = userGroupHasOperationMapper;
}
public String createUser(UserDTO dto) {
User user = userMapper.mapToEntity(dto);
setUserPassword(dto, user);
for(UserAttribute attribute: user.getUserAttributes()){
attribute.setUser(user);
}
userRepository.save(user);
return user.getId();
}
public void updateUser(UserDTO dto, boolean updatePassword, boolean createIfMissing) {
User user = userRepository.fetchById(dto.getId());
userMapper.mapToExistingEntity(dto, user);
if (updatePassword) {
setUserPassword(dto, user);
}
if (dto.getUserAttributes() != null) {
for (UserAttributeDTO attribute : dto.getUserAttributes()) {
updateAttribute(attribute, createIfMissing);
}
}
}
public void deleteUser(String userID) {
User user = userRepository.fetchById(userID);
userRepository.delete(user);
}
public UserDTO getUserById(String userID) {
User user = userRepository.fetchById(userID);
return userMapper.mapToDTO(user);
}
public Set getUsersById(Collection userIDs) {
Predicate predicate = qUser.id.in(userIDs);
return userRepository.findAll(predicate).stream()
.map(userMapper::mapToDTO)
.collect(Collectors.toSet());
}
public Map getUsersByIdAsHash(Collection userIDs) {
Predicate predicate = qUser.id.in(userIDs);
return userRepository.findAll(predicate).stream()
.map(userMapper::mapToDTO)
.collect(Collectors.toMap(UserDTO::getId,dto -> dto));
}
public UserDTO getUserByName(String userName) {
return userMapper.mapToDTO(userRepository.findByUsername(userName));
}
public void updateUserStatus(String userID, byte status) {
User user = userRepository.fetchById(userID);
user.setStatus(status);
}
public byte getUserStatus(String userID) {
User user = userRepository.fetchById(userID);
return user.getStatus();
}
public boolean isSuperadmin(String userID) {
User user = userRepository.fetchById(userID);
if (user != null) {
return user.isSuperadmin();
} else {
return false;
}
}
public boolean isExternal(String userID) {
User user = userRepository.fetchById(userID);
return user.isExternal();
}
public String canAuthenticate(String username, String password) {
String retVal = null;
/** Try to find this user in the database */
User user = userRepository.findByUsername(username);
/** If the user was found proceed trying to authenticate it. Otherwise, if LDAP integration is
* enabled try to authenticate the user in LDAP. Note that if the user is successfully
* authenticated with LDAP, a new user will also be created/duplicated in AAA as an external
* user.
*/
if (user != null && BooleanUtils.isFalse(user.isExternal())) {
/** Generate password hash to compare with password stored in the DB. */
String checkPassword = DigestUtils.md5Hex(user.getSalt() + password);
if (checkPassword.equals(user.getPassword())) {
retVal = user.getId();
}
} else {
if (ldapUserUtil.isLdapEnable()) {
retVal = ldapUserUtil.canAuthenticate(username, password);
}
}
return retVal;
}
public UserDTO login(String userID, String applicationSessionID,
boolean terminateOtherSessions) {
User user = userRepository.fetchById(userID);
// Check if other sessions of this user need to be terminated first.
if (terminateOtherSessions) {
if (user.getSessions() != null) {
for (Session session : user.getSessions()) {
if (session.getTerminatedOn() == null) {
accountingService.terminateSession(session.getId());
}
}
}
}
// Create a new session for the user.
SessionDTO session = new SessionDTO();
session.setUserId(user.getId());
session.setApplicationSessionId(applicationSessionID);
String sessionId = accountingService.createSession(session);
// Create a DTO representation of the user and populate the session Id of the session that was
// just created.
final UserDTO userDTO = userMapper.mapToDTO(user);
userDTO.setSessionId(sessionId);
return userDTO;
}
public void logout(String userID, String applicationSessionID) {
User user = userRepository.fetchById(userID);
if (user.getSessions() != null) {
for (Session session : user.getSessions()) {
if (((applicationSessionID != null) && (session
.getApplicationSessionId().equals(applicationSessionID)))
|| ((applicationSessionID == null) && (session
.getApplicationSessionId() == null))) {
accountingService.terminateSession(session.getId());
}
}
}
}
public void logoutAll() {
Predicate predicate = qSession.terminatedOn.isNull();
List queryResult = sessionRepository.findAll(predicate);
if (queryResult != null) {
for (Session session : queryResult) {
logout(session.getUser().getId(),
session.getApplicationSessionId());
}
}
}
public List isUserAlreadyLoggedIn(String userID) {
Predicate predicate = qSession.user.id.eq(userID).and(qSession.terminatedOn.isNull());
List retVal = sessionMapper.mapToDTO(sessionRepository
.findAll(predicate, Sort.by("createdOn").ascending()));
return retVal.isEmpty() ? null : retVal;
}
public boolean belongsToGroupByName(String userID, String groupName,
boolean includeChildren) {
User user = userRepository.fetchById(userID);
UserGroup userGroup = userGroupRepository.findByName(groupName);
boolean retVal = userGroup.getUsers().contains(user);
if (!retVal && includeChildren) {
for (UserGroup child : userGroup.getChildren()) {
if (belongsToGroupByName(userID, child.getName(),
includeChildren)) {
return true;
}
}
}
return retVal;
}
public void updateAttributes(Collection attributes,
boolean createIfMissing) {
for (UserAttributeDTO attributeDTO : attributes) {
updateAttribute(attributeDTO, createIfMissing);
}
}
public void updateAttribute(UserAttributeDTO attributeDTO,
boolean createIfMissing) {
String userId = attributeDTO.getUserId();
String name = attributeDTO.getName();
UserAttribute attribute = userAttributeRepository.findByUserIdAndName(userId, name);
if (attribute != null) {
mapAttribute(attribute, attributeDTO);
userAttributeRepository.save(attribute);
} else {
if (createIfMissing) {
attribute = new UserAttribute();
mapAttribute(attribute, attributeDTO);
userAttributeRepository.save(attribute);
} else {
return;
}
}
}
private void mapAttribute(UserAttribute attribute,
UserAttributeDTO attributeDTO) {
String userId = attributeDTO.getUserId();
User user = userRepository.fetchById(userId);
attribute.setUser(user);
userAttributeMapper.mapToExistingEntity(attributeDTO, attribute);
}
public void deleteAttribute(String userID, String attributeName) {
UserAttribute attribute = userAttributeRepository.findByUserIdAndName(userID, attributeName);
if (attribute != null) {
userAttributeRepository.delete(attribute);
}
}
public UserAttributeDTO getAttribute(String userID, String attributeName) {
UserAttribute attribute = userAttributeRepository.findByUserIdAndName(userID, attributeName);
return userAttributeMapper.mapToDTO(attribute);
}
public Set getUserIDsForAttribute(Collection userIDs,
String attributeName, String attributeValue) {
Predicate predicate = qUser.userAttributes.any().name.eq(attributeName)
.and(qUser.userAttributes.any().data.eq(attributeValue));
if ((userIDs != null) && (!userIDs.isEmpty())) {
predicate = ((BooleanExpression) predicate).and(qUser.id.in(userIDs));
}
return userRepository.findAll(predicate).stream()
.map(User::getId)
.collect(Collectors.toSet());
}
public Iterable findUsers(UserSearchCriteria criteria){
Predicate predicate = buildPredicate(criteria);
if(criteria.getAttributeCriteria() != null){
predicate = getAttributePredicate(criteria.getAttributeCriteria(), predicate);
}
if(criteria.getPageable() != null){
return listUsersPaginated(predicate, criteria.getPageable());
}else{
return listUsers(predicate);
}
}
//TODO fix attribute sorting
private Predicate getAttributePredicate(UserAttributeCriteria criteria, Predicate predicate){
if (criteria.getAttCriteria()!= null) {
for(UserAttributeCriteria uac: criteria.getAttCriteria()){
if (uac.getType() == Type.AND) {
// predicate = ((BooleanExpression)predicate).and(qUser.userAttributes.any().eq())
}
}
}
return predicate;
}
private List listUsers(Predicate predicate) {
return userRepository.findAll(predicate).stream()
.map(userMapper::mapToDTO)
.collect(Collectors.toList());
}
private Predicate buildPredicate(UserSearchCriteria criteria){
Predicate predicate = new BooleanBuilder();
if(criteria.getIncludeGroupIds() != null){
predicate = ((BooleanBuilder) predicate).and(qUser.userGroups.any().id.in(criteria.getIncludeGroupIds()));
}
if(criteria.getExcludeGroupIds() != null){
predicate = ((BooleanBuilder) predicate).and(qUser.userGroups.any().id.notIn(criteria.getExcludeGroupIds()));
}
if(criteria.getIncludeIds() != null){
predicate = ((BooleanBuilder) predicate).and(qUser.id.in(criteria.getIncludeIds()));
}
if(criteria.getExcludeIds() != null){
predicate = ((BooleanBuilder) predicate).and(qUser.id.notIn(criteria.getExcludeIds()));
}
if(criteria.getIncludeStatuses() != null){
predicate = ((BooleanBuilder) predicate).and(qUser.status.in(criteria.getIncludeStatuses()));
}
if(criteria.getExcludeStatuses() != null){
predicate = ((BooleanBuilder) predicate).and(qUser.status.notIn(criteria.getExcludeStatuses()));
}
if(criteria.getUsername() != null){
predicate = ((BooleanBuilder) predicate).and(qUser.username.eq(criteria.getUsername()));
}
if(criteria.getSuperadmin() != null){
predicate = ((BooleanBuilder) predicate).and(qUser.superadmin.eq(criteria.getSuperadmin()));
}
return predicate;
}
private Page listUsersPaginated(Predicate predicate, Pageable pageable){
return userRepository.findAll(predicate, pageable).map(userMapper::mapToDTO);
}
public long findUserCount(UserSearchCriteria criteria) {
Predicate predicate = buildPredicate(criteria);
return userRepository.findAll(predicate).size();
}
public boolean isAttributeValueUnique(String attributeValue,
String attributeName, String userID) {
boolean isAttributeValueUnique = false;
QUserAttribute quserAttribute = QUserAttribute.userAttribute;
Predicate predicate = quserAttribute.name.eq(attributeName)
.and(quserAttribute.data.eq(attributeName));
// convert Set to List
List qResult = userAttributeMapper.mapToDTO(userAttributeRepository.findAll(predicate));
ArrayList list = new ArrayList(qResult);
//in case of no user exists with this user attribute value or there is only the given user
if ((list.size() == 1 && list.get(0).getUserId().equals(userID)) || (list.isEmpty())) {
isAttributeValueUnique = true;
}
return isAttributeValueUnique;
}
public Page findAll(Predicate predicate, Pageable pageable) {
return userMapper.map(userRepository.findAll(predicate, pageable));
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
return userDetailsMapper.mapToDTO(user, userGroupHasOperationMapper);
}
private void setUserPassword(UserDTO dto, User user) {
if (dto == null || user == null) {
return;
}
// Retrieve target class from proxied bean interface.
Object targetPasswordEncoder = null;
try {
targetPasswordEncoder = SpringBeansUtils.getTargetObject(passwordEncoder, PasswordEncoder.class);
} catch (Exception e) {
log.log(Level.WARNING, e.getMessage(), e);
}
if (targetPasswordEncoder instanceof Md5PasswordEncoder) {
Md5PasswordEncoder encoder = (Md5PasswordEncoder) passwordEncoder;
byte[] salt = encoder.generateSalt(SALT_LENGTH);
// Generate salt and hash password
user.setSalt(new String(salt));
String password = encoder.encode(Arrays.toString(salt) + dto.getPassword());
user.setPassword(DigestUtils.md5Hex(password));
} else {
user.setPassword(passwordEncoder.encode(dto.getPassword()));
}
}
}