From 7b9e1ef4a7ab9e4080174634cb2efbb66a3d44f1 Mon Sep 17 00:00:00 2001 From: spyroukon Date: Tue, 6 Jul 2021 13:31:27 +0000 Subject: [PATCH] 1. update user authorities when adding/removing repositories 2. fixed some authorization expressions 3. refactoring --- .../controllers/AaiUserRoleController.java | 66 +++++------ .../manager/controllers/PiWikController.java | 11 +- .../controllers/RepositoryController.java | 8 +- .../service/RepositoryServiceImpl.java | 111 +++++++++--------- .../service/security/AaiUserRoleService.java | 23 ++-- .../security/AaiUserRoleServiceImpl.java | 8 +- .../service/security/AuthoritiesUpdater.java | 39 +++++- src/main/webapp/WEB-INF/spring-servlet.xml | 2 +- 8 files changed, 146 insertions(+), 122 deletions(-) diff --git a/src/main/java/eu/dnetlib/repo/manager/controllers/AaiUserRoleController.java b/src/main/java/eu/dnetlib/repo/manager/controllers/AaiUserRoleController.java index c446f45..2bc8341 100644 --- a/src/main/java/eu/dnetlib/repo/manager/controllers/AaiUserRoleController.java +++ b/src/main/java/eu/dnetlib/repo/manager/controllers/AaiUserRoleController.java @@ -4,6 +4,8 @@ import com.google.gson.JsonArray; import com.google.gson.JsonElement; import eu.dnetlib.repo.manager.domain.dto.Role; import eu.dnetlib.repo.manager.service.aai.registry.AaiRegistryService; +import eu.dnetlib.repo.manager.service.security.AaiUserRoleService; +import eu.dnetlib.repo.manager.service.security.AuthoritiesUpdater; import eu.dnetlib.repo.manager.utils.JsonUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -26,17 +28,16 @@ import java.util.List; public class AaiUserRoleController { private final AaiRegistryService aaiRegistryService; - - // TODO: Antonis K. This should be uncommented -// @Autowired -// private AuthoritiesUpdater authoritiesUpdater; -// -// @Autowired -// private AuthorizationService authorizationService; + private final AuthoritiesUpdater authoritiesUpdater; + private final AaiUserRoleService aaiUserRoleService; @Autowired - AaiUserRoleController(AaiRegistryService aaiRegistryService) { + AaiUserRoleController(AaiRegistryService aaiRegistryService, + AuthoritiesUpdater authoritiesUpdater, + AaiUserRoleService aaiUserRoleService) { this.aaiRegistryService = aaiRegistryService; + this.authoritiesUpdater = authoritiesUpdater; + this.aaiUserRoleService = aaiUserRoleService; } private String sendEmail() { @@ -45,10 +46,10 @@ public class AaiUserRoleController { } /** - * Create a new role with the given name and description. + * Get the role with the given name and description. **/ @RequestMapping(method = RequestMethod.GET, path = "/role/id/get") -// @PreAuthorize("hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") // TODO: Perhaps less roles here +// @PreAuthorize("hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") public Response getRole(@RequestParam(value = "type", defaultValue = "datasource") String type, @RequestParam("id") String id) { int roleId = aaiRegistryService.getCouId(type, id); return Response.status(HttpStatus.OK.value()).entity(JsonUtils.createResponse("Role id is: " + roleId).toString()).type(MediaType.APPLICATION_JSON).build(); @@ -58,7 +59,7 @@ public class AaiUserRoleController { * Create a new role with the given name and description. **/ @RequestMapping(method = RequestMethod.POST, path = "/createRole") - @PreAuthorize("hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") // TODO: Perhaps less roles here + @PreAuthorize("hasAnyAuthority('ROLE_ADMIN')") public Response createRole(@RequestBody Role role) { aaiRegistryService.createRole(role); return Response.status(HttpStatus.OK.value()).entity(JsonUtils.createResponse("Role has been created").toString()).type(MediaType.APPLICATION_JSON).build(); @@ -69,8 +70,7 @@ public class AaiUserRoleController { */ @ApiOperation(value = "subscribe") @RequestMapping(method = RequestMethod.POST, path = "/subscribe/{type}/{id}") - @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or (hasRole(@Converter.convertRepoIdToRoleId(#repository.id)) or hasRole(@Converter.convertRepoIdToRoleId(returnObject.id)))") - // TODO: Perhaps less roles here + @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") public Response subscribe(@PathVariable("type") String type, @PathVariable("id") String id) { Integer coPersonId = aaiRegistryService.getCoPersonIdByIdentifier(); if (coPersonId == null) { @@ -80,12 +80,10 @@ public class AaiUserRoleController { if (couId != null) { Integer role = aaiRegistryService.getRoleId(coPersonId, couId); aaiRegistryService.assignMemberRole(coPersonId, couId, role); - // TODO: Antonis K. This should be uncommented to make a role DATASOURCE.OP... for every new repo -// authoritiesUpdater.update(sendEmail(), old -> { -// HashSet authorities = new HashSet<>((Collection) old); -// authorities.add(new SimpleGrantedAuthority(authorizationService.member(type, id))); -// return authorities; -// }); + + // Add role to current user authorities + authoritiesUpdater.addRole(aaiUserRoleService.convertRepoIdToAuthority(id)); + return Response.status(HttpStatus.OK.value()).entity(JsonUtils.createResponse("Role has been assigned").toString()).type(MediaType.APPLICATION_JSON).build(); } else { return Response.status(HttpStatus.NOT_FOUND.value()).entity(JsonUtils.createResponse("Role has not been found").toString()).type(MediaType.APPLICATION_JSON).build(); @@ -98,7 +96,7 @@ public class AaiUserRoleController { */ @ApiOperation(value = "Remove role from member") @RequestMapping(method = RequestMethod.DELETE, path = "/{type}/{id}/member/{email}") - @PreAuthorize("hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") // TODO: Perhaps less roles here + @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") // FIXME: ?? public Response removeMemberRole(@PathVariable("type") String type, @PathVariable("id") String id, @PathVariable("email") String email) { Integer coPersonId = aaiRegistryService.getCoPersonIdByEmail(email); @@ -110,12 +108,10 @@ public class AaiUserRoleController { } if (couId != null && role != null) { aaiRegistryService.removeMemberRole(coPersonId, couId, role); - // TODO: Antonis K. This should be uncommented to make a role DATASOURCE.OP... for every new repo -// authoritiesUpdater.update(email, old -> { -// HashSet authorities = new HashSet<>((Collection) old); -// authorities.remove(new SimpleGrantedAuthority(authorizationService.member(type, id))); -// return authorities; -// }); + + // Remove role from current user authorities + authoritiesUpdater.removeRole(aaiUserRoleService.convertRepoIdToAuthority(id)); + return Response.status(HttpStatus.OK.value()).entity(JsonUtils.createResponse("Role has been removed").toString()).type(MediaType.APPLICATION_JSON).build(); } else { return Response.status(HttpStatus.NOT_FOUND.value()).entity(JsonUtils.createResponse("Role has not been found").toString()).type(MediaType.APPLICATION_JSON).build(); @@ -130,7 +126,7 @@ public class AaiUserRoleController { * Subscribe to role-repo by his email */ @RequestMapping(method = RequestMethod.POST, path = "/subscribe/repo-role/{id}") - @PreAuthorize("hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") // TODO: Perhaps less roles here + @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#id)") public Response subscribeRoleByEmail(@PathVariable("id") String id, @RequestParam("email") String email) { Integer coPersonId = aaiRegistryService.getCoPersonIdByEmail(email); if (coPersonId != null) { @@ -138,12 +134,10 @@ public class AaiUserRoleController { if (couId != null) { Integer role = aaiRegistryService.getRoleId(coPersonId, couId); aaiRegistryService.assignMemberRole(coPersonId, couId, role); - // TODO: Antonis K. This should be uncommented to make a role DATASOURCE.OP... for every new repo -// authoritiesUpdater.update(sendEmail(), old -> { -// HashSet authorities = new HashSet<>((Collection) old); -// authorities.add(new SimpleGrantedAuthority(authorizationService.member("datasource", id))); -// return authorities; -// }); + + // Add role to current user authorities + authoritiesUpdater.addRole(aaiUserRoleService.convertRepoIdToAuthority(id)); + return Response.status(HttpStatus.OK.value()).entity(JsonUtils.createResponse("Role has been assigned").toString()).type(MediaType.APPLICATION_JSON).build(); } else { return Response.status(HttpStatus.NOT_FOUND.value()).entity(JsonUtils.createResponse("Role has not been found").toString()).type(MediaType.APPLICATION_JSON).build(); @@ -160,7 +154,7 @@ public class AaiUserRoleController { * Get all the users that have the role that is associated with repoId */ @RequestMapping(method = RequestMethod.GET, path = "/repo/{id}/all-users") - @PreAuthorize("hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") // TODO: Perhaps less roles here + @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") // FIXME: ?? public ResponseEntity> getAllUsersOfARepo(@PathVariable("id") String id) { List userList = new ArrayList<>(); @@ -181,7 +175,7 @@ public class AaiUserRoleController { ///////////////////////////////////////////////////////////////////////////////////////////// @RequestMapping(method = RequestMethod.GET, path = "/users/couid/{id}") - @PreAuthorize("hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") + @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") public ResponseEntity getUsersByCouId(@PathVariable("id") Integer id) { // calls.getUserByCoId() return ResponseEntity.ok(aaiRegistryService.getUsersByCouId(id).toString()); @@ -189,7 +183,7 @@ public class AaiUserRoleController { @RequestMapping(method = RequestMethod.GET, path = "/user/roles") - @PreAuthorize("hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')") + @PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or hasRole('ROLE_USER') and authentication.userInfo.email==#email") public ResponseEntity> getRolesByEmail(@RequestParam("email") String email) { int coPersonId = aaiRegistryService.getCoPersonIdByEmail(email); List list = new ArrayList<>(); diff --git a/src/main/java/eu/dnetlib/repo/manager/controllers/PiWikController.java b/src/main/java/eu/dnetlib/repo/manager/controllers/PiWikController.java index 4a56799..a328399 100644 --- a/src/main/java/eu/dnetlib/repo/manager/controllers/PiWikController.java +++ b/src/main/java/eu/dnetlib/repo/manager/controllers/PiWikController.java @@ -6,7 +6,6 @@ import eu.dnetlib.repo.manager.domain.OrderByType; import eu.dnetlib.repo.manager.domain.Paging; import eu.dnetlib.repo.manager.domain.RepositoryServiceException; import eu.dnetlib.repo.manager.service.PiWikServiceImpl; -import eu.dnetlib.repo.manager.service.RepositoryService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -40,20 +39,16 @@ public class PiWikController { @Autowired private PiWikServiceImpl piWikService; - @Autowired - private RepositoryService repositoryService; - - // TODO: Antonis K. - replace here the registeredBy @RequestMapping(value = "/getPiwikSiteForRepo/{repositoryId}" , method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody - @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or ((@repositoryService.getRepositoryById(#repositoryId).registeredBy==authentication.userInfo.email or @repositoryService.getRepositoryById(#repositoryId).registeredBy=='null') and hasRole('ROLE_USER'))") + @PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#repositoryId) or (@repositoryService.getRepositoryById(#repositoryId).registeredBy=='null' and hasRole('ROLE_USER'))") public PiwikInfo getPiwikSiteForRepo(@PathVariable("repositoryId") String repositoryId) { return piWikService.getPiwikSiteForRepo(repositoryId); } @RequestMapping(value = "/savePiwikInfo" , method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_VALUE) - @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or ((@repositoryService.getRepositoryById(#piwikInfo.repositoryId).registeredBy==authentication.userInfo.email or @repositoryService.getRepositoryById(#piwikInfo.repositoryId).registeredBy=='null') and hasRole('ROLE_USER'))") + @PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#piwikInfo.repositoryId) or (@repositoryService.getRepositoryById(#piwikInfo.repositoryId).registeredBy=='null' and hasRole('ROLE_USER'))") public PiwikInfo savePiwikInfo(@RequestBody PiwikInfo piwikInfo) { return piWikService.savePiwikInfo(piwikInfo); } @@ -162,7 +157,7 @@ public class PiWikController { @RequestMapping(value = "/getOpenaireId/{repositoryId}" , method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody - @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or ((@repositoryService.getRepositoryById(#repositoryId).registeredBy==authentication.userInfo.email or @repositoryService.getRepositoryById(#repositoryId).registeredBy=='null') and hasRole('ROLE_USER'))") + @PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#repositoryId) or (@repositoryService.getRepositoryById(#repositoryId).registeredBy=='null' and hasRole('ROLE_USER'))") public String getOpenaireId(@PathVariable("repositoryId") String repositoryId){ return piWikService.getOpenaireId(repositoryId); } diff --git a/src/main/java/eu/dnetlib/repo/manager/controllers/RepositoryController.java b/src/main/java/eu/dnetlib/repo/manager/controllers/RepositoryController.java index ed59db5..f088a0d 100644 --- a/src/main/java/eu/dnetlib/repo/manager/controllers/RepositoryController.java +++ b/src/main/java/eu/dnetlib/repo/manager/controllers/RepositoryController.java @@ -11,6 +11,7 @@ import org.json.JSONException; import org.mitre.openid.connect.model.OIDCAuthenticationToken; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; +import org.springframework.security.access.prepost.PostAuthorize; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -82,12 +83,11 @@ public class RepositoryController { return repositoryService.searchRegisteredRepositories(country, typology, englishName, officialName, requestSortBy, order, page, pageSize); } - // TODO: Antonis K - Replace here the registeredBy @RequestMapping(value = "/getRepositoryById/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody - @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#id)") + @PostAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#id) or (returnObject.registeredBy=='null' and hasRole('ROLE_USER'))") public Repository getRepositoryById(@PathVariable("id") String id) throws JSONException, ResourceNotFoundException { Repository repo = repositoryService.getRepositoryById(id); @@ -137,10 +137,6 @@ public class RepositoryController { public Repository addRepository(@RequestParam("datatype") String datatype, @RequestBody Repository repository) throws Exception { - // TODO: - // 1) add repository - // 2) get repository id and create new role - // 3) assign new role to authenticated user return repositoryService.addRepository(datatype, repository); } diff --git a/src/main/java/eu/dnetlib/repo/manager/service/RepositoryServiceImpl.java b/src/main/java/eu/dnetlib/repo/manager/service/RepositoryServiceImpl.java index f9ffb71..02b4780 100644 --- a/src/main/java/eu/dnetlib/repo/manager/service/RepositoryServiceImpl.java +++ b/src/main/java/eu/dnetlib/repo/manager/service/RepositoryServiceImpl.java @@ -13,7 +13,8 @@ import eu.dnetlib.repo.manager.domain.*; import eu.dnetlib.repo.manager.domain.dto.Role; import eu.dnetlib.repo.manager.exception.ResourceNotFoundException; import eu.dnetlib.repo.manager.service.aai.registry.AaiRegistryService; -import eu.dnetlib.repo.manager.service.security.AuthorizationService; +import eu.dnetlib.repo.manager.service.security.AaiUserRoleService; +import eu.dnetlib.repo.manager.service.security.AuthoritiesUpdater; import eu.dnetlib.repo.manager.utils.Converter; import gr.uoa.di.driver.enabling.vocabulary.VocabularyLoader; import org.apache.commons.codec.digest.DigestUtils; @@ -24,12 +25,15 @@ import org.json.JSONObject; import org.mitre.openid.connect.model.OIDCAuthenticationToken; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Lazy; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; +import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponents; @@ -45,58 +49,58 @@ import java.util.stream.Collectors; @Service("repositoryService") public class RepositoryServiceImpl implements RepositoryService { + private static final Logger LOGGER = Logger.getLogger(RepositoryServiceImpl.class); + + private final AaiUserRoleService aaiUserRoleService; + private final AaiRegistryService registryCalls; + private final AuthoritiesUpdater authoritiesUpdater; + private final RestTemplate restTemplate; + private final VocabularyLoader vocabularyLoader; + private final PiWikService piWikService; + private final EmailUtils emailUtils; + private final ValidatorService validatorService; + @Value("${api.baseAddress}") private String baseAddress; @Value("${services.repo-manager.adminEmail}") private String adminEmail; - @Autowired - RestTemplate restTemplate; - - private HttpHeaders httpHeaders; - - private final String[] vocabularyNames = {"dnet:countries", "dnet:datasource_typologies", "dnet:compatibilityLevel"}; - - private static final Logger LOGGER = Logger.getLogger(RepositoryServiceImpl.class); - @Value("${services.repomanager.usageStatisticsDiagramsBaseURL}") private String usageStatisticsDiagramsBaseURL; @Value("${services.repomanager.usageStatisticsNumbersBaseURL}") private String usageStatisticsNumbersBaseURL; - @Autowired - private VocabularyLoader vocabularyLoader; + + private static final Map> dataSourceClass = new HashMap<>(); + private static final Map invertedDataSourceClass = new HashMap<>(); + + + private final String[] vocabularyNames = {"dnet:countries", "dnet:datasource_typologies", "dnet:compatibilityLevel"}; + private final Map vocabularyMap = new ConcurrentHashMap<>(); + private final Map countriesMap = new HashMap<>(); + private final Map inverseCountriesMap = new HashMap<>(); + + private HttpHeaders httpHeaders; @Autowired - private PiWikService piWikService; - - @Autowired - private EmailUtils emailUtils; - - @Autowired - ValidatorService validatorService; - - @Autowired - private AaiRegistryService registryCalls; - - // TODO: Antonis K. This should be uncommented -// @Autowired -// private AuthoritiesUpdater authoritiesUpdater; - - @Autowired - private AuthorizationService authorizationService; - - - private Map vocabularyMap = new ConcurrentHashMap<>(); - - private Map countriesMap = new HashMap<>(); - private Map inverseCountriesMap = new HashMap<>(); - - private static Map> dataSourceClass = new HashMap<>(); - - private static Map invertedDataSourceClass = new HashMap<>(); + public RepositoryServiceImpl(AaiUserRoleService aaiUserRoleService, + AaiRegistryService registryCalls, + AuthoritiesUpdater authoritiesUpdater, + VocabularyLoader vocabularyLoader, EmailUtils emailUtils, + RestTemplate restTemplate, + @Lazy ValidatorService validatorService, + @Lazy PiWikService piWikService) { + this.aaiUserRoleService = aaiUserRoleService; + this.registryCalls = registryCalls; + this.authoritiesUpdater = authoritiesUpdater; + this.vocabularyLoader = vocabularyLoader; + this.piWikService = piWikService; + this.emailUtils = emailUtils; + this.validatorService = validatorService; + this.restTemplate = restTemplate; + } private String sendEmail() { OIDCAuthenticationToken authenticationToken = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); @@ -508,31 +512,32 @@ public class RepositoryServiceImpl implements RepositoryService { this.latentUpdate(repository, SecurityContextHolder.getContext().getAuthentication()); } - // TODO: Antonis K. - Create new role ROLE_(datasource.datasourceId) and assign it to the user that created the folder (+ replace :: with $$) - // Create new role ( careful ... replace :: with $$ ) - String newRoleName = repository.getId().replaceAll(":", "\\$"); - String newRoleDescr = repository.getId().replaceAll(":", "\\$"); - Role newRole = new Role(newRoleName, newRoleDescr); + // TODO: move the following code elsewhere (creation and assignment of role to user) ?? + // Create new role + String newRoleName = aaiUserRoleService.getRoleIdByRepoId(repository.getId()); + Role newRole = new Role(newRoleName, repository.getOfficialName()); + Integer couId = null; try { - registryCalls.createRole(newRole); + couId = registryCalls.createRole(newRole); + } catch (HttpClientErrorException e) { + couId = registryCalls.getCouId(newRoleName); + if (couId == null) { + LOGGER.error(String.format("Could not create role '%s'", newRoleName), e); + } } catch (Exception e) { - LOGGER.debug("Exception on create role during add repository", e); + LOGGER.error(String.format("Could not create role '%s'", newRoleName), e); throw e; } // Assign new role to the user that created it Integer coPersonId = registryCalls.getCoPersonIdByIdentifier(); - Integer couId = registryCalls.getCouId("datasource", newRoleName); if (couId != null) { Integer role = registryCalls.getRoleId(coPersonId, couId); try { registryCalls.assignMemberRole(coPersonId, couId, role); - // TODO: Antonis K. This should be uncommented to make a role DATASOURCE.OP... for every new repo -// authoritiesUpdater.update(sendEmail(), old -> { -// HashSet authorities = new HashSet<>((Collection) old); -// authorities.add(new SimpleGrantedAuthority(authorizationService.member("datasource", newRoleName))); -// return authorities; -// }); + + // Add role to current user authorities + authoritiesUpdater.addRole(aaiUserRoleService.convertRepoIdToAuthority(repository.getId())); } catch (Exception e) { LOGGER.debug("Exception on assign role to user during add repository", e); throw e; diff --git a/src/main/java/eu/dnetlib/repo/manager/service/security/AaiUserRoleService.java b/src/main/java/eu/dnetlib/repo/manager/service/security/AaiUserRoleService.java index 6bba27e..aa77d61 100644 --- a/src/main/java/eu/dnetlib/repo/manager/service/security/AaiUserRoleService.java +++ b/src/main/java/eu/dnetlib/repo/manager/service/security/AaiUserRoleService.java @@ -12,33 +12,34 @@ public interface AaiUserRoleService { String getRepoNameWithoutType(String fullName, String prefix); /** - * @param repoId - * @param prefix - * @return + * @param repoId Repository Id + * @return Converts {@param repoId} to a role Id. */ - String getRoleIdByRepoId(String repoId, String prefix); + String getRoleIdByRepoId(String repoId); /** - * @param repoId + * @param repoId Repository Id * @return */ String convertRepoIdToAuthorityId(String repoId); /** - * @param repoId - * @return + * @param repoId Repository Id + * @return Converts {@param repoId} to {@link String} role id url encoded ($ -> %24) + * // TODO: remove role encoding and perform url decoding when mapping authorities. (Must be performed in all OpenAIRE projects because of Redis) */ String convertRepoIdToEncodedAuthorityId(String repoId); /** - * @param repoId - * @return + * @param repoId Repository Id + * @return Converts {@param repoId} to {@link SimpleGrantedAuthority} with the role url encoded ($ -> %24) + * // TODO: remove role encoding and perform url decoding when mapping authorities. (Must be performed in all OpenAIRE projects because of Redis) */ SimpleGrantedAuthority convertRepoIdToAuthority(String repoId); /** - * @param repoId - * @return + * @param repoId Repository Id to check. + * @return Checks if a user is a member of a repository or not. */ boolean isMemberOf(String repoId); diff --git a/src/main/java/eu/dnetlib/repo/manager/service/security/AaiUserRoleServiceImpl.java b/src/main/java/eu/dnetlib/repo/manager/service/security/AaiUserRoleServiceImpl.java index 86dfb5e..dede120 100644 --- a/src/main/java/eu/dnetlib/repo/manager/service/security/AaiUserRoleServiceImpl.java +++ b/src/main/java/eu/dnetlib/repo/manager/service/security/AaiUserRoleServiceImpl.java @@ -30,9 +30,10 @@ public class AaiUserRoleServiceImpl implements AaiUserRoleService { } @Override - public String getRoleIdByRepoId(String repoId, String prefix) { + public String getRoleIdByRepoId(String repoId) { String roleId = ""; - if (repoId != null && prefix != null) { + String prefix = production ? null : "beta." + "datasource"; + if (repoId != null) { roleId = createRepoRoleName(prefix, repoId); return roleId; } else { @@ -62,9 +63,6 @@ public class AaiUserRoleServiceImpl implements AaiUserRoleService { @Override public SimpleGrantedAuthority convertRepoIdToAuthority(String repoId) { String role = convertRepoIdToEncodedAuthorityId(repoId); - if (role != null) { - role = URLEncoder.encode(role); - } return new SimpleGrantedAuthority(role); } diff --git a/src/main/java/eu/dnetlib/repo/manager/service/security/AuthoritiesUpdater.java b/src/main/java/eu/dnetlib/repo/manager/service/security/AuthoritiesUpdater.java index e724bfd..b064532 100644 --- a/src/main/java/eu/dnetlib/repo/manager/service/security/AuthoritiesUpdater.java +++ b/src/main/java/eu/dnetlib/repo/manager/service/security/AuthoritiesUpdater.java @@ -6,12 +6,15 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.common.exceptions.UnauthorizedClientException; import org.springframework.security.web.context.HttpSessionSecurityContextRepository; import org.springframework.session.ExpiringSession; import org.springframework.session.FindByIndexNameSessionRepository; import org.springframework.stereotype.Service; import java.util.Collection; +import java.util.HashSet; import java.util.Map; @@ -23,7 +26,7 @@ public class AuthoritiesUpdater extends HttpSessionSecurityContextRepository { @Autowired FindByIndexNameSessionRepository sessions; - public void update(String id, Update update) { + public void update(String id, Collection authorities) { if (sessions != null) { Map map = sessions. findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, id); @@ -35,7 +38,6 @@ public class AuthoritiesUpdater extends HttpSessionSecurityContextRepository { Authentication authentication = securityContext.getAuthentication(); if (authentication instanceof OIDCAuthenticationToken) { OIDCAuthenticationToken authOIDC = (OIDCAuthenticationToken) authentication; - Collection authorities = update.authorities(authentication.getAuthorities()); logger.debug(authorities); securityContext.setAuthentication(new OIDCAuthenticationToken(authOIDC.getSub(), authOIDC.getIssuer(), authOIDC.getUserInfo(), authorities, authOIDC.getIdToken(), @@ -49,6 +51,39 @@ public class AuthoritiesUpdater extends HttpSessionSecurityContextRepository { } } + public void update(String id, Update update) { + Collection authorities = update.authorities(SecurityContextHolder.getContext().getAuthentication().getAuthorities()); + this.update(id, authorities); + } + + public void addRole(GrantedAuthority role) { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth instanceof OIDCAuthenticationToken) { + OIDCAuthenticationToken oidcAuth = (OIDCAuthenticationToken) auth; + this.update(oidcAuth.getUserInfo().getEmail(), old -> { + HashSet authorities = new HashSet<>(old); + authorities.add(role); + return authorities; + }); + } else { + throw new UnauthorizedClientException("User auth is not instance of OIDCAuthenticationToken"); + } + } + + public void removeRole(GrantedAuthority role) { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth instanceof OIDCAuthenticationToken) { + OIDCAuthenticationToken oidcAuth = (OIDCAuthenticationToken) auth; + this.update(oidcAuth.getUserInfo().getEmail(), old -> { + HashSet authorities = new HashSet<>(old); + authorities.remove(role); + return authorities; + }); + } else { + throw new UnauthorizedClientException("User auth is not instance of OIDCAuthenticationToken"); + } + } + public interface Update { Collection authorities(Collection old); } diff --git a/src/main/webapp/WEB-INF/spring-servlet.xml b/src/main/webapp/WEB-INF/spring-servlet.xml index e32c2ad..d8964ef 100644 --- a/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/src/main/webapp/WEB-INF/spring-servlet.xml @@ -5,7 +5,7 @@ xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd" >