Skip to content
SearchService.java 6.78 KiB
Newer Older
package it.inaf.ia2.gms.service;

import it.inaf.ia2.gms.manager.GroupsManager;
import it.inaf.ia2.gms.model.Permission;
import it.inaf.ia2.gms.model.response.PaginatedData;
import it.inaf.ia2.gms.model.response.SearchResponseItem;
import it.inaf.ia2.gms.model.response.SearchResponseType;
Sonia Zorba's avatar
Sonia Zorba committed
import it.inaf.ia2.gms.model.response.UserGroup;
import it.inaf.ia2.gms.model.response.UserPermission;
import it.inaf.ia2.gms.model.response.UserSearchResponse;
import it.inaf.ia2.gms.persistence.GroupsDAO;
import it.inaf.ia2.gms.persistence.MembershipsDAO;
import it.inaf.ia2.gms.persistence.PermissionsDAO;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import it.inaf.ia2.gms.persistence.model.PermissionEntity;
import it.inaf.ia2.gms.authn.RapClient;
import java.util.ArrayList;
import java.util.List;
Sonia Zorba's avatar
Sonia Zorba committed
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SearchService {

    @Autowired
    private RapClient rapClient;

    @Autowired
    private GroupsManager groupsManager;

    @Autowired
    private GroupsDAO groupsDAO;

    @Autowired
    private PermissionsDAO permissionsDAO;

    @Autowired
    private MembershipsDAO membershipsDAO;

Sonia Zorba's avatar
Sonia Zorba committed
    @Autowired
    private GroupNameService groupNameService;

    /**
     * Generic search (both groups and users).
     */
    public PaginatedData<SearchResponseItem> search(String query, String userId, int page, int pageSize) {

        List<SearchResponseItem> items = searchUsers(query);
        items.addAll(searchGroups(query, userId));

        // sort by label
        items.sort((i1, i2) -> i1.getLabel().compareTo(i2.getLabel()));

        return new PaginatedData<>(items, page, pageSize);
    }

    private List<SearchResponseItem> searchUsers(String query) {
        return rapClient.getUsers(query).stream()
                .map(u -> {
                    SearchResponseItem item = new SearchResponseItem();
                    item.setType(SearchResponseType.USER);
                    item.setId(u.getId());
                    item.setLabel(u.getDisplayName());
                    return item;
                })
                .collect(Collectors.toList());
    }

    private List<SearchResponseItem> searchGroups(String query, String userId) {

        List<GroupEntity> allGroups = groupsDAO.searchGroups(query);

        // Select only the groups visible to the user
        List<PermissionEntity> permissions = permissionsDAO.findUserPermissions(userId);
        Set<GroupEntity> visibleGroups = getVisibleGroups(allGroups, permissions);
        List<SearchResponseItem> items = new ArrayList<>();
        Map<String, List<String>> groupNames = groupNameService.getNames(visibleGroups);

        for (GroupEntity group : visibleGroups) {
            SearchResponseItem item = new SearchResponseItem();
            item.setType(SearchResponseType.GROUP);
            item.setId(group.getId());
            List<String> names = groupNames.get(group.getId());
            item.setLabel(String.join(" / ", names));
            items.add(item);
        }

        return items;
    }

    /**
     * Retrieve additional data about an user displayed into the generic search.
     *
     * @param actorUserId the user who performed the search
     * @param targetUserId the user displayed into the search results
     */
    public UserSearchResponse getUserSearchResult(String actorUserId, String targetUserId) {

Sonia Zorba's avatar
Sonia Zorba committed
        // Select only the information visible to the actor user
        List<PermissionEntity> actorPermissions = permissionsDAO.findUserPermissions(actorUserId);
Sonia Zorba's avatar
Sonia Zorba committed
        UserSearchResponse response = new UserSearchResponse();

        List<UserGroup> groups = getUserGroups(targetUserId, actorPermissions);
        sortByGroupCompleteName(groups);
        response.setGroups(groups);

Sonia Zorba's avatar
Sonia Zorba committed
        List<UserPermission> permissions = getUserPermission(groupsManager.getRoot(), targetUserId, actorPermissions);
        sortByGroupCompleteName(permissions);
        response.setPermissions(permissions);
Sonia Zorba's avatar
Sonia Zorba committed

        response.setUser(rapClient.getUser(targetUserId));

Sonia Zorba's avatar
Sonia Zorba committed
        return response;
    }

    private List<UserGroup> getUserGroups(String targetUserId, List<PermissionEntity> actorPermissions) {

        List<GroupEntity> allGroups = membershipsDAO.getUserMemberships(targetUserId);
Sonia Zorba's avatar
Sonia Zorba committed
        // Select only groups visible to the actor user
        Set<GroupEntity> visibleGroups = getVisibleGroups(allGroups, actorPermissions);
        return groupNameService.getNames(visibleGroups).entrySet().stream()
Sonia Zorba's avatar
Sonia Zorba committed
                .map(entry -> {
                    UserGroup ug = new UserGroup();
                    ug.setGroupId(entry.getKey());
                    ug.setGroupCompleteName(entry.getValue());
                    return ug;
                })
                .collect(Collectors.toList());
    }

    private Set<GroupEntity> getVisibleGroups(List<GroupEntity> allGroups, List<PermissionEntity> permissions) {
        return allGroups.stream()
                .filter(g -> PermissionUtils.getGroupPermission(g, permissions).isPresent())
                .collect(Collectors.toSet());
    }

Sonia Zorba's avatar
Sonia Zorba committed
    public List<UserPermission> getUserPermission(GroupEntity group, String targetUserId, List<PermissionEntity> actorPermissions) {
Sonia Zorba's avatar
Sonia Zorba committed

        List<UserPermission> permissions = new ArrayList<>();

        // Super-admin user is able to see also other user permissions
Sonia Zorba's avatar
Sonia Zorba committed
        PermissionUtils.getGroupPermission(group, actorPermissions).ifPresent(permission -> {
            if (permission.equals(Permission.ADMIN)) {
Sonia Zorba's avatar
Sonia Zorba committed

                Map<String, PermissionEntity> targetUserPermissions
                        = permissionsDAO.findUserPermissions(targetUserId).stream()
                                .collect(Collectors.toMap(PermissionEntity::getGroupId, p -> p));

                Set<String> groupIds = targetUserPermissions.values().stream()
                        .map(p -> p.getGroupId()).collect(Collectors.toSet());
Sonia Zorba's avatar
Sonia Zorba committed

                for (Map.Entry<String, List<String>> entry : groupNameService.getNamesFromIds(groupIds).entrySet()) {
Sonia Zorba's avatar
Sonia Zorba committed
                    UserPermission up = new UserPermission();
                    up.setGroupId(entry.getKey());
                    up.setGroupCompleteName(entry.getValue());
                    up.setPermission(targetUserPermissions.get(entry.getKey()).getPermission());
                    permissions.add(up);
                }
Sonia Zorba's avatar
Sonia Zorba committed
        return permissions;

    private void sortByGroupCompleteName(List<? extends UserGroup> items) {
        items.sort((i1, i2) -> {
            String completeName1 = String.join(" / ", i1.getGroupCompleteName());
            String completeName2 = String.join(" / ", i2.getGroupCompleteName());
            return completeName1.compareTo(completeName2);
        });
    }