1. refactoring and changes of rest api

This commit is contained in:
Konstantinos Spyrou 2021-07-09 19:01:49 +00:00
parent fc4b182e0f
commit e0c193f86b
19 changed files with 609 additions and 322 deletions

View File

@ -84,7 +84,7 @@ public class FrontEndLinkURIAuthenticationSuccessHandler implements Authenticati
accessToken.setPath("/");
Cookie openAIREUser = new Cookie("openAIREUser", new Gson().toJson(userInfo));
Cookie openAIREUser = new Cookie("openAIREUser", URLEncoder.encode(new Gson().toJson(userInfo), "UTF-8"));
openAIREUser.setMaxAge(accessToken.getMaxAge());
openAIREUser.setPath("/");
if (aai_mode.equalsIgnoreCase("production") || aai_mode.equalsIgnoreCase("beta"))

View File

@ -6,22 +6,48 @@ import eu.dnetlib.repo.manager.service.security.AuthoritiesMapper;
import org.apache.log4j.Logger;
import org.mitre.openid.connect.client.OIDCAuthoritiesMapper;
import org.mitre.openid.connect.model.UserInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@ComponentScan
@Component
public class OpenAIREAuthoritiesMapper implements OIDCAuthoritiesMapper {
private static final Logger logger = Logger.getLogger(OpenAIREAuthoritiesMapper.class);
@Value("${services.repo-manager.adminEmail}")
String adminEmail;
@Override
public Collection<? extends GrantedAuthority> mapAuthorities(JWT jwtToken, UserInfo userInfo) {
logger.info("entitlements" + userInfo.getSource().getAsJsonArray("edu_person_entitlements").size());
JsonArray entitlements = userInfo.getSource().getAsJsonArray("edu_person_entitlements");
return AuthoritiesMapper.map(entitlements);
JsonArray entitlements = null;
List<GrantedAuthority> authorities = new ArrayList<>();
if (userInfo != null && userInfo.getSource() != null) {
if (userInfo.getSource().getAsJsonArray("edu_person_entitlements") != null) {
entitlements = userInfo.getSource().getAsJsonArray("edu_person_entitlements");
} else if (userInfo.getSource().getAsJsonArray("eduperson_entitlement") != null) {
entitlements = userInfo.getSource().getAsJsonArray("eduperson_entitlement");
} else {
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
logger.error("Could not read user 'edu_person_entitlements' && 'eduperson_entitlement'\nAdding default role 'ROLE_USER' to user: " + userInfo.toString());
}
logger.debug("user info: " + userInfo + "\nentitlements: " + entitlements);
// FIXME: delete this if statement
if (userInfo.getEmail() != null && userInfo.getEmail().equals(adminEmail)) {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
authorities.addAll(AuthoritiesMapper.map(entitlements));
}
return authorities;
}
}

View File

@ -1,196 +0,0 @@
package eu.dnetlib.repo.manager.controllers;
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;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping(value = "/aai-user-management")
@Api(description = "AAI User Management", value = "aai-user-management")
public class AaiUserRoleController {
private final AaiRegistryService aaiRegistryService;
private final AuthoritiesUpdater authoritiesUpdater;
private final AaiUserRoleService aaiUserRoleService;
@Autowired
AaiUserRoleController(AaiRegistryService aaiRegistryService,
AuthoritiesUpdater authoritiesUpdater,
AaiUserRoleService aaiUserRoleService) {
this.aaiRegistryService = aaiRegistryService;
this.authoritiesUpdater = authoritiesUpdater;
this.aaiUserRoleService = aaiUserRoleService;
}
private String sendEmail() {
OIDCAuthenticationToken authenticationToken = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
return authenticationToken.getUserInfo().getEmail();
}
/**
* 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')")
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();
}
/**
* Create a new role with the given name and description.
**/
@RequestMapping(method = RequestMethod.POST, path = "/createRole")
@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();
}
/**
* Subscribe to a type(Community, etc.) with id(ee, egi, etc.)
*/
@ApiOperation(value = "subscribe")
@RequestMapping(method = RequestMethod.POST, path = "/subscribe/{type}/{id}")
@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) {
coPersonId = aaiRegistryService.getCoPersonIdByEmail();
}
Integer couId = aaiRegistryService.getCouId(type, id);
if (couId != null) {
Integer role = aaiRegistryService.getRoleId(coPersonId, couId);
aaiRegistryService.assignMemberRole(coPersonId, couId, role);
// 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();
}
}
/**
* Remove the member role from user with email for a type(Community, etc.) with id(ee, egi, etc.)
*/
@ApiOperation(value = "Remove role from member")
@RequestMapping(method = RequestMethod.DELETE, path = "/{type}/{id}/member/{email}")
@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);
if (coPersonId != null) {
Integer couId = aaiRegistryService.getCouId(type, id);
Integer role = null;
if (couId != null) {
role = aaiRegistryService.getRoleId(coPersonId, couId);
}
if (couId != null && role != null) {
aaiRegistryService.removeMemberRole(coPersonId, couId, role);
// 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();
}
} else {
return Response.status(HttpStatus.NOT_FOUND.value()).entity(JsonUtils.createResponse("User has not been found").toString()).type(MediaType.APPLICATION_JSON).build();
}
}
/**
* Subscribe to role-repo by his email
*/
@RequestMapping(method = RequestMethod.POST, path = "/subscribe/repo-role/{id}")
@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) {
Integer couId = aaiRegistryService.getCouId("datasource", id);
if (couId != null) {
Integer role = aaiRegistryService.getRoleId(coPersonId, couId);
aaiRegistryService.assignMemberRole(coPersonId, couId, role);
// 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();
}
} else {
return Response.status(HttpStatus.NOT_FOUND.value()).entity(JsonUtils.createResponse("User with this email has not been found").toString()).type(MediaType.APPLICATION_JSON).build();
}
}
/**
* 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_ADMIN', 'ROLE_PROVIDE_ADMIN')") // FIXME: ??
public ResponseEntity<List<String>> getAllUsersOfARepo(@PathVariable("id") String id) {
List<String> userList = new ArrayList<>();
// find couId by role name
Integer couId = aaiRegistryService.getCouId("datasource", id);
if (couId != null) {
JsonArray users = aaiRegistryService.getUsersByCouId(couId);
for (JsonElement jsonElement : users) {
userList.add(jsonElement.toString());
}
return ResponseEntity.ok(userList);
}
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
@RequestMapping(method = RequestMethod.GET, path = "/users/couid/{id}")
@PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')")
public ResponseEntity<String> getUsersByCouId(@PathVariable("id") Integer id) {
// calls.getUserByCoId()
return ResponseEntity.ok(aaiRegistryService.getUsersByCouId(id).toString());
}
@RequestMapping(method = RequestMethod.GET, path = "/user/roles")
@PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or hasRole('ROLE_USER') and authentication.userInfo.email==#email")
public ResponseEntity<List<String>> getRolesByEmail(@RequestParam("email") String email) {
int coPersonId = aaiRegistryService.getCoPersonIdByEmail(email);
List<String> list = new ArrayList<>();
for (JsonElement element : aaiRegistryService.getRoles(coPersonId)) {
list.add(element.toString());
}
return ResponseEntity.ok(list);
}
}

View File

@ -42,13 +42,13 @@ public class PiWikController {
@RequestMapping(value = "/getPiwikSiteForRepo/{repositoryId}" , method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#repositoryId) or (@repositoryService.getRepositoryById(#repositoryId).registeredBy=='null' and hasRole('ROLE_USER'))")
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @authorizationService.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("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#piwikInfo.repositoryId) or (@repositoryService.getRepositoryById(#piwikInfo.repositoryId).registeredBy=='null' and hasRole('ROLE_USER'))")
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @authorizationService.isMemberOf(#piwikInfo.repositoryId) or (@repositoryService.getRepositoryById(#piwikInfo.repositoryId).registeredBy=='null' and hasRole('ROLE_USER'))")
public PiwikInfo savePiwikInfo(@RequestBody PiwikInfo piwikInfo) {
return piWikService.savePiwikInfo(piwikInfo);
}
@ -157,7 +157,7 @@ public class PiWikController {
@RequestMapping(value = "/getOpenaireId/{repositoryId}" , method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#repositoryId) or (@repositoryService.getRepositoryById(#repositoryId).registeredBy=='null' and hasRole('ROLE_USER'))")
@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @authorizationService.isMemberOf(#repositoryId) or (@repositoryService.getRepositoryById(#repositoryId).registeredBy=='null' and hasRole('ROLE_USER'))")
public String getOpenaireId(@PathVariable("repositoryId") String repositoryId){
return piWikService.getOpenaireId(repositoryId);
}

View File

@ -3,20 +3,26 @@ package eu.dnetlib.repo.manager.controllers;
import eu.dnetlib.domain.data.Repository;
import eu.dnetlib.domain.data.RepositoryInterface;
import eu.dnetlib.repo.manager.domain.*;
import eu.dnetlib.repo.manager.domain.dto.User;
import eu.dnetlib.repo.manager.exception.ResourceNotFoundException;
import eu.dnetlib.repo.manager.service.RepositoryServiceImpl;
import eu.dnetlib.repo.manager.service.security.AuthorizationService;
import eu.dnetlib.repo.manager.utils.JsonUtils;
import io.swagger.annotations.Api;
import org.apache.log4j.Logger;
import org.json.JSONException;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
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;
import org.springframework.web.bind.annotation.*;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@ -28,8 +34,15 @@ public class RepositoryController {
private static final Logger logger = Logger.getLogger(RepositoryController.class);
private final RepositoryServiceImpl repositoryService; //TODO: why not RepositoryService??
private final AuthorizationService authorizationService;
@Autowired
private RepositoryServiceImpl repositoryService;
RepositoryController(RepositoryServiceImpl repositoryService,
AuthorizationService authorizationService) {
this.repositoryService = repositoryService;
this.authorizationService = authorizationService;
}
@RequestMapping(value = "/getCountries", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ -87,7 +100,7 @@ public class RepositoryController {
@RequestMapping(value = "/getRepositoryById/{id}", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@PostAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#id) or (returnObject.registeredBy=='null' and hasRole('ROLE_USER'))")
@PostAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @authorizationService.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);
@ -124,7 +137,7 @@ public class RepositoryController {
@RequestMapping(value = "/getRepositoryInterface/{id}", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@PostAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#id) or (@repositoryService.getRepositoryById(#id).registeredBy=='null' and hasRole('ROLE_USER'))")
@PostAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or @authorizationService.isMemberOf(#id) or (@repositoryService.getRepositoryById(#id).registeredBy=='null' and hasRole('ROLE_USER'))")
public List<RepositoryInterface> getRepositoryInterface(@PathVariable("id") String id) throws JSONException {
return repositoryService.getRepositoryInterface(id);
}
@ -132,7 +145,7 @@ public class RepositoryController {
@RequestMapping(value = "/addRepository", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
// @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or (hasRole(@aaiUserRoleService.convertRepoIdToRoleId(#repository.id)) or hasRole(@aaiUserRoleService.convertRepoIdToRoleId(returnObject.id)))")
// @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or (hasRole(@authorizationService.convertRepoIdToRoleId(#repository.id)) or hasRole(@authorizationService.convertRepoIdToRoleId(returnObject.id)))")
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or hasRole('ROLE_USER')")
public Repository addRepository(@RequestParam("datatype") String datatype,
@RequestBody Repository repository) throws Exception {
@ -164,13 +177,13 @@ public class RepositoryController {
@RequestMapping(value = "/updateRepository", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#repository.id)")
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or @authorizationService.isMemberOf(#repository.id)")
public Repository updateRepository(@RequestBody Repository repository, Authentication authentication) throws Exception {
return repositoryService.updateRepository(repository, authentication);
}
@RequestMapping(value = "/deleteInterface/", method = RequestMethod.DELETE)
@PreAuthorize("@aaiUserRoleService.isMemberOf(#id)")
@PreAuthorize("@authorizationService.isMemberOf(#id)")
public void deleteRepositoryInterface(@RequestParam("id") String id,
@RequestParam("registeredBy") String registeredBy) {
repositoryService.deleteRepositoryInterface(id, registeredBy);
@ -179,7 +192,7 @@ public class RepositoryController {
@RequestMapping(value = "/addInterface", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#repoId)")
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or @authorizationService.isMemberOf(#repoId)")
public RepositoryInterface addRepositoryInterface(@RequestParam("datatype") String datatype,
@RequestParam("repoId") String repoId,
@RequestParam("registeredBy") String registeredBy,
@ -235,11 +248,44 @@ public class RepositoryController {
@RequestMapping(value = "/updateRepositoryInterface", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or @aaiUserRoleService.isMemberOf(#repoId)")
@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_PROVIDE_ADMIN') or @authorizationService.isMemberOf(#repoId)")
public RepositoryInterface updateRepositoryInterface(@RequestParam("repoId") String repoId,
@RequestParam("registeredBy") String registeredBy,
@RequestParam(value = "comment", required = false) String comment,
@RequestBody RepositoryInterface repositoryInterface) throws Exception {
return repositoryService.updateRepositoryInterface(repoId, registeredBy, comment, repositoryInterface);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Get all the admins of the repository
*/
@RequestMapping(method = RequestMethod.GET, path = "{repoId}/admins")
@PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @authorizationService.isMemberOf(#id)")
public ResponseEntity<List<User>> getAdminsOfARepo(@PathVariable("repoId") String id) {
return new ResponseEntity<>(authorizationService.getAdminsOfRepo(id), HttpStatus.OK);
}
/**
* Subscribe to repo by email
*/
@RequestMapping(method = RequestMethod.POST, path = "{repoId}/admins")
@PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @authorizationService.isMemberOf(#id)")
public Response subscribeByEmail(@PathVariable("repoId") String id, @RequestBody String email) throws ResourceNotFoundException {
authorizationService.addAdmin(id, email);
return Response.status(HttpStatus.OK.value()).entity(JsonUtils.createResponse("Role has been assigned").toString()).type(javax.ws.rs.core.MediaType.APPLICATION_JSON).build();
}
/**
* Unsubscribe from repo by email
*/
@RequestMapping(method = RequestMethod.DELETE, path = "{repoId}/admins/{email}")
@PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or @authorizationService.isMemberOf(#id)")
public Response unsubscribeByEmail(@PathVariable("id") String id, @RequestBody String email) throws ResourceNotFoundException {
authorizationService.removeAdmin(id, email);
return Response.status(HttpStatus.OK.value()).entity(JsonUtils.createResponse("Role has been removed").toString()).type(javax.ws.rs.core.MediaType.APPLICATION_JSON).build();
}
}

View File

@ -0,0 +1,131 @@
package eu.dnetlib.repo.manager.controllers;
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.RoleMappingService;
import eu.dnetlib.repo.manager.service.security.AuthoritiesMapper;
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;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.mitre.openid.connect.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@RestController
@RequestMapping(value = "/role-management")
@Api(description = "Role Management", value = "role-management")
public class UserRoleController {
private final AaiRegistryService aaiRegistryService;
private final AuthoritiesUpdater authoritiesUpdater;
private final RoleMappingService roleMappingService;
@Autowired
UserRoleController(AaiRegistryService aaiRegistryService,
AuthoritiesUpdater authoritiesUpdater,
RoleMappingService roleMappingService) {
this.aaiRegistryService = aaiRegistryService;
this.authoritiesUpdater = authoritiesUpdater;
this.roleMappingService = roleMappingService;
}
/**
* Get the role with the given id.
**/
@RequestMapping(method = RequestMethod.GET, path = "/role/{id}")
// @PreAuthorize("hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')")
public Response getRole(@RequestParam(value = "type", defaultValue = "datasource") String type, @PathVariable("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();
}
/**
* Create a new role with the given name and description.
**/
@RequestMapping(method = RequestMethod.POST, path = "/role")
@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();
}
/**
* Subscribe to a type(Community, etc.) with id(ee, egi, etc.)
*/
@ApiOperation(value = "subscribe")
@RequestMapping(method = RequestMethod.POST, path = "/subscribe/{type}/{id}")
@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) {
coPersonId = aaiRegistryService.getCoPersonIdByEmail();
}
Integer couId = aaiRegistryService.getCouId(type, id);
if (couId != null) {
Integer role = aaiRegistryService.getRoleId(coPersonId, couId);
aaiRegistryService.assignMemberRole(coPersonId, couId, role);
// Add role to current authorities
authoritiesUpdater.addRole(roleMappingService.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();
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////
@RequestMapping(method = RequestMethod.GET, path = "/users/couid/{id}")
@PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN')")
public ResponseEntity<String> getUsersByCouId(@PathVariable("id") Integer id) {
// calls.getUserByCoId()
return ResponseEntity.ok(aaiRegistryService.getUsersByCouId(id).toString());
}
@RequestMapping(method = RequestMethod.GET, path = "/users/{email}/roles")
@PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_PROVIDE_ADMIN') or hasRole('ROLE_USER') and authentication.userInfo.email==#email")
public ResponseEntity<Collection<String>> getRolesByEmail(@PathVariable("email") String email) {
int coPersonId = aaiRegistryService.getCoPersonIdByEmail(email);
List<Integer> list = new ArrayList<>();
// FIXME: getRoles returns all roles of user, requested and active
for (JsonElement element : aaiRegistryService.getRoles(coPersonId)) {
list.add(element.getAsJsonObject().get("CouId").getAsInt());
}
return ResponseEntity.ok(aaiRegistryService.getCouNames(list).values());
}
@RequestMapping(method = RequestMethod.GET, path = "/user/roles/my")
@PreAuthorize("hasRole('ROLE_USER')")
public ResponseEntity<Collection<String>> getRoleNames() {
List<String> roles;
JsonArray entitlements = null;
UserInfo userInfo = ((OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication()).getUserInfo();
if (userInfo.getSource().getAsJsonArray("edu_person_entitlements") != null) {
entitlements = userInfo.getSource().getAsJsonArray("edu_person_entitlements");
} else if (userInfo.getSource().getAsJsonArray("eduperson_entitlement") != null) {
entitlements = userInfo.getSource().getAsJsonArray("eduperson_entitlement");
} else {
return ResponseEntity.ok(null);
}
roles = AuthoritiesMapper.entitlementRoles(entitlements);
return ResponseEntity.ok(roles);
}
}

View File

@ -0,0 +1,61 @@
package eu.dnetlib.repo.manager.domain.dto;
import org.mitre.openid.connect.model.UserInfo;
public class User {
private String sub;
private String firstName;
private String lastName;
private String email;
public User() {}
public User(String sub, String firstName, String lastName, String email) {
this.sub = sub;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public static User from(UserInfo userInfo) {
User user = new User();
user.setSub(user.getSub());
user.setFirstName(userInfo.getGivenName());
user.setLastName(userInfo.getFamilyName());
user.setEmail(userInfo.getEmail());
return user;
}
public String getSub() {
return sub;
}
public void setSub(String sub) {
this.sub = sub;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

View File

@ -9,6 +9,10 @@ public class ResourceNotFoundException extends Exception {
super("Resource Not Found");
}
public ResourceNotFoundException(String message) {
super(message);
}
public ResourceNotFoundException(String id, String resourceType) {
super(resourceType + " with id " + id + " was not found");
}

View File

@ -33,11 +33,9 @@ public class EmailUtilsImpl implements EmailUtils {
private boolean override = false, logonly = false;
private String overrideEmail = null, from = null;
@Autowired
private MailLibrary mailLibrary;
@Autowired
private CascadingPropertyLoader pLoader;
private final MailLibrary mailLibrary;
private final CascadingPropertyLoader pLoader;
private final RepositoryService repositoryService;
@Value("${services.repo-manager.baseUrl}")
private String baseUrl;
@ -55,7 +53,12 @@ public class EmailUtilsImpl implements EmailUtils {
private String valBaseUrl;
@Autowired
private RepositoryService repositoryService;
EmailUtilsImpl(MailLibrary mailLibrary, CascadingPropertyLoader pLoader,
RepositoryService repositoryService) {
this.mailLibrary = mailLibrary;
this.pLoader = pLoader;
this.repositoryService = repositoryService;
}
@PostConstruct

View File

@ -13,7 +13,7 @@ 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.AaiUserRoleService;
import eu.dnetlib.repo.manager.service.security.RoleMappingService;
import eu.dnetlib.repo.manager.service.security.AuthoritiesUpdater;
import eu.dnetlib.repo.manager.utils.Converter;
import gr.uoa.di.driver.enabling.vocabulary.VocabularyLoader;
@ -30,7 +30,6 @@ 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;
@ -51,7 +50,7 @@ public class RepositoryServiceImpl implements RepositoryService {
private static final Logger LOGGER = Logger.getLogger(RepositoryServiceImpl.class);
private final AaiUserRoleService aaiUserRoleService;
private final RoleMappingService roleMappingService;
private final AaiRegistryService registryCalls;
private final AuthoritiesUpdater authoritiesUpdater;
private final RestTemplate restTemplate;
@ -85,14 +84,15 @@ public class RepositoryServiceImpl implements RepositoryService {
private HttpHeaders httpHeaders;
@Autowired
public RepositoryServiceImpl(AaiUserRoleService aaiUserRoleService,
public RepositoryServiceImpl(RoleMappingService roleMappingService,
AaiRegistryService registryCalls,
AuthoritiesUpdater authoritiesUpdater,
VocabularyLoader vocabularyLoader, EmailUtils emailUtils,
VocabularyLoader vocabularyLoader,
RestTemplate restTemplate,
@Lazy EmailUtils emailUtils,
@Lazy ValidatorService validatorService,
@Lazy PiWikService piWikService) {
this.aaiUserRoleService = aaiUserRoleService;
this.roleMappingService = roleMappingService;
this.registryCalls = registryCalls;
this.authoritiesUpdater = authoritiesUpdater;
this.vocabularyLoader = vocabularyLoader;
@ -514,7 +514,7 @@ public class RepositoryServiceImpl implements RepositoryService {
// TODO: move the following code elsewhere (creation and assignment of role to user) ??
// Create new role
String newRoleName = aaiUserRoleService.getRoleIdByRepoId(repository.getId());
String newRoleName = roleMappingService.getRoleIdByRepoId(repository.getId());
Role newRole = new Role(newRoleName, repository.getOfficialName());
Integer couId = null;
try {
@ -537,7 +537,7 @@ public class RepositoryServiceImpl implements RepositoryService {
registryCalls.assignMemberRole(coPersonId, couId, role);
// Add role to current user authorities
authoritiesUpdater.addRole(aaiUserRoleService.convertRepoIdToAuthority(repository.getId()));
authoritiesUpdater.addRole(roleMappingService.convertRepoIdToAuthority(repository.getId()));
} catch (Exception e) {
LOGGER.debug("Exception on assign role to user during add repository", e);
throw e;
@ -686,9 +686,14 @@ public class RepositoryServiceImpl implements RepositoryService {
this.updateCompliance(repoId, repositoryInterface.getId(), repositoryInterface.getCompliance());
this.updateValidationSet(repoId, repositoryInterface.getId(), repositoryInterface.getAccessSet());
Repository e = this.getRepositoryById(repoId);
emailUtils.sendAdminUpdateInterfaceEmail(e, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
emailUtils.sendUserUpdateInterfaceEmail(e, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
Repository repository = this.getRepositoryById(repoId);
try {
emailUtils.sendAdminUpdateInterfaceEmail(repository, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
emailUtils.sendUserUpdateInterfaceEmail(repository, comment, repositoryInterface, SecurityContextHolder.getContext().getAuthentication());
} catch (Exception e) {
LOGGER.warn("Could not send emails", e);
}
submitInterfaceValidation(getRepositoryById(repoId), registeredBy, repositoryInterface, true);
return repositoryInterface;

View File

@ -3,6 +3,7 @@ package eu.dnetlib.repo.manager.service.aai.registry;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import eu.dnetlib.repo.manager.domain.dto.Role;
import eu.dnetlib.repo.manager.domain.dto.User;
import java.util.List;
import java.util.Map;
@ -247,4 +248,7 @@ public interface AaiRegistryService {
* @return
*/
Map<Integer, String> getCouNames(List<Integer> couIds);
// TODO: add description
List<User> getUsers(Integer couId);
}

View File

@ -4,6 +4,7 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import eu.dnetlib.repo.manager.domain.dto.Role;
import eu.dnetlib.repo.manager.domain.dto.User;
import eu.dnetlib.repo.manager.service.aai.registry.utils.RegistryUtils;
import eu.dnetlib.repo.manager.utils.HttpUtils;
import org.apache.log4j.Logger;
@ -270,6 +271,20 @@ public class RegistryCalls implements AaiRegistryService {
return infos;
}
@Override
public List<User> getUsers(Integer couId) {
List<User> users = new ArrayList<>();
JsonArray infos = getUserEmailByCouId(couId, false);
infos.forEach(info -> {
User user = new User();
user.setEmail(info.getAsJsonObject().get("email").getAsString());
users.add(user);
});
return users;
}
@Override
public JsonArray getUserNamesByCouId(Integer couId, boolean admin) {
Map<String, String> params = new HashMap<>();

View File

@ -2,16 +2,16 @@ package eu.dnetlib.repo.manager.service.security;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import java.net.URLEncoder;
@Service("aaiUserRoleService")
public class AaiUserRoleServiceImpl implements AaiUserRoleService {
@Service("roleMappingService")
public class AaiRoleMappingService implements RoleMappingService {
private static final Logger logger = Logger.getLogger(AaiUserRoleServiceImpl.class);
private static final Logger logger = Logger.getLogger(AaiRoleMappingService.class);
@Value("${registry.production:true}")
private boolean production;
@ -29,6 +29,11 @@ public class AaiUserRoleServiceImpl implements AaiUserRoleService {
return null;
}
@Override
public String getRepoIdByRoleId(String roleId) {
return roleId.replaceFirst(".*datasource\\.", "").replace("$", ":");
}
@Override
public String getRoleIdByRepoId(String repoId) {
String roleId = "";
@ -42,6 +47,23 @@ public class AaiUserRoleServiceImpl implements AaiUserRoleService {
}
@Override
public String convertAuthorityIdToRepoId(String authorityId) {
String repo = "";
if (authorityId != null) {
repo = authorityId
.replaceFirst(".*datasource\\.", "")
.replace("$", ":")
.toLowerCase();
}
return repo;
}
@Override
public String convertAuthorityToRepoId(GrantedAuthority authority) {
return convertAuthorityIdToRepoId(authority.toString());
}
@Override
public String convertRepoIdToAuthorityId(String repoId) {
StringBuilder roleBuilder = new StringBuilder();
@ -65,12 +87,4 @@ public class AaiUserRoleServiceImpl implements AaiUserRoleService {
String role = convertRepoIdToEncodedAuthorityId(repoId);
return new SimpleGrantedAuthority(role);
}
@Override
public boolean isMemberOf(String repoId) {
String repoRole = convertRepoIdToEncodedAuthorityId(repoId);
return SecurityContextHolder.getContext().getAuthentication().getAuthorities()
.parallelStream().anyMatch(authority -> authority.toString().equals(repoRole));
}
}

View File

@ -6,6 +6,7 @@ import org.apache.log4j.Logger;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.net.URLDecoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -13,42 +14,65 @@ import java.util.regex.Pattern;
public class AuthoritiesMapper {
private static final Logger logger = Logger.getLogger(AuthoritiesMapper.class);
private static final String ENTITLEMENT_REGEX = "urn:geant:openaire[.]eu:group:([^:]*):?(.*)?:role=member#aai[.]openaire[.]eu";
private AuthoritiesMapper() {
}
public static Collection<? extends GrantedAuthority> map(JsonArray entitlements) {
HashSet<SimpleGrantedAuthority> authorities = new HashSet<>();
//entitlements.add("urn:geant:openaire.eu:group:datasource.opendoar____$$3469:role=member#aai.openaire.eu");
public static Collection<GrantedAuthority> map(JsonArray entitlements) {
HashSet<GrantedAuthority> authorities = new HashSet<>();
provideRoles(entitlements, authorities);
entityRoles(entitlements, authorities);
return authorities;
}
private static void entityRoles(JsonArray entitlements, Set<SimpleGrantedAuthority> authorities) {
String regex = "urn:geant:openaire[.]eu:group:([^:]*):?(.*)?:role=member#aai[.]openaire[.]eu";
for (JsonElement obj : entitlements) {
Matcher matcher = Pattern.compile(regex).matcher(obj.getAsString());
if (matcher.find()) {
StringBuilder sb = new StringBuilder();
if (matcher.group(1) != null && matcher.group(1).length() > 0) {
sb.append(matcher.group(1).replace("+-+", "_").replaceAll("[+.]", "_").toUpperCase());
}
if (matcher.group(2).length() > 0) {
sb.append("_");
if (matcher.group(2).equals("admins")) {
sb.append("MANAGER");
} else {
sb.append(matcher.group(2).toUpperCase());
public static List<String> entitlementRoles(JsonArray entitlements) {
List<String> roles = new ArrayList<>();
if (entitlements != null) {
for (JsonElement obj : entitlements) {
Matcher matcher = Pattern.compile(ENTITLEMENT_REGEX).matcher(obj.getAsString());
if (matcher.find()) {
StringBuilder sb = new StringBuilder();
if (matcher.group(1) != null && matcher.group(1).length() > 0) {
sb.append(matcher.group(1));
}
if (matcher.group(2).length() > 0) {
sb.append(":");
sb.append(matcher.group(2));
}
String role = sb.toString().replace("+", " ");
roles.add(URLDecoder.decode(role));
}
}
}
return roles;
}
private static void entityRoles(JsonArray entitlements, Set<GrantedAuthority> authorities) {
if (entitlements != null) {
for (JsonElement obj : entitlements) {
Matcher matcher = Pattern.compile(ENTITLEMENT_REGEX).matcher(obj.getAsString());
if (matcher.find()) {
StringBuilder sb = new StringBuilder();
if (matcher.group(1) != null && matcher.group(1).length() > 0) {
sb.append(matcher.group(1).replace("+-+", "_").replaceAll("[+.]", "_").toUpperCase());
}
if (matcher.group(2).length() > 0) {
sb.append("_");
if (matcher.group(2).equals("admins")) {
sb.append("MANAGER");
} else {
sb.append(matcher.group(2).toUpperCase());
}
}
authorities.add(new SimpleGrantedAuthority(sb.toString()));
}
authorities.add(new SimpleGrantedAuthority(sb.toString()));
}
}
}
// TODO: remove when ROLE_ADMIN and ROLE_PROVIDE_ADMIN are removed from project
private static void provideRoles(JsonArray entitlements, Set<SimpleGrantedAuthority> authorities) {
private static void provideRoles(JsonArray entitlements, Set<GrantedAuthority> authorities) {
Map<String, String> userRoles = new HashMap() {{
put("urn:geant:openaire.eu:group:Super+Administrator:role=member#aai.openaire.eu", "ROLE_ADMIN");
put("urn:geant:openaire.eu:group:Content+Provider+Dashboard+Administrator:role=member#aai.openaire.eu", "ROLE_PROVIDE_ADMIN");

View File

@ -26,61 +26,69 @@ public class AuthoritiesUpdater extends HttpSessionSecurityContextRepository {
@Autowired
FindByIndexNameSessionRepository sessions;
public void update(String id, Collection<? extends GrantedAuthority> authorities) {
public void update(String email, Collection<? extends GrantedAuthority> authorities) {
if (sessions != null) {
Map<String, ExpiringSession> map = sessions.
findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, id);
logger.debug(map.values().toArray().length);
for (ExpiringSession session : map.values()) {
logger.debug(session.getId());
if (!session.isExpired()) {
SecurityContext securityContext = session.getAttribute(SPRING_SECURITY_CONTEXT_KEY);
Authentication authentication = securityContext.getAuthentication();
if (authentication instanceof OIDCAuthenticationToken) {
OIDCAuthenticationToken authOIDC = (OIDCAuthenticationToken) authentication;
logger.debug(authorities);
securityContext.setAuthentication(new OIDCAuthenticationToken(authOIDC.getSub(), authOIDC.getIssuer(),
authOIDC.getUserInfo(), authorities, authOIDC.getIdToken(),
authOIDC.getAccessTokenValue(), authOIDC.getRefreshTokenValue()));
logger.debug("Update authorities");
session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, securityContext);
sessions.save(session);
findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, email);
if (map != null) {
logger.debug(map.values().toArray().length);
for (ExpiringSession session : map.values()) {
logger.debug(session.getId());
if (!session.isExpired()) {
SecurityContext securityContext = session.getAttribute(SPRING_SECURITY_CONTEXT_KEY);
Authentication authentication = securityContext.getAuthentication();
if (authentication instanceof OIDCAuthenticationToken) {
OIDCAuthenticationToken authOIDC = (OIDCAuthenticationToken) authentication;
logger.debug(authorities);
securityContext.setAuthentication(new OIDCAuthenticationToken(authOIDC.getSub(), authOIDC.getIssuer(),
authOIDC.getUserInfo(), authorities, authOIDC.getIdToken(),
authOIDC.getAccessTokenValue(), authOIDC.getRefreshTokenValue()));
logger.debug("Update authorities");
session.setAttribute(SPRING_SECURITY_CONTEXT_KEY, securityContext);
sessions.save(session);
}
}
}
}
}
}
public void update(String id, Update update) {
public void update(String email, Update update) {
Collection<? extends GrantedAuthority> authorities = update.authorities(SecurityContextHolder.getContext().getAuthentication().getAuthorities());
this.update(id, authorities);
this.update(email, authorities);
}
public void addRole(String email, GrantedAuthority role) {
this.update(email, old -> {
HashSet<GrantedAuthority> authorities = new HashSet<>(old);
authorities.add(role);
return 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<GrantedAuthority> authorities = new HashSet<>(old);
authorities.add(role);
return authorities;
});
this.addRole(oidcAuth.getUserInfo().getEmail(), role);
} else {
throw new UnauthorizedClientException("User auth is not instance of OIDCAuthenticationToken");
}
}
public void removeRole(String email, GrantedAuthority role) {
this.update(email, old -> {
HashSet<GrantedAuthority> authorities = new HashSet<>(old);
authorities.remove(role);
return authorities;
});
}
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<GrantedAuthority> authorities = new HashSet<>(old);
authorities.remove(role);
return authorities;
});
} else {
throw new UnauthorizedClientException("User auth is not instance of OIDCAuthenticationToken");
this.removeRole(oidcAuth.getUserInfo().getEmail(), role);
}
}

View File

@ -1,12 +1,51 @@
package eu.dnetlib.repo.manager.service.security;
import eu.dnetlib.repo.manager.domain.dto.User;
import eu.dnetlib.repo.manager.exception.ResourceNotFoundException;
import java.util.List;
public interface AuthorizationService {
/**
*
* @param type
* @param id
* @return
*/
String member(String type, String id);
String member(String type, String id); //TODO: use or delete
/**
* @param id Resource Id to check.
* @return Checks if a user is a member of a resource.
*/
boolean isMemberOf(String id);
/**
* Returns a list of admins of the resource.
*
* @param repoId
* @return
*/
List<User> getAdminsOfRepo(String repoId);
/**
* Add a user as admin to a resource.
*
* @param id Resource id
* @param email User email
* @return
* @throws ResourceNotFoundException
*/
boolean addAdmin(String id, String email) throws ResourceNotFoundException;
/**
* Remove user from resource admins.
*
* @param id Resource id
* @param email User email
* @return
* @throws ResourceNotFoundException
*/
boolean removeAdmin(String id, String email) throws ResourceNotFoundException;
}

View File

@ -1,14 +1,36 @@
package eu.dnetlib.repo.manager.service.security;
import org.springframework.stereotype.Component;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
@Component("AuthorizationService")
import java.util.ArrayList;
import java.util.List;
@Service("authorizationService")
public class AuthorizationServiceImpl implements AuthorizationService {
public final String ROLE_ADMIN = "ROLE_ADMIN";
public final String ROLE_PROVIDE_ADMIN = "ROLE_PROVIDE_ADMIN";
public final String ROLE_USER = "ROLE_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";
@ -19,8 +41,80 @@ public class AuthorizationServiceImpl implements AuthorizationService {
/**
* 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()
.parallelStream().anyMatch(authority -> authority.toString().equals(repoRole));
}
@Override
public List<User> getAdminsOfRepo(String repoId) {
List<String> userList = new ArrayList<>();
// find couId by role name
String role = roleMappingService.getRoleIdByRepoId(repoId);
Integer couId = aaiRegistryService.getCouId(role);
if (couId != null) {
JsonArray users = aaiRegistryService.getUsersByCouId(couId);
for (JsonElement jsonElement : users) {
userList.add(jsonElement.toString());
}
}
return aaiRegistryService.getUsers(couId);
}
@Override
public boolean addAdmin(String id, String email) throws ResourceNotFoundException {
Integer coPersonId = aaiRegistryService.getCoPersonIdByEmail(email);
if (coPersonId != null) {
String role = roleMappingService.getRoleIdByRepoId(id);
Integer couId = aaiRegistryService.getCouId(role);
if (couId != null) {
Integer roleId = aaiRegistryService.getRoleId(coPersonId, couId);
aaiRegistryService.assignMemberRole(coPersonId, couId, roleId);
// Add role to user current authorities
authoritiesUpdater.addRole(email, roleMappingService.convertRepoIdToAuthority(id));
return true;
} else {
throw new ResourceNotFoundException("Cannot find CouId for role: " + role);
}
} else {
throw new ResourceNotFoundException("Cannot find coPersonId for user with email: " + email);
}
}
@Override
public boolean removeAdmin(String id, String email) throws ResourceNotFoundException {
Integer coPersonId = aaiRegistryService.getCoPersonIdByEmail(email);
if (coPersonId != null) {
String role = roleMappingService.getRoleIdByRepoId(id);
Integer couId = aaiRegistryService.getCouId(role);
Integer roleId = null;
if (couId != null) {
roleId = aaiRegistryService.getRoleId(coPersonId, couId);
}
if (couId != null && roleId != null) {
aaiRegistryService.removeMemberRole(coPersonId, couId, roleId);
// Remove role from user current authorities
authoritiesUpdater.removeRole(email, roleMappingService.convertRepoIdToAuthority(id));
return true;
} else {
throw new ResourceNotFoundException("Cannot find CouId for role: " + role);
}
} else {
throw new ResourceNotFoundException("Cannot find coPersonId for user with email: " + email);
}
}
}

View File

@ -1,8 +1,9 @@
package eu.dnetlib.repo.manager.service.security;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
public interface AaiUserRoleService {
public interface RoleMappingService {
/**
* @param fullName
@ -11,12 +12,30 @@ public interface AaiUserRoleService {
*/
String getRepoNameWithoutType(String fullName, String prefix);
/**
* @param roleId Role Id
* @return Converts {@param roleId} to a repo Id.
*/
String getRepoIdByRoleId(String roleId);
/**
* @param repoId Repository Id
* @return Converts {@param repoId} to a role Id.
*/
String getRoleIdByRepoId(String repoId);
/**
* @param authorityId Authority Id
* @return Converts {@param authorityId} to repo Id.
*/
String convertAuthorityIdToRepoId(String authorityId);
/**
* @param authority Granted authority
* @return Converts {@param authority} to repo Id.
*/
String convertAuthorityToRepoId(GrantedAuthority authority);
/**
* @param repoId Repository Id
* @return
@ -37,10 +56,4 @@ public interface AaiUserRoleService {
*/
SimpleGrantedAuthority convertRepoIdToAuthority(String repoId);
/**
* @param repoId Repository Id to check.
* @return Checks if a user is a member of a repository or not.
*/
boolean isMemberOf(String repoId);
}

View File

@ -36,11 +36,7 @@ public class HttpUtils {
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> request = new HttpEntity<>(body.toString(), headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(issuer + path, HttpMethod.POST, request, String.class);
if (responseEntity.getBody() != null) {
return new JsonParser().parse(responseEntity.getBody());
} else {
return null;
}
return getResponseEntityAsJsonElement(responseEntity);
}
public JsonElement put(String path, JsonObject body) {
@ -49,11 +45,7 @@ public class HttpUtils {
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> request = new HttpEntity<>(body.toString(), headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(issuer + path, HttpMethod.PUT, request, String.class);
if (responseEntity.getBody() != null) {
return new JsonParser().parse(responseEntity.getBody());
} else {
return null;
}
return getResponseEntityAsJsonElement(responseEntity);
}
public JsonElement get(String path, Map<String, String> params) {
@ -61,11 +53,7 @@ public class HttpUtils {
String url = issuer + path + ((params != null) ? createParams(params) : null);
ResponseEntity<String> responseEntity = restTemplate.exchange
(url, HttpMethod.GET, new HttpEntity<>(createHeaders(user, password)), String.class);
if (responseEntity.getBody() != null) {
return new JsonParser().parse(responseEntity.getBody());
} else {
return null;
}
return getResponseEntityAsJsonElement(responseEntity);
}
public JsonElement delete(String path) {
@ -73,11 +61,7 @@ public class HttpUtils {
String url = issuer + path;
ResponseEntity<String> responseEntity = restTemplate.exchange
(url, HttpMethod.DELETE, new HttpEntity<>(createHeaders(user, password)), String.class);
if (responseEntity.getBody() != null) {
return new JsonParser().parse(responseEntity.getBody());
} else {
return null;
}
return getResponseEntityAsJsonElement(responseEntity);
}
@ -103,4 +87,16 @@ public class HttpUtils {
set("Authorization", authHeader);
}};
}
private JsonElement getResponseEntityAsJsonElement(ResponseEntity<String> responseEntity) {
if (responseEntity != null && responseEntity.getBody() != null) {
logger.info(responseEntity.getBody());
try {
return new JsonParser().parse(responseEntity.getBody());
} catch (Exception e) {
logger.warn("Could not parse response body", e);
}
}
return null;
}
}