1. optimization in retrieval time of repositories/snippets of authenticated user

2. Marked with FIXME methods that need attention
This commit is contained in:
Konstantinos Spyrou 2021-07-13 15:22:08 +00:00
parent 90827f99d3
commit aaecacd58b
9 changed files with 198 additions and 93 deletions

View File

@ -66,8 +66,8 @@ public class RepositoryController {
@PreAuthorize("hasAuthority('REGISTERED_USER')")
public List<RepositorySnippet> getRepositoriesSnippetOfUser(
@PathVariable("page") String page,
@PathVariable("size") String size) throws JSONException, IOException {
return repositoryService.getRepositoriesSnippetOfUser(((OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication()).getUserInfo().getEmail(), page, size);
@PathVariable("size") String size) throws Exception {
return repositoryService.getRepositoriesSnippetOfUser(page, size);
}
@RequestMapping(value = "/user/repositories/{page}/{size}", method = RequestMethod.GET,
@ -77,7 +77,7 @@ public class RepositoryController {
public List<Repository> getRepositoriesOfUser(
@PathVariable("page") String page,
@PathVariable("size") String size) throws JSONException, IOException {
return repositoryService.getRepositoriesOfUser(((OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication()).getUserInfo().getEmail(), page, size);
return repositoryService.getRepositoriesOfUser(page, size);
}
@RequestMapping(value = "/searchRegisteredRepositories/{page}/{size}", method = RequestMethod.GET,

View File

@ -1,29 +1,22 @@
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.service.security.AuthorizationService;
import eu.dnetlib.repo.manager.service.security.RoleMappingService;
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")
@ -33,14 +26,17 @@ public class UserRoleController {
private final AaiRegistryService aaiRegistryService;
private final AuthoritiesUpdater authoritiesUpdater;
private final RoleMappingService roleMappingService;
private final AuthorizationService authorizationService;
@Autowired
UserRoleController(AaiRegistryService aaiRegistryService,
AuthoritiesUpdater authoritiesUpdater,
RoleMappingService roleMappingService) {
RoleMappingService roleMappingService,
AuthorizationService authorizationService) {
this.aaiRegistryService = aaiRegistryService;
this.authoritiesUpdater = authoritiesUpdater;
this.roleMappingService = roleMappingService;
this.authorizationService = authorizationService;
}
/**
@ -101,30 +97,14 @@ public class UserRoleController {
@RequestMapping(method = RequestMethod.GET, path = "/users/{email}/roles")
@PreAuthorize("hasAnyAuthority('SUPER_ADMINISTRATOR', 'CONTENT_PROVIDER_DASHBOARD_ADMINISTRATOR') or hasAuthority('REGISTERED_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<>();
for (JsonElement element : aaiRegistryService.getRolesWithStatus(coPersonId, AaiRegistryService.RoleStatus.ACTIVE)) {
list.add(element.getAsJsonObject().get("CouId").getAsInt());
}
return ResponseEntity.ok(aaiRegistryService.getCouNames(list).values());
return ResponseEntity.ok(authorizationService.getUserRoles(email));
}
@RequestMapping(method = RequestMethod.GET, path = "/user/roles/my")
@PreAuthorize("hasAuthority('REGISTERED_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);
return ResponseEntity.ok(authorizationService.getUserRoles());
}
}

View File

@ -92,7 +92,7 @@ public class BrokerServiceImpl implements BrokerService {
// if (Boolean.parseBoolean(includeByOthers)) {
// ret.setDatasourcesOfOthers(getDatasourcesOfUserType(getRepositoriesOfUser(user)));
// }
} catch (BrokerException | IOException e) {
} catch (Exception e) {
LOGGER.debug("Exception on getDatasourcesOfUser" , e);
emailUtils.reportException(e);
}

View File

@ -16,13 +16,25 @@ public interface RepositoryService {
Country[] getCountries() ;
List<Repository> getRepositories(List<String> ids) throws JSONException;
List<Repository> getRepositories(List<String> ids, int page, int size) throws JSONException;
List<RepositorySnippet> getRepositoriesSnippets(List<String> ids) throws Exception;
List<RepositorySnippet> getRepositoriesSnippets(List<String> ids, int page, int size) throws Exception;
List<RepositorySnippet> getRepositoriesByCountry(String country, String mode, Boolean managed) throws JSONException, IOException;
List<Repository> getRepositoriesOfUser(String page, String size) throws JSONException, IOException;
List<Repository> getRepositoriesOfUser(String userEmail,
String page,
String size) throws JSONException, IOException;
List<RepositorySnippet> getRepositoriesSnippetOfUser(String userEmail, String page, String size) throws IOException, JSONException;
List<RepositorySnippet> getRepositoriesSnippetOfUser(String page, String size) throws Exception;
List<RepositorySnippet> getRepositoriesSnippetOfUser(String userEmail, String page, String size) throws Exception;
RepositorySnippet getRepositorySnippetById(String id) throws JSONException, ResourceNotFoundException;
Repository getRepositoryById(String id) throws JSONException, ResourceNotFoundException;

View File

@ -13,8 +13,9 @@ 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.RoleMappingService;
import eu.dnetlib.repo.manager.service.security.AuthoritiesUpdater;
import eu.dnetlib.repo.manager.service.security.AuthorizationService;
import eu.dnetlib.repo.manager.service.security.RoleMappingService;
import eu.dnetlib.repo.manager.utils.Converter;
import gr.uoa.di.driver.enabling.vocabulary.VocabularyLoader;
import org.apache.commons.codec.digest.DigestUtils;
@ -50,6 +51,7 @@ public class RepositoryServiceImpl implements RepositoryService {
private static final Logger LOGGER = Logger.getLogger(RepositoryServiceImpl.class);
private final AuthorizationService authorizationService;
private final RoleMappingService roleMappingService;
private final AaiRegistryService registryCalls;
private final AuthoritiesUpdater authoritiesUpdater;
@ -84,7 +86,8 @@ public class RepositoryServiceImpl implements RepositoryService {
private HttpHeaders httpHeaders;
@Autowired
public RepositoryServiceImpl(RoleMappingService roleMappingService,
public RepositoryServiceImpl(AuthorizationService authorizationService,
RoleMappingService roleMappingService,
AaiRegistryService registryCalls,
AuthoritiesUpdater authoritiesUpdater,
VocabularyLoader vocabularyLoader,
@ -92,6 +95,7 @@ public class RepositoryServiceImpl implements RepositoryService {
@Lazy EmailUtils emailUtils,
@Lazy ValidatorService validatorService,
@Lazy PiWikService piWikService) {
this.authorizationService = authorizationService;
this.roleMappingService = roleMappingService;
this.registryCalls = registryCalls;
this.authoritiesUpdater = authoritiesUpdater;
@ -102,7 +106,7 @@ public class RepositoryServiceImpl implements RepositoryService {
this.restTemplate = restTemplate;
}
private String sendEmail() {
private String getAuthenticatedUserEmail() {
OIDCAuthenticationToken authenticationToken = (OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
return authenticationToken.getUserInfo().getEmail();
}
@ -153,6 +157,83 @@ public class RepositoryServiceImpl implements RepositoryService {
.build().encode();
return restTemplate.getForObject(uriComponents.toUri(), Country[].class);
}
// FIXME: with the new roles of the users the "requestFilter.setRegisteredby(userEmail)" can no longer be used
// and the "requestFilter.setId(repoId)" should return only one result at a time, thus,
// another way for paging must be implemented.
@Override
public List<Repository> getRepositories(List<String> ids) throws JSONException {
return getRepositories(ids, 0, 10);
}
// FIXME: with the new roles of the users the "requestFilter.setRegisteredby(userEmail)" can no longer be used
// and the "requestFilter.setId(repoId)" should return only one result at a time, thus,
// another way for paging must be implemented.
@Override
public List<Repository> getRepositories(List<String> ids, int page, int size) throws JSONException {
List<Repository> repos = new ArrayList<>();
LOGGER.debug("Retreiving repositories with ids : " + String.join(", ", ids));
UriComponents uriComponents = searchDatasource(Integer.toString(Math.abs(page)), Integer.toString(Math.abs(size)));
RequestFilter requestFilter = new RequestFilter();
try {
for (String repoId : ids) {
requestFilter.setId(repoId);
String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
repos.addAll(Converter.jsonToRepositoryList(new JSONObject(rs)));
}
} catch (JSONException e) {
LOGGER.debug("Exception on getRepositoriesOfUser", e);
emailUtils.reportException(e);
throw e;
}
for (Repository r : repos)
r.setPiwikInfo(piWikService.getPiwikSiteForRepo(r.getId()));
return repos;
}
// FIXME: with the new roles of the users the "requestFilter.setRegisteredby(userEmail)" can no longer be used
// and the "requestFilter.setId(repoId)" should return only one result at a time, thus,
// another way for paging must be implemented.
@Override
public List<RepositorySnippet> getRepositoriesSnippets(List<String> ids) throws Exception {
return getRepositoriesSnippets(ids, 0, 10);
}
// FIXME: with the new roles of the users the "requestFilter.setRegisteredby(userEmail)" can no longer be used
// and the "requestFilter.setId(repoId)" should return only one result at a time, thus,
// another way for paging must be implemented.
@Override
public List<RepositorySnippet> getRepositoriesSnippets(List<String> ids, int page, int size) throws Exception {
List<RepositorySnippet> resultSet = new ArrayList<>();
ObjectMapper mapper = new ObjectMapper();
// here page should be 0
UriComponents uriComponents = searchSnipperDatasource(Integer.toString(Math.abs(page)), Integer.toString(Math.abs(size)));
RequestFilter requestFilter = new RequestFilter();
try {
for (String repoId : ids) {
requestFilter.setId(repoId);
String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
resultSet.addAll(mapper.readValue(String.valueOf(jsonArray),
mapper.getTypeFactory().constructCollectionType(List.class, RepositorySnippet.class)));
}
} catch (Exception e) {
LOGGER.debug("Exception on getRepositoriesSnippetOfUser", e);
throw e;
}
LOGGER.debug("resultSet:" + resultSet);
resultSet.parallelStream().forEach(repositorySnippet -> {
repositorySnippet.setPiwikInfo(piWikService.getPiwikSiteForRepo(repositorySnippet.getId()));
});
return resultSet;
}
@Override
@ -255,68 +336,30 @@ public class RepositoryServiceImpl implements RepositoryService {
}
@Override
public List<Repository> getRepositoriesOfUser(String userEmail,
String page,
String size) throws JSONException {
LOGGER.debug("Retreiving repositories of user : " + userEmail);
UriComponents uriComponents = searchDatasource(page, size);
RequestFilter requestFilter = new RequestFilter();
// requestFilter.setRegisteredby(userEmail);
List<String> repoIds = getRepoIdsFromUserRoles(userEmail);
List<Repository> repos = new ArrayList<>();
try {
for (String repoId : repoIds) {
requestFilter.setId(repoId);
String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
repos.addAll(Converter.jsonToRepositoryList(new JSONObject(rs)));
}
} catch (Exception e) {
LOGGER.debug("Exception on getRepositoriesOfUser", e);
emailUtils.reportException(e);
throw e;
}
for (Repository r : repos)
r.setPiwikInfo(piWikService.getPiwikSiteForRepo(r.getId()));
return repos;
public List<Repository> getRepositoriesOfUser(String page, String size) throws JSONException {
String userEmail = ((OIDCAuthenticationToken) SecurityContextHolder.getContext().getAuthentication()).getUserInfo().getEmail();
LOGGER.debug("Retreiving repositories of authenticated user : " + userEmail);
Collection<String> repoIds = roleMappingService.getRepoIdsByRoleIds(authorizationService.getUserRoles());
return getRepositories(new ArrayList<>(repoIds));
}
@Override
public List<RepositorySnippet> getRepositoriesSnippetOfUser(String userEmail, String page, String size) throws IOException, JSONException {
public List<Repository> getRepositoriesOfUser(String userEmail, String page, String size) throws JSONException {
LOGGER.debug("Retreiving repositories of authenticated user : " + userEmail);
Collection<String> repoIds = roleMappingService.getRepoIdsByRoleIds(authorizationService.getUserRoles(userEmail));
return getRepositories(new ArrayList<>(repoIds));
}
// TODO: Step 3 - For each repo from the previous step call findByRepositoryId piwik_site to get the full info of repo
List<String> repoIds = getRepoIdsFromUserRoles(userEmail);
@Override
public List<RepositorySnippet> getRepositoriesSnippetOfUser(String page, String size) throws Exception {
Collection<String> repoIds = roleMappingService.getRepoIdsByRoleIds(authorizationService.getUserRoles());
return getRepositoriesSnippets(new ArrayList<>(repoIds));
}
List<RepositorySnippet> resultSet = new ArrayList<>();
ObjectMapper mapper = new ObjectMapper();
// here page should be 0
UriComponents uriComponents = searchSnipperDatasource(page, size);
RequestFilter requestFilter = new RequestFilter();
try {
for (String repoId : repoIds) {
requestFilter.setId(repoId);
String rs = restTemplate.postForObject(uriComponents.toUri(), requestFilter, String.class);
JSONArray jsonArray = (JSONArray) new JSONObject(rs).get("datasourceInfo");
resultSet.addAll(mapper.readValue(String.valueOf(jsonArray),
mapper.getTypeFactory().constructCollectionType(List.class, RepositorySnippet.class)));
}
} catch (Exception e) {
LOGGER.debug("Exception on getRepositoriesSnippetOfUser", e);
throw e;
}
LOGGER.debug("resultSet:" + resultSet);
resultSet.parallelStream().forEach(repositorySnippet -> {
repositorySnippet.setPiwikInfo(piWikService.getPiwikSiteForRepo(repositorySnippet.getId()));
});
return resultSet;
@Override
public List<RepositorySnippet> getRepositoriesSnippetOfUser(String userEmail, String page, String size) throws Exception {
Collection<String> repoIds = roleMappingService.getRepoIdsByRoleIds(authorizationService.getUserRoles(userEmail));
return getRepositoriesSnippets(new ArrayList<>(repoIds));
}
@Override

View File

@ -7,6 +7,8 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.stream.Collectors;
@Service("roleMappingService")
public class AaiRoleMappingService implements RoleMappingService {
@ -34,6 +36,14 @@ public class AaiRoleMappingService implements RoleMappingService {
return roleId.replaceFirst(".*datasource\\.", "").replace("$", ":");
}
@Override
public Collection<String> getRepoIdsByRoleIds(Collection<String> roleIds) {
return roleIds
.stream()
.map(this::getRepoIdByRoleId)
.collect(Collectors.toList());
}
@Override
public String getRoleIdByRepoId(String repoId) {
String roleId = "";
@ -47,6 +57,14 @@ public class AaiRoleMappingService implements RoleMappingService {
}
@Override
public Collection<String> getRoleIdsByRepoIds(Collection<String> repoIds) {
return repoIds
.stream()
.map(this::getRoleIdByRepoId)
.collect(Collectors.toList());
}
@Override
public String convertAuthorityIdToRepoId(String authorityId) {
String repo = "";

View File

@ -3,6 +3,7 @@ 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.Collection;
import java.util.List;
public interface AuthorizationService {
@ -48,4 +49,11 @@ public interface AuthorizationService {
* @throws ResourceNotFoundException
*/
boolean removeAdmin(String id, String email) throws ResourceNotFoundException;
Collection<String> getUserRoles();
Collection<String> getUserRoles(String email);
}

View File

@ -5,11 +5,14 @@ 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.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.mitre.openid.connect.model.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Service("authorizationService")
@ -117,4 +120,30 @@ public class AuthorizationServiceImpl implements AuthorizationService {
}
}
@Override
public Collection<String> getUserRoles() {
List<String> roles;
JsonArray entitlements;
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 {
entitlements = new JsonArray();
}
roles = AuthoritiesMapper.entitlementRoles(entitlements);
return roles;
}
@Override
public Collection<String> getUserRoles(String email) {
int coPersonId = aaiRegistryService.getCoPersonIdByEmail(email);
List<Integer> list = new ArrayList<>();
for (JsonElement element : aaiRegistryService.getRolesWithStatus(coPersonId, AaiRegistryService.RoleStatus.ACTIVE)) {
list.add(element.getAsJsonObject().get("CouId").getAsInt());
}
return aaiRegistryService.getCouNames(list).values();
}
}

View File

@ -3,6 +3,8 @@ package eu.dnetlib.repo.manager.service.security;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.Collection;
public interface RoleMappingService {
/**
@ -18,12 +20,25 @@ public interface RoleMappingService {
*/
String getRepoIdByRoleId(String roleId);
/**
*
* @param roleIds Collection of roles
* @return Converts {@param roleIds} to a repo Ids.
*/
Collection<String> getRepoIdsByRoleIds(Collection<String> roleIds);
/**
* @param repoId Repository Id
* @return Converts {@param repoId} to a role Id.
*/
String getRoleIdByRepoId(String repoId);
/**
* @param repoIds Collection of Repository Ids
* @return Converts {@param repoIds} to role Ids.
*/
Collection<String> getRoleIdsByRepoIds(Collection<String> repoIds);
/**
* @param authorityId Authority Id
* @return Converts {@param authorityId} to repo Id.