Skip to content

Commit dd9a5af

Browse files
author
Hassane Diaby
committed
story #15015 : CSV errors when updating metadatas on Collect
1 parent aef96fe commit dd9a5af

File tree

20 files changed

+567
-27
lines changed

20 files changed

+567
-27
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022)
3+
*
4+
* contact.vitam@culture.gouv.fr
5+
*
6+
* This software is a computer program whose purpose is to implement a digital archiving back-office system managing
7+
* high volumetry securely and efficiently.
8+
*
9+
* This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free
10+
* software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as
11+
* circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info".
12+
*
13+
* As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
14+
* users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the
15+
* successive licensors have only limited liability.
16+
*
17+
* In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or
18+
* developing or reproducing the software by the user in light of its specific status of free software, that may mean
19+
* that it is complicated to manipulate, and that also therefore means that it is reserved for developers and
20+
* experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the
21+
* software's suitability as regards their requirements in conditions enabling the security of their systems and/or data
22+
* to be ensured and, more generally, to use and operate it in the same conditions as regards security.
23+
*
24+
* The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you
25+
* accept its terms.
26+
*/
27+
28+
package fr.gouv.vitamui.collect.common.dto;
29+
30+
import lombok.AllArgsConstructor;
31+
import lombok.Data;
32+
import lombok.NoArgsConstructor;
33+
34+
import java.util.List;
35+
36+
@Data
37+
@AllArgsConstructor
38+
@NoArgsConstructor
39+
public class VitamErrorDto {
40+
41+
private String code;
42+
private String httpCode;
43+
private String context;
44+
private String message;
45+
private List<VitamErrorsDetailsDto> errorsDetails;
46+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022)
3+
*
4+
* contact.vitam@culture.gouv.fr
5+
*
6+
* This software is a computer program whose purpose is to implement a digital archiving back-office system managing
7+
* high volumetry securely and efficiently.
8+
*
9+
* This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free
10+
* software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as
11+
* circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info".
12+
*
13+
* As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
14+
* users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the
15+
* successive licensors have only limited liability.
16+
*
17+
* In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or
18+
* developing or reproducing the software by the user in light of its specific status of free software, that may mean
19+
* that it is complicated to manipulate, and that also therefore means that it is reserved for developers and
20+
* experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the
21+
* software's suitability as regards their requirements in conditions enabling the security of their systems and/or data
22+
* to be ensured and, more generally, to use and operate it in the same conditions as regards security.
23+
*
24+
* The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you
25+
* accept its terms.
26+
*/
27+
28+
package fr.gouv.vitamui.collect.common.dto;
29+
30+
import lombok.AllArgsConstructor;
31+
import lombok.Data;
32+
import lombok.NoArgsConstructor;
33+
34+
import java.util.HashMap;
35+
36+
@Data
37+
@AllArgsConstructor
38+
@NoArgsConstructor
39+
public class VitamErrorsDetailsDto {
40+
41+
private String key;
42+
private HashMap<String, String> args;
43+
}

api/api-collect/collect/src/main/java/fr/gouv/vitamui/collect/server/rest/ProjectController.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
*/
2727
package fr.gouv.vitamui.collect.server.rest;
2828

29+
import com.fasterxml.jackson.databind.JsonNode;
2930
import fr.gouv.vitam.collect.common.dto.UploadSipResult;
3031
import fr.gouv.vitam.common.exception.VitamClientException;
3132
import fr.gouv.vitam.common.model.RequestResponseOK;
@@ -187,7 +188,7 @@ public CollectTransactionDto createTransactionForProject(
187188
@Secured(ServicesData.ROLE_CREATE_PROJECTS)
188189
@Operation(summary = "Upload and stream collect zip file")
189190
@PostMapping(value = "/upload", consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
190-
public void streamingUpload(
191+
public JsonNode streamingUpload(
191192
InputStream inputStream,
192193
@RequestHeader(value = CommonConstants.X_TRANSACTION_ID_HEADER) final String transactionId,
193194
@RequestHeader(value = CommonConstants.X_ATTACHMENT_ID_HEADER, required = false) final String attachmentId,
@@ -198,7 +199,7 @@ public void streamingUpload(
198199
SanityChecker.isValidFileName(originalFileName);
199200
SafeFileChecker.checkSafeFilePath(originalFileName);
200201
LOGGER.debug("[External] upload collect zip file : {}", originalFileName);
201-
projectService.streamingUpload(
202+
return projectService.streamingUpload(
202203
inputStream,
203204
transactionId,
204205
attachmentId,

api/api-collect/collect/src/main/java/fr/gouv/vitamui/collect/server/rest/TransactionController.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import fr.gouv.vitam.common.exception.VitamClientException;
3030
import fr.gouv.vitamui.archives.search.common.dto.ReclassificationCriteriaDto;
3131
import fr.gouv.vitamui.collect.common.dto.CollectTransactionDto;
32+
import fr.gouv.vitamui.collect.common.dto.VitamErrorDto;
3233
import fr.gouv.vitamui.collect.common.rest.RestApi;
3334
import fr.gouv.vitamui.collect.server.service.ExternalParametersService;
3435
import fr.gouv.vitamui.collect.server.service.TransactionService;
@@ -58,6 +59,7 @@
5859
import org.springframework.web.bind.annotation.RestController;
5960
import reactor.core.publisher.Mono;
6061

62+
import java.io.IOException;
6163
import java.io.InputStream;
6264

6365
import static fr.gouv.vitamui.collect.common.rest.RestApi.ABORT_PATH;
@@ -155,22 +157,22 @@ public CollectTransactionDto updateTransaction(@RequestBody CollectTransactionDt
155157
}
156158

157159
@Secured(ServicesData.COLLECT_UPDATE_BULK_ARCHIVE_UNIT_ROLE)
158-
@Operation(summary = "Upload on streaming metadata file and update archive units")
160+
@Operation(summary = "Upload on streaming metadata file and update archive units by CSV file")
159161
@PutMapping(
160162
value = CommonConstants.TRANSACTION_PATH_ID + UPDATE_UNITS_METADATA_PATH,
161163
consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE
162164
)
163-
public String updateArchiveUnitsMetadataFromFile(
165+
public VitamErrorDto updateArchiveUnitsMetadataFromCsvFile(
164166
final @PathVariable("transactionId") String transactionId,
165167
InputStream inputStream,
166168
@RequestHeader(value = CommonConstants.X_ORIGINAL_FILENAME_HEADER) final String originalFileName
167-
) throws PreconditionFailedException {
169+
) throws PreconditionFailedException, IOException {
168170
ParameterChecker.checkParameter(" [External] The transactionId is a mandatory parameter: ", transactionId);
169171
SanityChecker.checkSecureParameter(transactionId);
170172
SanityChecker.isValidFileName(originalFileName);
171173
SafeFileChecker.checkSafeFilePath(originalFileName);
172174
LOGGER.debug("[External] Calling update archive units metadata for transaction Id {} ", transactionId);
173-
return transactionService.updateArchiveUnitsFromFile(
175+
return transactionService.updateArchiveUnitsFromCsvFile(
174176
inputStream,
175177
transactionId,
176178
externalParametersService.buildVitamContextFromExternalParam()

api/api-collect/collect/src/main/java/fr/gouv/vitamui/collect/server/service/ProjectService.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ public PaginatedValuesDto<CollectProjectDto> getAllProjectsPaginated(
218218
}
219219
}
220220

221-
public void streamingUpload(
221+
public JsonNode streamingUpload(
222222
InputStream inputStream,
223223
String transactionId,
224224
String attachmentId,
@@ -228,10 +228,10 @@ public void streamingUpload(
228228
LOGGER.debug("TransactionId: {}", transactionId);
229229
LOGGER.debug("OriginalFileName: {}", originalFileName);
230230
try {
231-
collectService.uploadProjectZip(vitamContext, transactionId, attachmentId, inputStream);
231+
return collectService.uploadProjectZip(vitamContext, transactionId, attachmentId, inputStream).toJsonNode();
232232
} catch (VitamClientException e) {
233233
LOGGER.debug(UNABLE_TO_UPLOAD_PROJECT_ZIP_FILE, e);
234-
throw new InternalServerException(UNABLE_TO_UPLOAD_PROJECT_ZIP_FILE, e);
234+
return e.getVitamError().toJsonNode();
235235
}
236236
}
237237

api/api-collect/collect/src/main/java/fr/gouv/vitamui/collect/server/service/TransactionService.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
package fr.gouv.vitamui.collect.server.service;
3131

3232
import com.fasterxml.jackson.databind.JsonNode;
33+
import com.fasterxml.jackson.databind.ObjectMapper;
3334
import com.fasterxml.jackson.databind.node.ArrayNode;
3435
import com.fasterxml.jackson.databind.node.ObjectNode;
3536
import fr.gouv.vitam.collect.common.dto.TransactionDto;
@@ -41,6 +42,7 @@
4142
import fr.gouv.vitam.common.model.RequestResponseOK;
4243
import fr.gouv.vitamui.archives.search.common.dto.ReclassificationCriteriaDto;
4344
import fr.gouv.vitamui.collect.common.dto.CollectTransactionDto;
45+
import fr.gouv.vitamui.collect.common.dto.VitamErrorDto;
4446
import fr.gouv.vitamui.collect.server.service.converters.TransactionConverter;
4547
import fr.gouv.vitamui.commons.api.exception.BadRequestException;
4648
import fr.gouv.vitamui.commons.api.exception.InternalServerException;
@@ -59,6 +61,7 @@
5961
import org.springframework.stereotype.Service;
6062
import reactor.core.publisher.Mono;
6163

64+
import java.io.IOException;
6265
import java.io.InputStream;
6366
import java.util.Arrays;
6467

@@ -186,6 +189,21 @@ public String updateArchiveUnitsFromFile(InputStream inputStream, String transac
186189
return result;
187190
}
188191

192+
public VitamErrorDto updateArchiveUnitsFromCsvFile(
193+
InputStream inputStream,
194+
String transactionId,
195+
VitamContext vitamContext
196+
) throws IOException {
197+
try {
198+
LOGGER.debug("[Internal] call update Archive Units From CSV File for transaction Id {} ", transactionId);
199+
collectService.updateCollectArchiveUnitsWithCsv(vitamContext, transactionId, inputStream);
200+
return new VitamErrorDto("200", "Collect", null, "", null);
201+
} catch (VitamClientException e) {
202+
ObjectMapper objectMapper = new ObjectMapper();
203+
return objectMapper.treeToValue(e.getVitamError().toJsonNode(), VitamErrorDto.class);
204+
}
205+
}
206+
189207
public String reclassification(
190208
final String transactionId,
191209
final ReclassificationCriteriaDto reclassificationCriteriaDto,
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2015-2022)
3+
*
4+
* contact.vitam@culture.gouv.fr
5+
*
6+
* This software is a computer program whose purpose is to implement a digital archiving back-office system managing
7+
* high volumetry securely and efficiently.
8+
*
9+
* This software is governed by the CeCILL 2.1 license under French law and abiding by the rules of distribution of free
10+
* software. You can use, modify and/ or redistribute the software under the terms of the CeCILL 2.1 license as
11+
* circulated by CEA, CNRS and INRIA at the following URL "https://cecill.info".
12+
*
13+
* As a counterpart to the access to the source code and rights to copy, modify and redistribute granted by the license,
14+
* users are provided only with a limited warranty and the software's author, the holder of the economic rights, and the
15+
* successive licensors have only limited liability.
16+
*
17+
* In this respect, the user's attention is drawn to the risks associated with loading, using, modifying and/or
18+
* developing or reproducing the software by the user in light of its specific status of free software, that may mean
19+
* that it is complicated to manipulate, and that also therefore means that it is reserved for developers and
20+
* experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the
21+
* software's suitability as regards their requirements in conditions enabling the security of their systems and/or data
22+
* to be ensured and, more generally, to use and operate it in the same conditions as regards security.
23+
*
24+
* The fact that you are presently reading this means that you have had knowledge of the CeCILL 2.1 license and that you
25+
* accept its terms.
26+
*/
27+
28+
package fr.gouv.vitamui.collect.server.service.converters;
29+
30+
import lombok.experimental.UtilityClass;
31+
32+
@UtilityClass
33+
public class VitamErrorConverter {}

api/api-collect/collect/src/test/java/fr/gouv/vitamui/collect/server/rest/TransactionControllerTest.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import fr.gouv.vitam.common.client.VitamContext;
3333
import fr.gouv.vitam.common.exception.InvalidParseOperationException;
3434
import fr.gouv.vitam.common.exception.VitamClientException;
35+
import fr.gouv.vitamui.collect.common.dto.VitamErrorDto;
3536
import fr.gouv.vitamui.collect.server.service.ExternalParametersService;
3637
import fr.gouv.vitamui.collect.server.service.TransactionService;
3738
import fr.gouv.vitamui.commons.api.domain.IdDto;
@@ -49,6 +50,7 @@
4950
import org.springframework.test.context.bean.override.mockito.MockitoBean;
5051

5152
import java.io.ByteArrayInputStream;
53+
import java.io.IOException;
5254
import java.io.InputStream;
5355

5456
import static fr.gouv.vitamui.collect.common.rest.RestApi.COLLECT_TRANSACTION_PATH;
@@ -122,27 +124,30 @@ void when_searchCollectUnitsByCriteria_Service_ko_should_return_ko()
122124
}
123125

124126
@Test
125-
void testUpdateUnitsMetadataThenReturnVitamOperationDetails()
126-
throws InvalidParseOperationException, PreconditionFailedException {
127+
void testUpdateUnitsMetadataThenReturnVitamOperationDetails() throws PreconditionFailedException, IOException {
127128
// Given
128129
String fileName = "FileName";
129130
String transactionId = "transactionId";
130-
String expectedResponse = "operationStatus";
131+
VitamErrorDto expectedResponse = new VitamErrorDto("200", "200", "context", "", null);
131132
String initialString = "csv file to update collect units";
132133
InputStream csvFile = new ByteArrayInputStream(initialString.getBytes());
133134

134135
// When
135136
Mockito.when(externalParametersService.buildVitamContextFromExternalParam()).thenReturn(new VitamContext(0));
136137
Mockito.when(
137-
transactionService.updateArchiveUnitsFromFile(
138+
transactionService.updateArchiveUnitsFromCsvFile(
138139
any(InputStream.class),
139140
eq(transactionId),
140141
any(VitamContext.class)
141142
)
142143
).thenReturn(expectedResponse);
143-
String response = transactionController.updateArchiveUnitsMetadataFromFile(transactionId, csvFile, fileName);
144+
VitamErrorDto response = transactionController.updateArchiveUnitsMetadataFromCsvFile(
145+
transactionId,
146+
csvFile,
147+
fileName
148+
);
144149

145150
// Then
146-
Assertions.assertEquals(response, expectedResponse);
151+
Assertions.assertEquals(response.getCode(), expectedResponse.getCode());
147152
}
148153
}

commons/commons-vitam/src/main/java/fr/gouv/vitamui/commons/vitam/api/collect/CollectService.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,14 @@ public RequestResponse<JsonNode> searchProject(
239239
* @return
240240
* @throws VitamClientException
241241
*/
242-
public RequestResponse uploadProjectZip(
242+
public RequestResponse<JsonNode> uploadProjectZip(
243243
final VitamContext vitamContext,
244244
final String transactionId,
245245
final String attachmentId,
246246
final InputStream inputStream
247247
) throws VitamClientException {
248248
LOGGER.debug("upload zip by transaction id : {}", transactionId);
249-
final RequestResponse result = collectExternalClient.uploadZipToTransaction(
249+
final RequestResponse<JsonNode> result = collectExternalClient.uploadZipToTransaction(
250250
vitamContext,
251251
transactionId,
252252
inputStream,
@@ -416,6 +416,12 @@ public String updateCollectArchiveUnits(VitamContext vitamContext, String transa
416416
return response;
417417
}
418418

419+
public void updateCollectArchiveUnitsWithCsv(VitamContext vitamContext, String transactionId, InputStream csvFile)
420+
throws VitamClientException {
421+
LOGGER.debug(TRANSACTION_ID, transactionId);
422+
collectExternalClient.updateUnitsWithCsvMetadata(vitamContext, transactionId, csvFile);
423+
}
424+
419425
public JsonNode selectUnitWithInheritedRules(
420426
final JsonNode dslQuery,
421427
String transactionId,

ui/ui-frontend/projects/collect/src/app/collect/archive-search-collect/archive-collect.service.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import {
5959
SnackBarService,
6060
Transaction,
6161
Unit,
62+
VitamError,
6263
VitamuiHttpHeaders,
6364
} from 'vitamui-library';
6465
import { ProjectsApiService } from '../core/api/project-api.service';
@@ -292,6 +293,14 @@ export class ArchiveCollectService extends SearchService<any> implements SearchA
292293
return this.transactionApiService.updateUnitsMetadata(transactionId, csvFile, headers);
293294
}
294295

296+
updateUnitsMetadataByCsvFile(csvFile: Blob, fileName: string, transactionId: string): Observable<VitamError> {
297+
let headers = new HttpHeaders();
298+
headers = headers.append('Content-Type', 'application/octet-stream');
299+
headers = headers.append(VitamuiHttpHeaders.X_ORIGINAL_FILENAME, fileName);
300+
301+
return this.transactionApiService.updateUnitsMetadataByCsvFile(transactionId, csvFile, headers);
302+
}
303+
295304
getExternalOntologiesList(): Observable<IOntology[]> {
296305
return this.transactionApiService.getExternalOntologiesList();
297306
}

0 commit comments

Comments
 (0)