package alien4cloud.security.groups;
import static alien4cloud.utils.AlienUtils.safe;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Resource;
import javax.inject.Inject;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import alien4cloud.exception.AlreadyExistException;
import alien4cloud.exception.InvalidArgumentException;
import alien4cloud.exception.NotFoundException;
import alien4cloud.security.event.GroupDeletedEvent;
import alien4cloud.security.event.UserDeletedEvent;
import alien4cloud.security.groups.rest.UpdateGroupRequest;
import alien4cloud.security.model.Group;
import alien4cloud.security.model.Role;
import alien4cloud.security.model.User;
import alien4cloud.security.users.UserService;
import alien4cloud.utils.ReflectionUtil;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class GroupService {
@Resource
private IAlienGroupDao alienGroupDao;
@Resource
private UserService userService;
@Inject
private ApplicationEventPublisher publisher;
public void updateGroup(String groupId, UpdateGroupRequest groupUpdateRequest) {
Group group = retrieveGroup(groupId);
String currentGroupName = group.getName();
ReflectionUtil.mergeObject(groupUpdateRequest, group);
if (group.getName() == null || group.getName().isEmpty()) {
throw new InvalidArgumentException("Group's name cannot be set to null or empty");
}
// Check with precedent value
if (!currentGroupName.equals(group.getName())) {
// If group name has changed, must check unicity
checkGroupNameUniqueness(group.getName());
}
alienGroupDao.save(group);
}
public void deleteGroup(String groupId) throws IOException, ClassNotFoundException {
Group group = retrieveGroup(groupId);
alienGroupDao.delete(groupId);
publisher.publishEvent(new GroupDeletedEvent(this, group));
}
public User addUserToGroup(String username, String groupId) {
Group group = retrieveGroup(groupId);
User user = userService.retrieveUser(username);
Set<String> users = group.getUsers() == null ? new HashSet<String>() : group.getUsers();
users.add(user.getUsername());
group.setUsers(users);
alienGroupDao.save(group);
// update groupRoles in the user
userService.addGroupToUser(group, user);
return user;
}
public User removeUserFromGroup(String username, String groupId) {
Group group = retrieveGroup(groupId);
if (CollectionUtils.isEmpty(group.getUsers())) {
return null;
}
User user = userService.retrieveUser(username);
group.getUsers().remove(user.getUsername());
alienGroupDao.save(group);
// update groupRoles in users objects
userService.removeGroupFromUser(user, group);
return user;
}
public String createGroup(String name, String email, String description, Set<String> roles, Set<String> users) throws AlreadyExistException {
checkGroupNameUniqueness(name);
Group group = new Group(name);
group.setId(UUID.randomUUID().toString());
group.setDescription(description);
group.setEmail(email);
if (CollectionUtils.isNotEmpty(roles)) {
Set<String> formatedRoles = Sets.newHashSet();
for (String role : roles) {
formatedRoles.add(Role.getStringFormatedRole(role));
}
group.setRoles(formatedRoles);
}
List<User> usersList = null;
if (CollectionUtils.isNotEmpty(users)) {
usersList = Lists.newArrayList();
Set<String> usersSet = Sets.newHashSet();
for (String username : users) {
usersList.add(userService.retrieveUser(username));
usersSet.add(username);
}
group.setUsers(usersSet);
}
alienGroupDao.save(group);
if (CollectionUtils.isNotEmpty(usersList)) {
for (User user : usersList) {
userService.addGroupToUser(group, user);
}
}
return group.getId();
}
public void addRoleToGroup(String groupId, String role) {
Group group = retrieveGroup(groupId);
Set<String> rolesSet = group.getRoles() == null ? new HashSet<String>() : group.getRoles();
rolesSet.add(Role.getStringFormatedRole(role));
group.setRoles(rolesSet);
alienGroupDao.save(group);
// update groupRoles in users objects
if (CollectionUtils.isNotEmpty(group.getUsers())) {
for (String username : group.getUsers()) {
userService.addGroupRoleToUser(username, role);
}
}
}
public Group retrieveGroup(String id) {
Group group = alienGroupDao.find(id);
if (group == null) {
throw new NotFoundException("Group [" + id + "] cannot be found");
}
return group;
}
public void removeRoleFromGroup(String groupId, String role) {
Group group = retrieveGroup(groupId);
if (CollectionUtils.isEmpty(group.getRoles())) {
return;
}
group.getRoles().remove(Role.getStringFormatedRole(role));
alienGroupDao.save(group);
// update groupRoles in users objects
if (CollectionUtils.isNotEmpty(group.getUsers())) {
for (String username : group.getUsers()) {
userService.updateUserGroupRoles(username);
}
}
}
/**
* check if the given groupId is unique in the system
*
* @param groupName
*/
private void checkGroupNameUniqueness(String groupName) throws AlreadyExistException {
if (alienGroupDao.isGroupWithNameExist(groupName)) {
log.debug("Create group <{}> impossible (already exists)", groupName);
// a group already exist with the given id.
throw new AlreadyExistException("A Group with the given id <" + groupName + "> already exists.");
} else {
log.debug("Create group <{}>", groupName);
}
}
/**
* Listener for user deleted. Removes the user from all groups where he was
*
* @param event
*/
@EventListener
public void userDeletedEventListener(UserDeletedEvent event) {
User user = event.getUser();
for (String groupId : safe(user.getGroups())) {
Group group = retrieveGroup(groupId);
if (safe(group.getUsers()).contains(user.getUsername())) {
group.getUsers().remove(user.getUsername());
alienGroupDao.save(group);
}
}
}
}