All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.molgenis.data.security.auth.GroupService Maven / Gradle / Ivy

There is a newer version: 8.4.5
Show newest version
package org.molgenis.data.security.auth;

import static com.google.common.collect.Lists.newArrayList;
import static java.util.Objects.requireNonNull;
import static org.molgenis.data.meta.model.PackageMetadata.PACKAGE;
import static org.molgenis.data.security.auth.RoleMetadata.ROLE;
import static org.molgenis.security.core.SidUtils.createRoleAuthority;

import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.molgenis.data.DataService;
import org.molgenis.data.Fetch;
import org.molgenis.data.UnknownEntityException;
import org.molgenis.data.meta.model.Package;
import org.molgenis.data.meta.model.PackageFactory;
import org.molgenis.data.meta.model.PackageMetadata;
import org.molgenis.data.security.exception.IsAlreadyMemberException;
import org.molgenis.data.security.exception.NotAValidGroupRoleException;
import org.molgenis.data.security.permission.RoleMembershipService;
import org.molgenis.security.core.model.GroupValue;
import org.molgenis.security.core.runas.RunAsSystem;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class GroupService {
  private final DataService dataService;
  private final PackageFactory packageFactory;
  private final GroupMetadata groupMetadata;
  private final RoleMembershipService roleMembershipService;
  private final RoleMembershipMetadata roleMembershipMetadata;

  public static final String MANAGER = "Manager";
  public static final String EDITOR = "Editor";
  public static final String VIEWER = "Viewer";

  public static final String AUTHORITY_MANAGER = createRoleAuthority(MANAGER.toUpperCase());
  public static final String AUTHORITY_EDITOR = createRoleAuthority(EDITOR.toUpperCase());
  public static final String AUTHORITY_VIEWER = createRoleAuthority(VIEWER.toUpperCase());

  public static final Set DEFAULT_ROLES = ImmutableSet.of(MANAGER, EDITOR, VIEWER);

  @SuppressWarnings("squid:S00107")
  GroupService(
      PackageFactory packageFactory,
      DataService dataService,
      GroupMetadata groupMetadata,
      RoleMembershipService roleMembershipService,
      RoleMembershipMetadata roleMembershipMetadata) {
    this.packageFactory = requireNonNull(packageFactory);
    this.dataService = requireNonNull(dataService);
    this.groupMetadata = requireNonNull(groupMetadata);
    this.roleMembershipService = requireNonNull(roleMembershipService);
    this.roleMembershipMetadata = requireNonNull(roleMembershipMetadata);
  }

  /**
   * Creates {@link Group}, {@link Role} and {@link Package} entities and adds them to the
   * dataService.
   *
   * @param groupValue details of the group that should be created
   */
  @Transactional
  public void persist(GroupValue groupValue) {
    Package rootPackage = packageFactory.create(groupValue.getRootPackage());
    dataService.add(PACKAGE, rootPackage);
  }

  @RunAsSystem
  public Collection getGroups() {
    return dataService.findAll(GroupMetadata.GROUP, Group.class).collect(Collectors.toList());
  }

  /**
   * Get the group entity by its unique name.
   *
   * @param groupName unique group name
   * @return group with given name
   * @throws UnknownEntityException in case no group with given name can be retrieved
   */
  @RunAsSystem
  public Group getGroup(String groupName) {
    Fetch roleFetch = new Fetch().field(RoleMetadata.NAME).field(RoleMetadata.LABEL);
    Fetch fetch =
        new Fetch()
            .field(GroupMetadata.ROLES, roleFetch)
            .field(GroupMetadata.NAME)
            .field(GroupMetadata.LABEL)
            .field(GroupMetadata.DESCRIPTION)
            .field(GroupMetadata.ID)
            .field(GroupMetadata.PUBLIC)
            .field(GroupMetadata.ROOT_PACKAGE);

    Group group =
        dataService
            .query(GroupMetadata.GROUP, Group.class)
            .eq(GroupMetadata.NAME, groupName)
            .fetch(fetch)
            .findOne();
    if (group == null) {
      throw new UnknownEntityException(
          groupMetadata, groupMetadata.getAttribute(GroupMetadata.NAME), groupName);
    }
    return group;
  }

  /**
   * Add member to group. User can only be added to a role that belongs to the group. The user can
   * only have a single role within the group
   *
   * @param group group to add the user to in the given role
   * @param user user to be added in the given role to the given group
   * @param role role in which the given user is to be added to given group
   */
  @RunAsSystem
  public void addMember(final Group group, final User user, final Role role) {
    ArrayList groupRoles = newArrayList(group.getRoles());
    Collection memberships = roleMembershipService.getMemberships(groupRoles);
    boolean isGroupRole = isGroupRole(role, groupRoles);

    if (!isGroupRole) {
      throw new NotAValidGroupRoleException(role, group);
    }

    boolean isMember = memberships.stream().parallel().anyMatch(m -> m.getUser().equals(user));

    if (isMember) {
      throw new IsAlreadyMemberException(user, group);
    }

    roleMembershipService.addUserToRole(user, role);
  }

  private boolean isGroupRole(Role role, ArrayList groupRoles) {
    return groupRoles.stream().anyMatch(groupRole -> groupRole.getName().equals(role.getName()));
  }

  @RunAsSystem
  public void removeMember(final Group group, final User user) {
    ArrayList groupRoles = newArrayList(group.getRoles());
    final RoleMembership membership = findRoleMembership(user, groupRoles);
    roleMembershipService.removeMembership(membership);
  }

  @RunAsSystem
  public void updateMemberRole(final Group group, final User member, final Role newRole) {
    ArrayList groupRoles = newArrayList(group.getRoles());
    boolean isGroupRole = isGroupRole(newRole, groupRoles);

    if (!isGroupRole) {
      throw new NotAValidGroupRoleException(newRole, group);
    }

    final RoleMembership roleMembership = findRoleMembership(member, groupRoles);
    roleMembershipService.updateMembership(roleMembership, newRole);
  }

  @RunAsSystem
  public boolean isGroupNameAvailable(final GroupValue groupValue) {
    String rootPackageName = groupValue.getRootPackage().getName();
    final Package existingPackage =
        dataService.query(PACKAGE, Package.class).eq(PackageMetadata.ID, rootPackageName).findOne();
    return existingPackage == null;
  }

  private UnknownEntityException unknownMembershipForUser(User user) {
    return new UnknownEntityException(
        roleMembershipMetadata,
        roleMembershipMetadata.getAttribute(RoleMembershipMetadata.USER),
        user.getUsername());
  }

  private RoleMembership findRoleMembership(User member, List groupRoles) {
    Collection memberships = roleMembershipService.getMemberships(groupRoles);
    return memberships.stream()
        .filter(m -> m.getUser().getId().equals(member.getId()))
        .findFirst()
        .orElseThrow(() -> unknownMembershipForUser(member));
  }

  public void deleteGroup(String groupName) {
    Group group =
        dataService
            .query(GroupMetadata.GROUP, Group.class)
            .eq(GroupMetadata.NAME, groupName)
            .findOne();
    if (group == null) {
      throw new UnknownEntityException(
          groupMetadata, groupMetadata.getAttribute(GroupMetadata.NAME), groupName);
    }
    dataService.delete(PACKAGE, group.getRootPackage());
  }

  public void updateExtendsRole(Group group, Role groupRole, Role memberRole) {
    List newIncludes = removeIncludedGroupRoles(group, memberRole);
    if (!isGroupRole(groupRole, newArrayList(group.getRoles()))) {
      throw new NotAValidGroupRoleException(groupRole, group);
    }
    newIncludes.add(groupRole);
    memberRole.setIncludes(newIncludes);
    dataService.update(ROLE, memberRole);
  }

  public void removeExtendsRole(Group group, Role memberRole) {
    List newIncludes = removeIncludedGroupRoles(group, memberRole);
    memberRole.setIncludes(newIncludes);
    dataService.update(ROLE, memberRole);
  }

  private List removeIncludedGroupRoles(Group group, Role memberRole) {
    ArrayList includes = newArrayList(memberRole.getIncludes());
    ArrayList groupRoles = newArrayList(group.getRoles());
    return includes.stream()
        .filter(role -> !isGroupRole(role, groupRoles))
        .collect(Collectors.toList());
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy