Newer
Older
package it.inaf.ia2.gms.service;
import it.inaf.ia2.gms.exception.BadRequestException;
import it.inaf.ia2.gms.exception.UnauthorizedException;
import it.inaf.ia2.gms.persistence.GroupsRepository;
import it.inaf.ia2.gms.persistence.MembershipRepository;
import it.inaf.ia2.gms.persistence.model.Group;
import it.inaf.ia2.gms.persistence.model.User;
import it.inaf.ia2.gms.persistence.model.UserGroupPermission;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import it.inaf.ia2.gms.persistence.PermissionsRepository;
import it.inaf.ia2.gms.persistence.model.Membership;
import it.inaf.ia2.gms.model.GroupNode;
import it.inaf.ia2.gms.model.Permission;
import java.util.ArrayList;
import java.util.Map;
import java.util.UUID;
import org.springframework.transaction.annotation.Transactional;
@Service
public class GroupsService {
public static final String ROOT = "ROOT";
private final GroupsRepository groupsRepository;
private final PermissionsRepository permissionsRepository;
private final MembershipRepository membershipRepository;
@Autowired
public GroupsService(GroupsRepository groupsRepository,
PermissionsRepository permissionsRepository,
MembershipRepository membershipRepository) {
this.groupsRepository = groupsRepository;
this.permissionsRepository = permissionsRepository;
this.membershipRepository = membershipRepository;
createRootIfNecessary();
}
private void createRootIfNecessary() {
if (groupsRepository.count() == 0) {
Group root = new Group();
root.setId(ROOT);
root.setName(ROOT);
groupsRepository.save(root);
}
}
public Group addGroup(String parentId, String groupName, User user) {
Group parent = getGroupById(parentId);
if (!getPermissions(parent, user).contains(Permission.ADMIN)) {
throw new UnauthorizedException("Missing admin privileges");
}
if (parent.getChildrenGroups().stream()
.anyMatch(g -> g.getName().equals(groupName))) {
throw new BadRequestException("There is already a group named " + groupName);
}
Group group = new Group();
group.setId(UUID.randomUUID().toString());
group.setName(groupName);
group.setParentGroup(parent);
group = groupsRepository.save(group);
groupsRepository.save(parent);
return group;
}
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
public Group renameGroup(String groupId, String newGroupName, User user) {
Group group = getGroupById(groupId);
if (!getPermissions(group, user).contains(Permission.ADMIN)) {
throw new UnauthorizedException("Missing admin privileges");
}
if (group.getParentGroup().getChildrenGroups().stream()
.anyMatch(g -> g.getName().equals(newGroupName))) {
throw new BadRequestException("There is already a group named " + newGroupName);
}
group.setName(newGroupName);
return groupsRepository.save(group);
}
public Group deleteGroup(String groupId, User user) {
Group group = getGroupById(groupId);
if (!getPermissions(group, user).contains(Permission.ADMIN)) {
throw new UnauthorizedException("Missing admin privileges");
}
if (ROOT.equals(group.getId())) {
throw new UnauthorizedException("It is not possible to remove the ROOT");
}
Group parent = group.getParentGroup();
groupsRepository.delete(group);
return parent;
}
public List<GroupNode> getSubgroups(Group parent, User user) {
List<UserGroupPermission> permissions = getAllPermissions(user);
Map<String, GroupNode> nodesMap = new HashMap<>();
for (Group childGroup : parent.getChildrenGroups()) {
addGroupNodeToMap(childGroup, permissions, nodesMap);
}
List<GroupNode> nodes = new ArrayList<>(nodesMap.values());
// Sort by group name
nodes.sort((n1, n2) -> n1.getGroupName().compareTo(n2.getGroupName()));
return nodes;
}
public List<Permission> getPermissions(Group group, User user) {
List<UserGroupPermission> permissions = getAllPermissions(user);
Map<String, GroupNode> nodesMap = new HashMap<>();
addGroupNodeToMap(group, permissions, nodesMap);
GroupNode groupNode = nodesMap.get(group.getId());
if (groupNode == null) {
}
return groupNode.getPermissions();
}
/**
* Returns all the permissions, including also the calculated ones (the ones
* derived from the memberships).
*/
private List<UserGroupPermission> getAllPermissions(User user) {
// explicit permissions
List<UserGroupPermission> permissions = permissionsRepository.findBy_user(user);
List<UserGroupPermission> implicitPermissions = new ArrayList<>();
for (Membership membership : membershipRepository.findBy_user(user)) {
UserGroupPermission userGroupPermission = new UserGroupPermission();
userGroupPermission.setUser(user);
userGroupPermission.setGroup(membership.getGroup());
userGroupPermission.setPermission(Permission.TRAVERSE);
implicitPermissions.add(userGroupPermission);
}
permissions.addAll(implicitPermissions);
return permissions;
}
private void addGroupNodeToMap(Group group, List<UserGroupPermission> permissions, Map<String, GroupNode> nodesMap) {
for (UserGroupPermission permission : permissions) {
boolean isChild = false;
if (permission.getGroup().getId().equals(group.getId())
|| (isChild = isChildOf(permission.getGroup(), group))
|| (isParentOf(permission.getGroup(), group))) {
GroupNode node = nodesMap.get(group.getId());
if (node == null) {
node = getGroupNode(group);
}
if (isChild) {
// Traversal only
node.addPermission(Permission.TRAVERSE);
} else {
// Direct permission or permission inherited from parent
node.addPermission(permission.getPermission());
}
}
}
private GroupNode getGroupNode(Group group) {
GroupNode node = new GroupNode();
node.setGroupId(group.getId());
node.setGroupName(group.getName());
node.setHasChildren(!group.getChildrenGroups().isEmpty());
return node;
}
private boolean isChildOf(Group group, Group possibleParent) {
Group parent = group.getParentGroup();
if (parent == null) {
// ROOT has no parent
return false;
}
if (possibleParent.getId().equals(parent.getId())) {
return true;
}
// recursive call to parent group
return isChildOf(parent, possibleParent);
}
private boolean isParentOf(Group group, Group possibleChild) {
Group parent = possibleChild.getParentGroup();
if (parent == null) {
return false;
}
if (parent.getId().equals(group.getId())) {
return true;
}
// recursive call to parent group
return groupsRepository.findById(groupId)
.orElseThrow(() -> new BadRequestException("Group " + groupId + " not found"));
}
}