package eu.dnetlib.repo.manager.service.security; import com.google.gson.JsonElement; import eu.dnetlib.repo.manager.domain.dto.Role; import eu.dnetlib.repo.manager.domain.dto.User; import eu.dnetlib.repo.manager.exception.ResourceNotFoundException; import eu.dnetlib.repo.manager.service.aai.registry.AaiRegistryService; import org.mitre.openid.connect.model.OIDCAuthenticationToken; import org.mitre.openid.connect.model.UserInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpClientErrorException; import java.util.ArrayList; import java.util.Collection; import java.util.List; @Service("authorizationService") public class AuthorizationServiceImpl implements AuthorizationService { private static final Logger logger = LoggerFactory.getLogger(AuthorizationServiceImpl.class); public static final String SUPER_ADMINISTRATOR = "SUPER_ADMINISTRATOR"; public static final String CONTENT_PROVIDER_DASHBOARD_ADMINISTRATOR = "CONTENT_PROVIDER_DASHBOARD_ADMINISTRATOR"; public static final String REGISTERED_USER = "REGISTERED_USER"; private final RoleMappingService roleMappingService; private final AaiRegistryService aaiRegistryService; private final AuthoritiesUpdater authoritiesUpdater; @Autowired AuthorizationServiceImpl(RoleMappingService roleMappingService, AaiRegistryService aaiRegistryService, AuthoritiesUpdater authoritiesUpdater) { this.roleMappingService = roleMappingService; this.aaiRegistryService = aaiRegistryService; this.authoritiesUpdater = authoritiesUpdater; } private String mapType(String type) { if (type.equals("datasource")) { type = "datasource"; } return type; } /** * Type = DATASOURCE */ @Override public String member(String type, String id) { return mapType(type).toUpperCase() + "_" + id.toUpperCase(); } @Override public boolean isMemberOf(String repoId) { String repoRole = roleMappingService.convertRepoIdToEncodedAuthorityId(repoId); return SecurityContextHolder.getContext().getAuthentication().getAuthorities() .stream().anyMatch(authority -> authority.toString().equals(repoRole)); } @Override public boolean isMemberOfInterface(String interfaceId) { //TODO blame Konstantinos Spyrou. He forced my hand... String repoId = interfaceId.split("::")[1] + "::" + interfaceId.split("::")[2]; return isMemberOf(repoId); } @Override public List getAdminsOfRepo(String repoId) { // find couId by role name String role = roleMappingService.getRoleIdByRepoId(repoId); Integer couId = aaiRegistryService.getCouId(role); return aaiRegistryService.getUsers(couId); } @Override public void addAdmin(String resourceId, String email) throws ResourceNotFoundException { String role = roleMappingService.getRoleIdByRepoId(resourceId); Integer couId = aaiRegistryService.getCouId(role); if (couId == null) { throw new ResourceNotFoundException("Cannot find CouId for role: " + role); } List coPersonIds = aaiRegistryService.getCoPersonIdsByEmail(email); for (Integer coPersonId : coPersonIds) { assert coPersonId != null; aaiRegistryService.assignMemberRole(coPersonId, couId); // Add role to user current authorities for (String userId : aaiRegistryService.getUserIdentifiersByEmail(email)) { authoritiesUpdater.addRole(userId, roleMappingService.convertRepoIdToAuthority(resourceId)); } } } @Override public void removeAdmin(String resourceId, String email) throws ResourceNotFoundException { String role = roleMappingService.getRoleIdByRepoId(resourceId); Integer couId = aaiRegistryService.getCouId(role); if (couId == null) { throw new ResourceNotFoundException("Cannot find CouId for role: " + role); } List coPersonIds = aaiRegistryService.getCoPersonIdsByEmail(email); for (Integer coPersonId : coPersonIds) { assert coPersonId != null; Integer roleId = aaiRegistryService.getRoleId(coPersonId, couId); if (roleId != null) { aaiRegistryService.removeMemberRole(coPersonId, couId, roleId); // Remove role from user current authorities for (String userId : aaiRegistryService.getUserIdentifiersByEmail(email)) { authoritiesUpdater.removeRole(userId, roleMappingService.convertRepoIdToAuthority(resourceId)); } } else { logger.error("Cannot find RoleId for role: {}", role); } } } @Override public void createAndAssignRoleToAuthenticatedUser(String resourceId, String roleDescription) { // Create new role String newRoleName = roleMappingService.getRoleIdByRepoId(resourceId); Role newRole = new Role(newRoleName, roleDescription); Integer couId; try { couId = aaiRegistryService.createRole(newRole); } catch (HttpClientErrorException e) { couId = aaiRegistryService.getCouId(newRoleName); if (couId == null) { logger.error(String.format("Could not create role '%s'", newRoleName), e); } } catch (Exception e) { logger.error(String.format("Could not create role '%s'", newRoleName), e); throw e; } // Assign new role to the current authenticated user Integer coPersonId = aaiRegistryService.getCoPersonIdByIdentifier(); if (couId != null) { aaiRegistryService.assignMemberRole(coPersonId, couId); // Add role to current user authorities authoritiesUpdater.addRole(roleMappingService.convertRepoIdToAuthority(resourceId)); } } @Override public Collection getUserRoles() { Collection roles; UserInfo userInfo = ((OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication()).getUserInfo(); roles = getUserRolesByEmail(userInfo.getEmail()); if (logger.isTraceEnabled()) { logger.trace("User Roles: {}", String.join(",", roles)); } return roles; } @Override public Collection getUserRolesByEmail(String email) { List coPersonIds = aaiRegistryService.getCoPersonIdsByEmail(email); List list = new ArrayList<>(); for (JsonElement element : aaiRegistryService.getRolesWithStatus(coPersonIds, AaiRegistryService.RoleStatus.ACTIVE)) { if (element.getAsJsonObject().get("CouId") != null) { list.add(element.getAsJsonObject().get("CouId").getAsInt()); } } return aaiRegistryService.getCouNames(list).values(); } }