Skip to content
GroupsService.java 4.56 KiB
Newer Older
package it.inaf.ia2.gms.service;

import it.inaf.ia2.gms.exception.BadRequestException;
import it.inaf.ia2.gms.persistence.GroupsRepository;
import it.inaf.ia2.gms.persistence.UsersRepository;
import it.inaf.ia2.gms.persistence.model.Group;
import it.inaf.ia2.gms.persistence.model.User;
import it.inaf.ia2.gms.persistence.model.UserGroup;
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.service.model.GroupNode;
import it.inaf.ia2.gms.service.model.Permission;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

@Service
public class GroupsService {

    public static final String ROOT = "ROOT";

    private final GroupsRepository groupsRepository;
    private final UsersRepository usersRepository;
    private final PermissionsRepository permissionsRepository;

    @Autowired
    public GroupsService(GroupsRepository groupsRepository,
            UsersRepository usersRepository, PermissionsRepository permissionsRepository) {
        this.groupsRepository = groupsRepository;
        this.usersRepository = usersRepository;
        this.permissionsRepository = permissionsRepository;
        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) {
        Group parent = getGroupById(parentId);
        Group group = new Group();
        group.setId(UUID.randomUUID().toString());
        group.setName(groupName);
        group.setParentGroup(parent);
        parent.getGroupsMembers().add(group);
        group = groupsRepository.save(group);
        groupsRepository.save(parent);
        return group;
    }

    public List<Group> getSubgroups(String parentId) {
        Group parent = getGroupById(parentId);
        return groupsRepository.findByParentGroup(parent);
    }

    public List<GroupNode> getSubgroups(String parentGroupId, String userId) {

        User user = usersRepository.findById(userId)
                .orElseThrow(() -> new BadRequestException("User " + userId + " not found"));

        Group parent = getGroupById(parentGroupId);

        List<UserGroup> permissions = permissionsRepository.findBy_user(user);

        Map<String, GroupNode> nodes = new LinkedHashMap<>();

        for (Group childGroup : parent.getGroupsMembers()) {

            Iterator<UserGroup> ite = permissions.iterator();
            while (ite.hasNext()) {

                UserGroup permission = ite.next();

                boolean isChild = false;
                if (permission.getGroup().getId().equals(childGroup.getId())
                        || (isChild = isChildOf(permission.getGroup(), parentGroupId))) {

                    GroupNode node = nodes.get(childGroup.getId());
                    if (node == null) {
                        node = getGroupNode(childGroup);
                    }

                    if (isChild) {
                        // Traversal only
                        node.getPermissions().add(Permission.READ);
                    } else {
                        // Direct permission
                        node.getPermissions().add(permission.getPermission());
                    }

                    nodes.put(childGroup.getId(), node);
                    ite.remove();
                }
            }
        }

        // TODO: pagination
        return new ArrayList<>(nodes.values());
    }

    private GroupNode getGroupNode(Group group) {
        GroupNode node = new GroupNode();
        node.setGroupId(group.getId());
        node.setGroupName(group.getName());
        node.setHasChildren(!group.getGroupsMembers().isEmpty());
        return node;
    }

    private boolean isChildOf(Group group, String parentGroupId) {
        Group parent = group.getParentGroup();
        if (parent == null) {
            // ROOT has no parent
            return false;
        }
        if (parentGroupId.equals(parent.getId())) {
            return true;
        }
        // recursive call to parent group
        return isChildOf(parent, parentGroupId);
    }

    private Group getGroupById(String groupId) {
        return groupsRepository.findById(groupId)
                .orElseThrow(() -> new BadRequestException("Group " + groupId + " not found"));
    }
}