package net.techreadiness.service; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Set; import javax.inject.Inject; import javax.jws.WebService; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import net.techreadiness.annotation.CoreDataModificationStatus; import net.techreadiness.annotation.CoreDataModificationStatus.ModificationType; import net.techreadiness.annotation.CoreSecured; import net.techreadiness.persistence.dao.RoleDAO; import net.techreadiness.persistence.dao.UserDAO; import net.techreadiness.persistence.dao.UserRoleDAO; import net.techreadiness.persistence.domain.RoleDO; import net.techreadiness.persistence.domain.UserDO; import net.techreadiness.persistence.domain.UserRoleDO; import net.techreadiness.security.CorePermissionCodes; import net.techreadiness.security.PermissionCode; import net.techreadiness.service.common.ValidationError; import net.techreadiness.service.exception.AuthorizationException; import net.techreadiness.service.exception.FaultInfo; import net.techreadiness.service.exception.ValidationServiceException; import net.techreadiness.service.object.UserRole; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.collect.Sets.SetView; @WebService @Service @Transactional public class UserRoleServiceImpl extends BaseServiceImpl implements UserRoleService { @Inject private UserService userService; @Inject private UserRoleDAO userRoleDao; @Inject private UserDAO userDao; @Inject private RoleDAO roleDao; @PersistenceContext private EntityManager em; @Override @CoreSecured(CorePermissionCodes.CORE_CUSTOMER_USER_ROLE_UPDATE) @CoreDataModificationStatus(modificationType = ModificationType.UPDATE, entityClass = UserRoleDO.class) public UserRole persist(ServiceContext context, Long userId, final Long roleId) { UserRoleDO userRoleDO = userRoleDao.getUserRoleByUserIdAndRoleId(userId, roleId); if (userRoleDO != null) { return getMappingService().getMapper().map(userRoleDO, UserRole.class); } RoleDO roleDO = roleDao.getById(roleId); if (isDelegatabale(context, roleId)) { userRoleDO = new UserRoleDO(); UserDO userDO = userDao.getById(userId); userRoleDO.setRole(roleDO); userRoleDO.setUser(userDO); userRoleDao.persist(userRoleDO); return getMappingService().getMapper().map(userRoleDO, UserRole.class); } throw new AuthorizationException(messageSource.getMessage("validation.userRole.delegationNotAllowed", new Object[] { context.getUserName(), roleDO.getName() }, Locale.getDefault())); } @Override @CoreDataModificationStatus(modificationType = ModificationType.DELETE, entityClass = UserRoleDO.class) public void delete(ServiceContext context, Long userId, Long roleId) { if (isDelegatabale(context, roleId)) { UserRoleDO userRoleDO = userRoleDao.getUserRoleByUserIdAndRoleId(userId, roleId); if (userRoleDO != null) { userRoleDao.delete(userRoleDO); } } else { RoleDO roleDO = roleDao.getById(roleId); throw new AuthorizationException(messageSource.getMessage("validation.userRole.delegationNotAllowed", new Object[] { context.getUserName(), roleDO.getName() }, Locale.getDefault())); } } @Override @CoreDataModificationStatus(modificationType = ModificationType.DELETE, entityClass = UserRoleDO.class) public void deleteAllUserRoles(ServiceContext context, Long userId) { List<UserRoleDO> userRoles = userRoleDao.findUserRolesByUser(userId); for (UserRoleDO userRole : userRoles) { if (isDelegatabale(context, userRole.getRole().getRoleId())) { userRoleDao.delete(userRole); } } } private boolean isDelegatabale(final ServiceContext context, final Long roleId) { if (ignoreConferrability(context)) { return true; } List<RoleDO> delegatableRoles = roleDao.findDelegatableRoles(context.getUserId(), context.getScopeId()); Iterable<RoleDO> filter = Iterables.filter(delegatableRoles, new Predicate<RoleDO>() { @Override public boolean apply(RoleDO input) { return input.getRoleId().equals(roleId); } }); return filter.iterator().hasNext(); } private boolean ignoreConferrability(ServiceContext context) { PermissionCode[] ignoreConferPerm = { CorePermissionCodes.CORE_SEARCH_IGNORE_ROLECONFER }; if (null == context.getUser()) { return false; } return userService.hasPermission(context, ignoreConferPerm); } @Override public void mergeUserRoles(ServiceContext context, Long userId, List<String> roleCodes) { // cannot accept empty role code list if (CollectionUtils.isEmpty(roleCodes)) { ValidationError error = new ValidationError("code", "Code", messageSource.getMessage( "validation.user.roleCodeRequired", new Object[] {}, Locale.getDefault())); ValidationServiceException e = new ValidationServiceException(new FaultInfo()); e.getFaultInfo().getAttributeErrors().add(error); throw e; } Set<RoleDO> requestedRoles = Sets.newHashSet(roleDao.findRolesByCode(context.getScopeId(), roleCodes)); Set<String> existing = new HashSet<>(); for (RoleDO role : requestedRoles) { existing.add(role.getCode()); } Set<String> requestedCodes = new HashSet<>(roleCodes); SetView<String> difference = Sets.difference(requestedCodes, existing); if (!difference.isEmpty()) { ValidationError error = new ValidationError("code", "Code", messageSource.getMessage( "validation.role.invalid.code", new Object[] { difference }, Locale.getDefault())); ValidationServiceException e = new ValidationServiceException(new FaultInfo()); e.getFaultInfo().getAttributeErrors().add(error); throw e; } mergeRoles(context.getUserId(), context.getScopeId(), userId, requestedRoles); } @Override public void mergeUserRoles(ServiceContext context, Long userId, Collection<Long> roleIds) { List<RoleDO> roles = roleDao.findById(roleIds); mergeRoles(context.getUserId(), context.getScopeId(), userId, new HashSet<>(roles)); } private void mergeRoles(Long conferingUserId, Long scopeId, Long userId, Set<RoleDO> roles) { Set<RoleDO> delegatableRoles = Sets.newHashSet(roleDao.findDelegatableRoles(conferingUserId, scopeId)); SetView<RoleDO> nonDelegatableRoles = Sets.difference(roles, delegatableRoles); if (nonDelegatableRoles.isEmpty()) { SetView<RoleDO> rolesToAdd = Sets.intersection(delegatableRoles, roles); SetView<RoleDO> rolesToDelete = Sets.difference(delegatableRoles, rolesToAdd); UserDO user = userDao.getById(userId); for (RoleDO role : rolesToAdd) { UserRoleDO userRole = userRoleDao.getUserRoleByUserIdAndRoleId(userId, role.getRoleId()); if (userRole == null) { userRole = new UserRoleDO(); userRole.setUser(user); userRole.setRole(role); userRoleDao.create(userRole); } } for (RoleDO role : rolesToDelete) { UserRoleDO userRole = userRoleDao.getUserRoleByUserIdAndRoleId(userId, role.getRoleId()); if (userRole != null) { userRoleDao.delete(userRole); } } } else { StringBuilder sb = new StringBuilder(); Iterator<RoleDO> i = nonDelegatableRoles.iterator(); while (i.hasNext()) { RoleDO role = i.next(); sb.append(role.getName()); if (i.hasNext()) { sb.append(", "); } } UserDO user = userDao.getById(conferingUserId); throw new AuthorizationException(messageSource.getMessage("validation.userRole.delegationNotAllowed", new Object[] { user.getUsername(), sb.toString() }, Locale.getDefault())); } } public void setRoleDao(RoleDAO roleDao) { this.roleDao = roleDao; } public void setUserDao(UserDAO userDao) { this.userDao = userDao; } public void setUserRoleDao(UserRoleDAO userRoleDao) { this.userRoleDao = userRoleDao; } }