Skip to content

Commit

Permalink
story 9854 partitioning access to ingest
Browse files Browse the repository at this point in the history
  • Loading branch information
Souhaib committed Feb 9, 2023
1 parent a18cc10 commit 0a54d51
Show file tree
Hide file tree
Showing 9 changed files with 428 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,16 @@

import com.fasterxml.jackson.databind.JsonNode;
import fr.gouv.vitamui.commons.api.ParameterChecker;
import fr.gouv.vitamui.commons.api.domain.AggregationRequestOperator;
import fr.gouv.vitamui.commons.api.domain.Criterion;
import fr.gouv.vitamui.commons.api.domain.CriterionOperator;
import fr.gouv.vitamui.commons.api.domain.DirectionDto;
import fr.gouv.vitamui.commons.api.domain.IdDto;
import fr.gouv.vitamui.commons.api.domain.PaginatedValuesDto;
import fr.gouv.vitamui.commons.api.domain.ProfileDto;
import fr.gouv.vitamui.commons.api.domain.QueryDto;
import fr.gouv.vitamui.commons.api.domain.QueryOperator;
import fr.gouv.vitamui.commons.api.domain.RequestParamDto;
import fr.gouv.vitamui.commons.api.domain.RequestParamGroupDto;
import fr.gouv.vitamui.commons.api.domain.ResultsDto;
import fr.gouv.vitamui.commons.api.domain.ServicesData;
import fr.gouv.vitamui.commons.api.exception.ForbiddenException;
import fr.gouv.vitamui.commons.api.exception.InvalidFormatException;
import fr.gouv.vitamui.commons.api.exception.NotImplementedException;
Expand All @@ -75,13 +72,13 @@
/**
* Class for ExternalVitamUICrudService
*
*
* @param <E> External DTO type
* @param <I> Internal DTO Type
*/
@Getter
@Setter
public abstract class AbstractResourceClientService<E extends IdDto, I extends IdDto> extends AbstractInternalClientService {
public abstract class AbstractResourceClientService<E extends IdDto, I extends IdDto>
extends AbstractInternalClientService {

protected static final String EXTERNAL_PARAM_ID_KEY = "externalParamId";

Expand Down Expand Up @@ -124,37 +121,38 @@ protected E getOne(final String id, final Optional<String> embedded) {
}

protected PaginatedValuesDto<E> getAllPaginated(final Integer page, final Integer size,
final Optional<String> criteria, final Optional<String> orderBy, final Optional<DirectionDto> direction) {
final Optional<String> criteria, final Optional<String> orderBy, final Optional<DirectionDto> direction) {
ParameterChecker.checkPagination(size, page);
final PaginatedValuesDto<I> result = getClient().getAllPaginated(getInternalHttpContext(), page, size,
checkAuthorization(criteria), orderBy, direction);
checkAuthorization(criteria), orderBy, direction);
return new PaginatedValuesDto<>(result.getValues().stream().map(element -> converterToExternalDto(element))
.collect(Collectors.toList()), result.getPageNum(), result.getPageSize(), result.isHasMore());
.collect(Collectors.toList()), result.getPageNum(), result.getPageSize(), result.isHasMore());
}

protected PaginatedValuesDto<E> getAllPaginated(final Integer page, final Integer size,
final Optional<String> criteria, final Optional<String> orderBy, final Optional<DirectionDto> direction,
final Optional<String> embedded) {
final Optional<String> criteria, final Optional<String> orderBy, final Optional<DirectionDto> direction,
final Optional<String> embedded) {
ParameterChecker.checkPagination(size, page);
final PaginatedValuesDto<I> result = getClient().getAllPaginated(getInternalHttpContext(), page, size,
checkAuthorization(criteria), orderBy, direction, embedded);
checkAuthorization(criteria), orderBy, direction, embedded);
return new PaginatedValuesDto<>(result.getValues().stream().map(element -> converterToExternalDto(element))
.collect(Collectors.toList()), result.getPageNum(), result.getPageSize(), result.isHasMore());
.collect(Collectors.toList()), result.getPageNum(), result.getPageSize(), result.isHasMore());
}

protected ResultsDto<E> getAllRequest(final RequestParamDto requestParamDto) {
ParameterChecker.checkPagination(requestParamDto.getSize(), requestParamDto.getPage());
requestParamDto.setCriteria(checkRequestAuthorization(requestParamDto));
final ResultsDto<I> result = getClient().getAllRequest(getInternalHttpContext(), requestParamDto);
return new ResultsDto<>(result.getValues().stream().map(element -> converterToExternalDto(element))
.collect(Collectors.toList()), result);
.collect(Collectors.toList()), result);
}

/**
* Check the criteria. <br>
*
* Convert Json to CriteriaWrapper <br>
* Check if the criteria keys are allowed
*
* @param criteria
* @return
* @throws InvalidFormatException
Expand All @@ -170,15 +168,17 @@ protected Optional<String> checkAuthorization(final Optional<String> criteria) t
* Check if the criteria keys are allowed
* Check if the groups fields keys are allowed
* Check if the aggregation operator is allowed
*
* @param requestParamDto
* @return
* @throws InvalidFormatException
*/
protected Optional<String> checkRequestAuthorization(RequestParamDto requestParamDto) throws InvalidFormatException {
protected Optional<String> checkRequestAuthorization(RequestParamDto requestParamDto)
throws InvalidFormatException {
if (requestParamDto.getGroups().isPresent()) {
RequestParamGroupDto requestParamGroupDto = requestParamDto.getGroups().get();
for(String field: requestParamGroupDto.getFields()){
if(!getAllowedAggregationKeys().contains(field))
for (String field : requestParamGroupDto.getFields()) {
if (!getAllowedAggregationKeys().contains(field))
throw new ForbiddenException(String.format("Not allowed to get aggregation %s values", field));
}
}
Expand All @@ -190,12 +190,13 @@ protected Optional<String> checkRequestAuthorization(RequestParamDto requestPara
*
* Convert Json to CriteriaWrapper <br>
* Check if the criteria keys are allowed
*
* @param criteria
* @return
* @throws InvalidFormatException
*/
protected Optional<QueryDto> checkCriteriaAuthorization(final Optional<QueryDto> criteria)
throws InvalidFormatException {
throws InvalidFormatException {
return Optional.of(addAccessRestriction(criteria.orElse(new QueryDto())));
}

Expand All @@ -211,6 +212,7 @@ protected QueryDto addAccessRestriction(final QueryDto query) {

/**
* Create an andQuery and add security filter
*
* @param query
* @return
*/
Expand All @@ -225,6 +227,7 @@ protected QueryDto addAccessRestrictionV2(final QueryDto query) {

/**
* Check if the query and subqueries only contains criteria on allowed keys.
*
* @param query
* @throws ForbiddenException If a key is not allowed
*/
Expand All @@ -243,13 +246,14 @@ protected QueryDto addAccessRestrictionV1(final QueryDto criteria) {
getRestrictedKeys().forEach(key -> addAccessRestrictionByKey(key, criteria));
if (!(criteria.getQueryOperator() == null || QueryOperator.AND.equals(criteria.getQueryOperator()))) {
throw new UnsupportedOperationException("Unsupported operator " + criteria.getQueryOperator()
+ ". This API only supports the queryOperator \"AND\" on the root query.");
+ ". This API only supports the queryOperator \"AND\" on the root query.");
}
return criteria;
}

/**
* Override this method for use the desired version
*
* @return
*/
protected String getVersionApiCrtieria() {
Expand All @@ -258,13 +262,13 @@ protected String getVersionApiCrtieria() {

protected void addAccessRestrictionByKey(final String key, final QueryDto criteria) {
switch (key) {
case CUSTOMER_ID_KEY :
case CUSTOMER_ID_KEY:
addCustomerRestriction(criteria);
break;
case TENANT_IDENTIFIER_KEY :
case TENANT_IDENTIFIER_KEY:
addTenantIdentifierRestriction(criteria);
break;
default :
default:
addRestriction(key, criteria);
break;
}
Expand All @@ -273,6 +277,7 @@ protected void addAccessRestrictionByKey(final String key, final QueryDto criter
/**
* Method allowing to defined restrictions for criterion's field.
* This method must be implemented by any service using restrictions.
*
* @param key Key of the restriction.
* @param criteria Criteria linked to the search.
*/
Expand All @@ -292,10 +297,10 @@ protected void addTenantIdentifierRestriction(final QueryDto criteria) {

protected void checkTenantIdentifierCriteria(final Criterion tenantIdentifierCriteria) {
if (!CastUtils.toInteger(tenantIdentifierCriteria.getValue())
.equals(externalSecurityService.getTenantIdentifier())
|| !tenantIdentifierCriteria.getOperator().equals(CriterionOperator.EQUALS)) {
.equals(externalSecurityService.getTenantIdentifier())
|| !tenantIdentifierCriteria.getOperator().equals(CriterionOperator.EQUALS)) {
throw new ForbiddenException(
"tenantIdentifier's criteria is not equal to the tenantIdentifier from context");
"tenantIdentifier's criteria is not equal to the tenantIdentifier from context");
}
}

Expand All @@ -310,15 +315,14 @@ protected void addCustomerRestriction(final QueryDto criteria) {

protected void checkCustomerCriteria(final Criterion customerCriteria) {
if (!StringUtils.equals(CastUtils.toString(customerCriteria.getValue()),
externalSecurityService.getCustomerId())
|| !customerCriteria.getOperator().equals(CriterionOperator.EQUALS)) {
externalSecurityService.getCustomerId())
|| !customerCriteria.getOperator().equals(CriterionOperator.EQUALS)) {
throw new ForbiddenException("customerId's criteria is not equal to the customerId from context");
}
}

/**
* Override for add restriction, like customerId, tenantIdentifier etc.
*
*/
protected Collection<String> getRestrictedKeys() {
return Arrays.asList(CUSTOMER_ID_KEY);
Expand All @@ -328,6 +332,7 @@ protected Collection<String> getRestrictedKeys() {
* The Collection contains keys allowed
* By default the collection is null and all keys are authorized
* Function as a whitelist
*
* @return
*/
protected Collection<String> getAllowedKeys() {
Expand All @@ -338,6 +343,7 @@ protected Collection<String> getAllowedKeys() {
* The Collection contains keys allowed for aggregation.
* By default the collection is null and all keys are authorized
* Function as a whitelist
*
* @return
*/
protected Collection<String> getAllowedAggregationKeys() {
Expand All @@ -350,7 +356,7 @@ protected Criterion getCustomerRestriction() {

protected Criterion getTenantIdentifierRestriction() {
return new Criterion(TENANT_IDENTIFIER_KEY, externalSecurityService.getTenantIdentifier(),
CriterionOperator.EQUALS);
CriterionOperator.EQUALS);
}

protected E update(final E dto) {
Expand All @@ -360,17 +366,17 @@ protected E update(final E dto) {

protected List<E> getAll(final Optional<String> criteria) {
return getClient().getAll(getInternalHttpContext(), checkAuthorization(criteria)).stream()
.map(element -> converterToExternalDto(element)).collect(Collectors.toList());
.map(element -> converterToExternalDto(element)).collect(Collectors.toList());
}

protected List<E> getAll(final Optional<String> criteria, final Optional<String> embedded) {
return getClient().getAll(getInternalHttpContext(), checkAuthorization(criteria), embedded).stream()
.map(element -> converterToExternalDto(element)).collect(Collectors.toList());
.map(element -> converterToExternalDto(element)).collect(Collectors.toList());
}

protected boolean checkExists(final String criteria) {
return getClient().checkExist(getInternalHttpContext(),
checkAuthorization(Optional.ofNullable(criteria)).get());
checkAuthorization(Optional.ofNullable(criteria)).get());
}

protected void delete(final String id) {
Expand All @@ -382,12 +388,12 @@ protected void delete(final String id) {

protected void checkCustomerId(final String customerId, final String message) {
Assert.isTrue(StringUtils.equals(customerId, externalSecurityService.getCustomerId()),
message + ": customerId " + customerId + " is not allowed");
message + ": customerId " + customerId + " is not allowed");
}

protected void checkTenantIdentifier(final Integer tenantIdentifier, final String message) {
Assert.isTrue(externalSecurityService.getTenantIdentifier().equals(tenantIdentifier),
message + ": tenantIdentifier " + tenantIdentifier + " is not allowed");
message + ": tenantIdentifier " + tenantIdentifier + " is not allowed");
}

protected void checkLevel(final String level, final String message) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public class VitamQueryHelper {
private static final String EV_DATE_TIME_START = "evDateTime_Start";
private static final String EV_DATE_TIME_END = "evDateTime_End";
private static final String COMMENT = "events.evDetData.EvDetailReq";
private static final String SELECTED_ORIGINATING_AGENCIES = "SELECTED_ORIGINATING_AGENCIES";

/**
* create a valid VITAM DSL Query from a map of criteria
Expand All @@ -87,8 +88,8 @@ public class VitamQueryHelper {
* @throws InvalidCreateOperationException
*/
public static JsonNode createQueryDSL(Map<String, Object> searchCriteriaMap, final Integer pageNumber,
final Integer size,
final Optional<String> orderBy, final Optional<DirectionDto> direction)
final Integer size,
final Optional<String> orderBy, final Optional<DirectionDto> direction)
throws InvalidParseOperationException, InvalidCreateOperationException {

final Select select = new Select();
Expand Down Expand Up @@ -123,17 +124,26 @@ public static JsonNode createQueryDSL(Map<String, Object> searchCriteriaMap, fin
// string equals operation
final String stringValue = (String) entry.getValue();
query.add(eq(searchKey, stringValue));

break;
case OB_ID_IN:
case TRANSFERRING_AGENCY:
case ARCHIVAL_AGENCY:
case ORIGINATING_AGENCY:
case ID:
case COMMENT:
final String searchValue = (String) entry.getValue();
queryOr.add(eq(searchKey, searchValue));
haveOrParameters = true;
if (entry.getValue() instanceof ArrayList) {
final List<String> stringsValues = (ArrayList) entry.getValue();
for (String elt : stringsValues) {
queryOr.add(eq(searchKey, elt));
}
haveOrParameters = true;
} else {
if (entry.getValue() instanceof String) {
final String searchValue = (String) entry.getValue();
queryOr.add(eq(searchKey, searchValue));
haveOrParameters = true;
}
}
break;
case EV_TYPE:
// Special case EvType can be String or String[]
Expand All @@ -153,6 +163,15 @@ public static JsonNode createQueryDSL(Map<String, Object> searchCriteriaMap, fin
case EV_DATE_TIME_END:
query.add(lt("evDateTime", (String) entry.getValue()));
break;
case SELECTED_ORIGINATING_AGENCIES:
if (entry.getValue() instanceof ArrayList) {
final List<String> stringsValues = (ArrayList) entry.getValue();
for (String elt : stringsValues) {
orGroup.add(eq(ORIGINATING_AGENCY, elt));
}
haveOrGroup = true;
}
break;
default:
LOGGER.error("Can not find binding for key: {}", searchKey);
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022)
*
* contact.vitam@culture.gouv.fr
*
* This software is a computer program whose purpose is to implement a digital archiving back-office system managing
* high volumetry securely and efficiently.
*
* This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free
* software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as
* circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info".
*
* As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
* users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the
* successive licensors have only limited liability.
*
* In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or
* developing or reproducing the software by the user in light of its specific status of free software, that may mean
* that it is complicated to manipulate, and that also therefore means that it is reserved for developers and
* experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the
* software's suitability as regards their requirements in conditions enabling the security of their systems and/or data
* to be ensured and, more generally, to use and operate it in the same conditions as regards security.
*
* The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you
* accept its terms.
*/
package fr.gouv.vitamui.ingest.common.dto;

import fr.gouv.vitamui.commons.vitam.api.dto.AbstractVitamUIResponseDto;

public class AccessContractResponseDto extends AbstractVitamUIResponseDto<AccessContractVitamDto> {

}
Loading

0 comments on commit 0a54d51

Please sign in to comment.