Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Epic #12041: Migration apps to API Gateway #1664

Merged
merged 8 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ maven-eclipse.xml
*~
.merge_file*
.java-version
.python-version

######################
# Gradle Wrapper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import fr.gouv.vitamui.archives.search.common.dto.RuleSearchCriteriaDto;
import fr.gouv.vitamui.archives.search.common.dto.TransferRequestDto;
import fr.gouv.vitamui.archives.search.common.dto.UnitDescriptiveMetadataDto;
import fr.gouv.vitamui.archives.search.common.dto.VitamUIArchiveUnitResponseDto;
import fr.gouv.vitamui.archives.search.common.rest.RestApi;
import fr.gouv.vitamui.commons.api.CommonConstants;
import fr.gouv.vitamui.commons.api.domain.PaginatedValuesDto;
Expand Down Expand Up @@ -91,14 +92,14 @@ public String getPathUrl() {
return RestApi.ARCHIVE_SEARCH_PATH;
}

public ArchiveUnitsDto searchArchiveUnitsByCriteria(ExternalHttpContext context, SearchCriteriaDto query) {
public VitamUIArchiveUnitResponseDto searchArchiveUnitsByCriteria(ExternalHttpContext context, SearchCriteriaDto query) {
LOGGER.debug("Calling search archives units by criteria");
MultiValueMap<String, String> headers = buildHeaders(context);

final HttpEntity<SearchCriteriaDto> request = new HttpEntity<>(query, headers);
final ResponseEntity<ArchiveUnitsDto> response =
final ResponseEntity<VitamUIArchiveUnitResponseDto> response =
restTemplate.exchange(getUrl() + RestApi.SEARCH_PATH, HttpMethod.POST,
request, ArchiveUnitsDto.class);
request, VitamUIArchiveUnitResponseDto.class);
checkResponse(response);
return response.getBody();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public List<SearchCriteriaHistoryDto> getSearchCriteriaHistory(final ExternalHtt
LOGGER.debug("getSearchCriteriaHistory external client");
final HttpEntity<?> request = new HttpEntity<>(buildHeaders(context));

final UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(getUrl() + CommonConstants.PATH_ME);
final UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(getUrl());

final ResponseEntity<List<SearchCriteriaHistoryDto>> response = restTemplate.exchange(uriBuilder.toUriString(), HttpMethod.GET, request, getDtoListClass());
checkResponse(response);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import fr.gouv.vitamui.archives.search.common.dto.ArchiveUnitsDto;
import fr.gouv.vitamui.archives.search.common.dto.TransferRequestDto;
import fr.gouv.vitamui.archives.search.common.dto.VitamUIArchiveUnitResponseDto;
import fr.gouv.vitamui.archives.search.common.rest.RestApi;
import fr.gouv.vitamui.commons.api.dtos.SearchCriteriaDto;
import fr.gouv.vitamui.commons.api.logger.VitamUILogger;
Expand Down Expand Up @@ -94,13 +95,13 @@ public void sampleArchiveTest() {
@Test
public void when_searchArchiveUnitsByCriteria_rest_template_ok_should_return_ok() {
SearchCriteriaDto query = new SearchCriteriaDto();
final ArchiveUnitsDto responseEntity = new ArchiveUnitsDto();
final VitamUIArchiveUnitResponseDto responseEntity = new VitamUIArchiveUnitResponseDto();

when(restTemplate
.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(ArchiveUnitsDto.class)))
.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(VitamUIArchiveUnitResponseDto.class)))
.thenReturn(new ResponseEntity<>(responseEntity, HttpStatus.OK));

ArchiveUnitsDto response =
VitamUIArchiveUnitResponseDto response =
archiveSearchExternalRestClient.searchArchiveUnitsByCriteria(defaultContext, query);

assertEquals(response, responseEntity);
Expand Down
5 changes: 4 additions & 1 deletion api/api-archive-search/archive-search-external/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@
<groupId>fr.gouv.vitamui</groupId>
<artifactId>iam-security</artifactId>
</dependency>

<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<!-- SPRING BOOT -->
<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@

import com.fasterxml.jackson.databind.JsonNode;
import fr.gouv.vitam.common.exception.InvalidParseOperationException;
import fr.gouv.vitamui.archives.search.common.dto.ArchiveUnitsDto;
import fr.gouv.vitamui.archives.search.common.dto.ExportDipCriteriaDto;
import fr.gouv.vitamui.archives.search.common.dto.ReclassificationCriteriaDto;
import fr.gouv.vitamui.archives.search.common.dto.RuleSearchCriteriaDto;
import fr.gouv.vitamui.archives.search.common.dto.TransferRequestDto;
import fr.gouv.vitamui.archives.search.common.dto.UnitDescriptiveMetadataDto;
import fr.gouv.vitamui.archives.search.common.dto.VitamUIArchiveUnitResponseDto;
import fr.gouv.vitamui.archives.search.common.rest.RestApi;
import fr.gouv.vitamui.archives.search.external.server.service.ArchivesSearchExternalService;
import fr.gouv.vitamui.common.security.SafeFileChecker;
Expand Down Expand Up @@ -97,7 +97,7 @@ public ArchivesSearchExternalController(ArchivesSearchExternalService archivesSe

@PostMapping(RestApi.SEARCH_PATH)
@Secured(ServicesData.ROLE_GET_ARCHIVE)
public ArchiveUnitsDto searchArchiveUnitsByCriteria(final @RequestBody SearchCriteriaDto query) {
public VitamUIArchiveUnitResponseDto searchArchiveUnitsByCriteria(final @RequestBody SearchCriteriaDto query) {
ParameterChecker.checkParameter(MANDATORY_QUERY, query);
SanityChecker.sanitizeCriteria(query);
LOGGER.debug("Calling search archive Units By Criteria {} ", query);
Expand All @@ -114,7 +114,8 @@ public VitamUISearchResponseDto getFillingHoldingScheme() {
CommonConstants.PATH_ID, produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@Secured(ServicesData.ROLE_GET_ARCHIVE)
public Mono<ResponseEntity<Resource>> downloadObjectFromUnit(final @PathVariable("id") String id,
final @RequestParam("usage") String usage, final @RequestParam("version") Integer version)
final @RequestParam(value = "usage", required = false) String usage,
final @RequestParam(value = "version", required = false) Integer version)
throws InvalidParseOperationException, PreconditionFailedException {
ParameterChecker.checkParameter(MANDATORY_IDENTIFIER, id);
SanityChecker.checkSecureParameter(id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public SearchCriteriaHistoryExternalController(final SearchCriteriaHistoryExtern
this.searchCriteriaHistoryExternalService = searchCriteriaHistoryExternalService;
}

@GetMapping(CommonConstants.PATH_ME)
@GetMapping
@Secured(ServicesData.ROLE_GET_ALL_ARCHIVE)
public List<SearchCriteriaHistoryDto> getSearchCriteriaHistory() {
LOGGER.debug("getSearchCriteriaHistory archive external");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,32 +31,52 @@
import fr.gouv.archive.internal.client.ArchiveInternalRestClient;
import fr.gouv.archive.internal.client.ArchiveSearchInternalWebClient;
import fr.gouv.archive.internal.client.ArchiveSearchStreamingInternalRestClient;
import fr.gouv.vitam.common.model.objectgroup.VersionsModel;
import fr.gouv.vitamui.archives.search.common.dto.ArchiveUnitsDto;
import fr.gouv.vitamui.archives.search.common.dto.ExportDipCriteriaDto;
import fr.gouv.vitamui.archives.search.common.dto.ReclassificationCriteriaDto;
import fr.gouv.vitamui.archives.search.common.dto.RuleSearchCriteriaDto;
import fr.gouv.vitamui.archives.search.common.dto.TransferRequestDto;
import fr.gouv.vitamui.archives.search.common.dto.UnitDescriptiveMetadataDto;
import fr.gouv.vitamui.archives.search.common.dto.VitamUIArchiveUnitResponseDto;
import fr.gouv.vitamui.commons.api.dtos.SearchCriteriaDto;
import fr.gouv.vitamui.commons.api.dtos.VitamUiOntologyDto;
import fr.gouv.vitamui.commons.api.logger.VitamUILogger;
import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory;
import fr.gouv.vitamui.commons.vitam.api.dto.PersistentIdentifierResponseDto;
import fr.gouv.vitamui.commons.vitam.api.dto.QualifiersDto;
import fr.gouv.vitamui.commons.vitam.api.dto.ResultsDto;
import fr.gouv.vitamui.commons.vitam.api.dto.VersionsDto;
import fr.gouv.vitamui.commons.vitam.api.dto.VitamUISearchResponseDto;
import fr.gouv.vitamui.commons.vitam.api.model.ObjectQualifierType;
import fr.gouv.vitamui.iam.security.client.AbstractResourceClientService;
import fr.gouv.vitamui.iam.security.service.ExternalSecurityService;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.MimeType;
import reactor.core.publisher.Mono;

import javax.ws.rs.core.MediaType;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;

import static fr.gouv.vitamui.commons.rest.util.RestUtils.CONTENT_DISPOSITION;
import static java.util.Comparator.comparing;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static java.util.Optional.empty;
import static org.apache.commons.lang3.ObjectUtils.isEmpty;
import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.apache.commons.lang3.StringUtils.isNotBlank;


/**
Expand Down Expand Up @@ -99,12 +119,13 @@ protected ArchiveInternalRestClient getClient() {
}


public ArchiveUnitsDto searchArchiveUnitsByCriteria(final SearchCriteriaDto query) {
public VitamUIArchiveUnitResponseDto searchArchiveUnitsByCriteria(final SearchCriteriaDto query) {
Optional<Long> thresholdOpt = archiveSearchThresholdService.retrieveProfilThresholds();
if (thresholdOpt.isPresent()) {
query.setThreshold(thresholdOpt.get());
}
return getClient().searchArchiveUnitsByCriteria(getInternalHttpContext(), query);
ArchiveUnitsDto archiveUnitsDto = getClient().searchArchiveUnitsByCriteria(getInternalHttpContext(), query);
return archiveUnitsDto == null ? null : archiveUnitsDto.getArchives();
}

public ResponseEntity<ResultsDto> findUnitById(String id) {
Expand All @@ -120,8 +141,92 @@ public VitamUISearchResponseDto getFilingHoldingScheme() {
}

public Mono<ResponseEntity<Resource>> downloadObjectFromUnit(String id, String usage, Integer version) {
// Logic moved here from ui-archive-search
String fileName = null;
ResultsDto got = findObjectById(id).getBody();
if (nonNull(got)) {
QualifiersDto qualifier;
if (isEmpty(usage)) {
// find the best qualifier for download
qualifier = getLastObjectQualifier(got);
} else {
String finalUsage = usage;
qualifier = got.getQualifiers().stream()
.filter(q -> finalUsage.equals(q.getQualifier()))
.findFirst()
.orElse(null);
}
if (nonNull(qualifier)) {
usage = qualifier.getQualifier();
VersionsDto versionsDto;
if (isNull(version)) {
// find the latest version for the qualifier
versionsDto = getLastVersion(qualifier);
} else {
Integer finalVersion = version;
versionsDto = qualifier.getVersions().stream()
.filter(v -> finalVersion.equals(extractVersion(v)))
.findFirst()
.orElse(null);
}
if (nonNull(versionsDto)) {
version = extractVersion(versionsDto);
fileName = getFilename(versionsDto);
}
}
}
return archiveSearchInternalWebClient
.downloadObjectFromUnit(id, usage, version, getInternalHttpContext());
.downloadObjectFromUnit(id, usage, version, getInternalHttpContext(), fileName);
}

private QualifiersDto getLastObjectQualifier(ResultsDto got) {
for (String qualifierName : ObjectQualifierType.downloadableValuesOrdered) {
QualifiersDto qualifierFound = got.getQualifiers().stream()
.filter(qualifier -> qualifierName.equals(qualifier.getQualifier()))
.reduce((first, second) -> second)
.orElse(null);
if (nonNull(qualifierFound)) {
return qualifierFound;
}
}
return null;
}

private VersionsDto getLastVersion(QualifiersDto qualifier) {
return qualifier.getVersions().stream()
.max(comparing(ArchivesSearchExternalService::extractVersion))
.orElse(null);
}

@NotNull
private static Integer extractVersion(VersionsDto versionsDto) {
return Integer.parseInt(versionsDto.getDataObjectVersion().split("_")[1]);
}

private String getFilename(VersionsDto version) {
if (isNull(version) || StringUtils.isEmpty(version.getId())) {
return null;
}
return version.getId() + getExtension(version);
}

private String getExtension(VersionsDto version) {
String uriExtension = EMPTY;
if (isNotBlank(version.getUri()) && version.getUri().contains(".")) {
uriExtension = version.getUri().substring(version.getUri().lastIndexOf('.') + 1);
}
String filenameExtension = EMPTY;
if (nonNull(version.getFileInfoModel()) && isNotBlank(version.getFileInfoModel().getFilename()) &&
version.getFileInfoModel().getFilename().contains(".")) {
filenameExtension = version.getFileInfoModel().getFilename()
.substring(version.getFileInfoModel().getFilename().lastIndexOf('.') + 1);
}
if (isNotBlank(filenameExtension)) {
return "." + filenameExtension;
} else if (isNotBlank(uriExtension)) {
return "." + uriExtension;
}
return EMPTY;
}

public Resource exportCsvArchiveUnitsByCriteria(final SearchCriteriaDto query) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,17 @@ logging:
fr.gouv.vitamui: DEBUG
fr.gouv.vitamui.iam.security: DEBUG
#level.org.springframework.web.filter.CommonsRequestLoggingFilter: DEBUG


---
spring:
config:
activate:
on-profile: gateway

gateway:
enabled: true
server:
ssl:
client-auth: want
client-certificate-header-name: x-ssl-cert
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
import fr.gouv.archive.internal.client.ArchiveInternalRestClient;
import fr.gouv.vitam.common.exception.InvalidParseOperationException;
import fr.gouv.vitam.common.model.export.transfer.TransferRequestParameters;
import fr.gouv.vitamui.archives.search.common.dto.ArchiveUnitsDto;
import fr.gouv.vitamui.archives.search.common.dto.RuleSearchCriteriaDto;
import fr.gouv.vitamui.archives.search.common.dto.TransferRequestDto;
import fr.gouv.vitamui.archives.search.common.dto.VitamUIArchiveUnitResponseDto;
import fr.gouv.vitamui.archives.search.common.rest.RestApi;
import fr.gouv.vitamui.archives.search.external.client.ArchiveSearchExternalRestClient;
import fr.gouv.vitamui.archives.search.external.server.service.ArchivesSearchExternalService;
Expand Down Expand Up @@ -150,11 +150,11 @@ void test_searchArchiveUnitsByCriteria_with_ok_criteria_should_return_ok() throw
PreconditionFailedException {

SearchCriteriaDto query = new SearchCriteriaDto();
ArchiveUnitsDto expectedResponse = new ArchiveUnitsDto();
VitamUIArchiveUnitResponseDto expectedResponse = new VitamUIArchiveUnitResponseDto();
Mockito
.when(archivesSearchExternalService.searchArchiveUnitsByCriteria(query))
.thenReturn(expectedResponse);
ArchiveUnitsDto responseDto = archivesSearchExternalController.searchArchiveUnitsByCriteria(query);
VitamUIArchiveUnitResponseDto responseDto = archivesSearchExternalController.searchArchiveUnitsByCriteria(query);
assertEquals(responseDto, expectedResponse);
}

Expand All @@ -168,7 +168,7 @@ void test_searchArchiveUnitsByCriteria_with_invalid_criteria_should_return_ko()
nodeCriteria.setCategory(ArchiveSearchConsts.CriteriaCategory.NODES);
nodeCriteria.setValues(List.of(new CriteriaValue("<s>insecure</s>")));
query.setCriteriaList(List.of(nodeCriteria));
ArchiveUnitsDto expectedResponse = new ArchiveUnitsDto();
VitamUIArchiveUnitResponseDto expectedResponse = new VitamUIArchiveUnitResponseDto();
Mockito
.when(archivesSearchExternalService.searchArchiveUnitsByCriteria(query))
.thenReturn(expectedResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public void testGetSearchCriteriaHistories() throws Exception {
LOGGER.debug("get search criterias");
Mockito.when(service.getSearchCriteriaHistory()).thenReturn(Arrays.asList(new SearchCriteriaHistoryDto()));

ResultActions result = super.performGet(CommonConstants.PATH_ME);
ResultActions result = super.performGet("");
result.andExpect(MockMvcResultMatchers.handler().methodCall(mockedController.getSearchCriteriaHistory()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import static fr.gouv.vitamui.commons.rest.util.RestUtils.CONTENT_DISPOSITION;
import static java.util.Objects.nonNull;

public class ArchiveSearchInternalWebClient extends BaseWebClient<InternalHttpContext> {

private static final VitamUILogger LOGGER = VitamUILoggerFactory.getInstance(ArchiveSearchInternalWebClient.class);
Expand All @@ -64,6 +67,21 @@ public String getPathUrl() {
*/
public Mono<ResponseEntity<Resource>> downloadObjectFromUnit(String id, final String usage, Integer version,
final InternalHttpContext context) {
return downloadObjectFromUnit(id, usage, version, context, null);
}

/**
* Download object from unit
*
* @param id unit id
* @param usage usage
* @param version version
* @param context internl context
* @param fileName the file's name
* @return a mono<Response<Resourse>
*/
public Mono<ResponseEntity<Resource>> downloadObjectFromUnit(String id, final String usage, Integer version,
final InternalHttpContext context, final String fileName) {
LOGGER.debug("Start downloading Object from unit id : {} usage : {} version : {}", id, usage, version);
final UriComponentsBuilder uriBuilder =
UriComponentsBuilder.fromHttpUrl(
Expand All @@ -79,11 +97,15 @@ public Mono<ResponseEntity<Resource>> downloadObjectFromUnit(String id, final St
.retrieve()
.bodyToFlux(DataBuffer.class);


if (nonNull(fileName)) {
return Mono.just(ResponseEntity
.ok().header(CONTENT_DISPOSITION, "attachment;filename=" + fileName)
.cacheControl(CacheControl.noCache())
.body(convertDataBufferFileToInputStreamResponse(dataBuffer)));
}
return Mono.just(ResponseEntity
.ok().cacheControl(CacheControl.noCache())
.body(convertDataBufferFileToInputStreamResponse(dataBuffer)));

}

}
Loading