From 2fa65b84c2d1111edc77f57b5b81482936110497 Mon Sep 17 00:00:00 2001 From: G TanSndil <72496065+GtanSndil@users.noreply.github.com> Date: Wed, 4 Dec 2024 10:24:32 +0100 Subject: [PATCH] Change document and link id in request (#815) * refactor: document id as object instead of String * refactor: documentId for delete document * refactor: improve display error message when document Id does not exist * Update DocumentsResources.java * refactor:delete document and delete link object instead of String * refactor: PUT /link/id object instead of String * refactor:add sanitize * test: add new tests for documents services * tests: clean codeLists tests * fix: * refactor: place of constant * refactor --- .../rmes/bauhaus_services/Constants.java | 3 + .../documents/DocumentsUtils.java | 2 +- .../operations/documentation/DocumentId.java | 23 ++ .../distribution/DistributionResources.java | 2 +- .../operations/DocumentsResources.java | 76 +++++- .../TestCodeListsResourcesEnvProd.java | 17 +- .../TestDocumentsResourcesEnvProd.java | 233 ++++++++++++++++++ 7 files changed, 332 insertions(+), 24 deletions(-) create mode 100644 src/main/java/fr/insee/rmes/config/swagger/model/operations/documentation/DocumentId.java create mode 100644 src/test/java/fr/insee/rmes/integration/authorizations/TestDocumentsResourcesEnvProd.java diff --git a/src/main/java/fr/insee/rmes/bauhaus_services/Constants.java b/src/main/java/fr/insee/rmes/bauhaus_services/Constants.java index 1583717c7..06f27de94 100644 --- a/src/main/java/fr/insee/rmes/bauhaus_services/Constants.java +++ b/src/main/java/fr/insee/rmes/bauhaus_services/Constants.java @@ -2,6 +2,7 @@ public class Constants { + /*A*/ public static final String ACCRUAL_PERIODICITY_LIST ="accrualPeriodicityList"; public static final String ALT_LABEL_LG1 = "altLabelLg1"; @@ -108,8 +109,10 @@ public class Constants { public static final String TEXT_LG1 = "texte"; public static final String TEXT_LG2 = "text"; public static final String TYPE_OF_OBJECT = "typeOfObject"; + public static final String TYPE_STRING = "String"; public static final String TYPELIST = "typeList"; + /*U*/ public static final String UNDEFINED = "undefined"; public static final String UPDATED_DATE = "updatedDate"; diff --git a/src/main/java/fr/insee/rmes/bauhaus_services/operations/documentations/documents/DocumentsUtils.java b/src/main/java/fr/insee/rmes/bauhaus_services/operations/documentations/documents/DocumentsUtils.java index 548a7265f..98656e17f 100644 --- a/src/main/java/fr/insee/rmes/bauhaus_services/operations/documentations/documents/DocumentsUtils.java +++ b/src/main/java/fr/insee/rmes/bauhaus_services/operations/documentations/documents/DocumentsUtils.java @@ -340,7 +340,7 @@ public JSONObject getDocument(String id, boolean isLink) throws RmesException { if (jsonDocs.isNull(Constants.URI)) { logger.error("Error with the document {}. It looks like it does not have an uri", id); - throw new RmesNotFoundException(ErrorCodes.DOCUMENT_UNKNOWN_ID, "Cannot find " + (isLink ? "Link" : "Document") + " with id: ", id); + throw new RmesNotFoundException(ErrorCodes.DOCUMENT_UNKNOWN_ID, "Cannot find " + (isLink ? "Link" : "Document") + " with id : " + id, id); } formatDateInJsonObject(jsonDocs); jsonDocs.put("sims", this.getSimsByDocument(id, isLink)); diff --git a/src/main/java/fr/insee/rmes/config/swagger/model/operations/documentation/DocumentId.java b/src/main/java/fr/insee/rmes/config/swagger/model/operations/documentation/DocumentId.java new file mode 100644 index 000000000..75e6279e3 --- /dev/null +++ b/src/main/java/fr/insee/rmes/config/swagger/model/operations/documentation/DocumentId.java @@ -0,0 +1,23 @@ +package fr.insee.rmes.config.swagger.model.operations.documentation; + +public class DocumentId { + private String id; + + public DocumentId(String id) { + this.id = id; + } + + public String getDocumentId() { + return id; + } + + public String getString() { + if (id != null && !id.isEmpty()) { + return id; + } + else{ + return null; //without this it might cause some trouble to test with new DocumentID(null) + } + } + +} diff --git a/src/main/java/fr/insee/rmes/webservice/distribution/DistributionResources.java b/src/main/java/fr/insee/rmes/webservice/distribution/DistributionResources.java index 29ec1c917..48fda9c5e 100644 --- a/src/main/java/fr/insee/rmes/webservice/distribution/DistributionResources.java +++ b/src/main/java/fr/insee/rmes/webservice/distribution/DistributionResources.java @@ -53,7 +53,7 @@ public String getDistributions() throws RmesException { } @GetMapping("/{id}") - @Operation(operationId = "getDistribution", summary = "Get a distributions", + @Operation(operationId = "getDistribution", summary = "Get a distribution", responses = {@ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = Distribution.class))))}) public Distribution getDistribution(@PathVariable(Constants.ID) String id) throws RmesException { return this.distributionService.getDistributionByID(id); diff --git a/src/main/java/fr/insee/rmes/webservice/operations/DocumentsResources.java b/src/main/java/fr/insee/rmes/webservice/operations/DocumentsResources.java index ae0f06d07..69e51f0d5 100644 --- a/src/main/java/fr/insee/rmes/webservice/operations/DocumentsResources.java +++ b/src/main/java/fr/insee/rmes/webservice/operations/DocumentsResources.java @@ -2,6 +2,7 @@ import fr.insee.rmes.bauhaus_services.Constants; import fr.insee.rmes.bauhaus_services.DocumentsService; +import fr.insee.rmes.config.swagger.model.operations.documentation.DocumentId; import fr.insee.rmes.exceptions.RmesException; import fr.insee.rmes.model.operations.documentations.Document; import io.swagger.v3.oas.annotations.Operation; @@ -107,15 +108,28 @@ public ResponseEntity setDocument( @PutMapping("/document/{id}") @Operation(operationId = "setDocumentById", summary = "Update document ") public ResponseEntity setDocument( - @Parameter(description = "Id", required = true) @PathVariable(Constants.ID) String id, - @Parameter(description = Constants.DOCUMENT, required = true, schema = @Schema(implementation = Document.class)) @RequestBody String body) throws RmesException { - documentsService.setDocument(id, body); + @Parameter( + description = "Id", + required = true, + schema = @Schema (type=Constants.TYPE_STRING) + ) + @PathVariable(Constants.ID) DocumentId id, + @Parameter( + description = Constants.DOCUMENT, + required = true, + schema = @Schema(implementation = Document.class) + ) + @RequestBody String body) throws RmesException { + String documentIdString = (id.getDocumentId() != null) ? sanitizeDocumentId(id.getDocumentId()) : null; + documentsService.setDocument(documentIdString, body); logger.info("Update document : {}", id); - return ResponseEntity.ok(id); + return ResponseEntity.ok(documentIdString); } - @PreAuthorize("hasAnyRole(T(fr.insee.rmes.config.auth.roles.Roles).ADMIN " + + + @PreAuthorize("hasAnyRole(T(fr.insee.rmes.config.auth.roles.Roles).ADMIN " + ", T(fr.insee.rmes.config.auth.roles.Roles).INDICATOR_CONTRIBUTOR " + ", T(fr.insee.rmes.config.auth.roles.Roles).SERIES_CONTRIBUTOR)") @Operation(operationId = "changeDocument", summary = "Change document file") @@ -140,8 +154,15 @@ public ResponseEntity changeDocument( + ", T(fr.insee.rmes.config.auth.roles.Roles).SERIES_CONTRIBUTOR)") @DeleteMapping("/document/{id}") @Operation(operationId = "deleteDocument", summary = "Delete a document") - public ResponseEntity deleteDocument(@PathVariable(Constants.ID) String id) throws RmesException { - return ResponseEntity.status(documentsService.deleteDocument(id)).body(id); + public ResponseEntity deleteDocument( + @Parameter( + required = true, + schema = @Schema (type=Constants.TYPE_STRING) + ) + @PathVariable(Constants.ID) DocumentId id) + throws RmesException { + String documentIdString = (id.getDocumentId() != null) ? sanitizeDocumentId(id.getDocumentId()) : null; + return ResponseEntity.status(documentsService.deleteDocument(documentIdString)).body(documentIdString); } @@ -176,9 +197,21 @@ public ResponseEntity setLink( @PutMapping("/link/{id}") @Operation(operationId = "setLinkById", summary = "Update link") public ResponseEntity setLink( - @Parameter(description = "Id", required = true) @PathVariable(Constants.ID) String id, - @Parameter(description = "Link", required = true, schema = @Schema(implementation = Document.class)) @RequestBody String body) throws RmesException { - return ResponseEntity.ok(documentsService.setLink(id, body)); + @Parameter( + description = "Id", + required = true, + schema = @Schema (type=Constants.TYPE_STRING) + ) + @PathVariable(Constants.ID) DocumentId id, + @Parameter( + required = true, + schema = @Schema(implementation = Document.class) + ) + @RequestBody String body + ) + throws RmesException { + String documentIdString = (id.getDocumentId() != null) ? sanitizeDocumentId(id.getDocumentId()) : null; + return ResponseEntity.ok(documentsService.setLink(documentIdString, body)); } @PreAuthorize("hasAnyRole(T(fr.insee.rmes.config.auth.roles.Roles).ADMIN " @@ -186,7 +219,26 @@ public ResponseEntity setLink( + ", T(fr.insee.rmes.config.auth.roles.Roles).SERIES_CONTRIBUTOR)") @DeleteMapping("/link/{id}") @Operation(operationId = "deleteLink", summary = "Delete a link") - public ResponseEntity deleteLink(@PathVariable(Constants.ID) String id) throws RmesException { - return ResponseEntity.status(documentsService.deleteLink(id)).body(id); + public ResponseEntity deleteLink( + @Parameter( + required = true, + schema = @Schema (type=Constants.TYPE_STRING) + ) + @PathVariable(Constants.ID) DocumentId id + ) throws RmesException { + String documentIdString = (id.getDocumentId() != null) ? sanitizeDocumentId(id.getDocumentId()) : null; + return ResponseEntity.status(documentsService.deleteLink(documentIdString)).body(documentIdString); + } + + + // Méthode pour encoder et valider le DocumentID + private String sanitizeDocumentId(String documentIdString) { + if (documentIdString == null || documentIdString.isEmpty()) { + return null; + } + //on peut ajouter d'autres contrôles + return documentIdString.replaceAll("[/<>:\"]", ""); } + + } diff --git a/src/test/java/fr/insee/rmes/integration/authorizations/TestCodeListsResourcesEnvProd.java b/src/test/java/fr/insee/rmes/integration/authorizations/TestCodeListsResourcesEnvProd.java index 61b2c0bb3..e133388c7 100644 --- a/src/test/java/fr/insee/rmes/integration/authorizations/TestCodeListsResourcesEnvProd.java +++ b/src/test/java/fr/insee/rmes/integration/authorizations/TestCodeListsResourcesEnvProd.java @@ -1,14 +1,15 @@ package fr.insee.rmes.integration.authorizations; import fr.insee.rmes.bauhaus_services.CodeListService; -import fr.insee.rmes.bauhaus_services.OperationsDocumentationsService; import fr.insee.rmes.bauhaus_services.StampAuthorizationChecker; import fr.insee.rmes.config.Config; import fr.insee.rmes.config.auth.UserProviderFromSecurityContext; import fr.insee.rmes.config.auth.roles.Roles; -import fr.insee.rmes.config.auth.security.*; +import fr.insee.rmes.config.auth.security.BauhausMethodSecurityExpressionHandler; +import fr.insee.rmes.config.auth.security.CommonSecurityConfiguration; +import fr.insee.rmes.config.auth.security.DefaultSecurityContext; +import fr.insee.rmes.config.auth.security.OpenIDConnectSecurityContext; import fr.insee.rmes.config.auth.user.Stamp; -import fr.insee.rmes.model.ValidationStatus; import fr.insee.rmes.webservice.codesLists.CodeListsResources; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -23,7 +24,6 @@ import java.util.List; import static fr.insee.rmes.integration.authorizations.TokenForTestsConfiguration.*; -import static fr.insee.rmes.model.ValidationStatus.UNPUBLISHED; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; @@ -56,15 +56,12 @@ class TestCodeListsResourcesEnvProd { @MockBean private CodeListService codeListService; @MockBean - protected OperationsDocumentationsService documentationsService; - @MockBean StampAuthorizationChecker stampAuthorizationChecker; private final String idep = "xxxxxx"; private final String timbre = "XX59-YYY"; int codesListId=10; - ValidationStatus status= UNPUBLISHED; @Test void putCodesListAdmin_ok() throws Exception { @@ -143,7 +140,7 @@ void postCodesListAsCodesListContributor_ok() throws Exception { @Test void postCodesList_noAuth() throws Exception { - mvc.perform(put("/codeList/") + mvc.perform(post("/codeList/") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .content("{\"id\": \"1\"}")) @@ -233,7 +230,7 @@ void postCode_noAuth() throws Exception { @Test void postCodeAsNotCodesListContributor() throws Exception { - configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("mauvais rôle")); + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("bad_role")); mvc.perform(post("/codeList/detailed/1/codes").header("Authorization", "Bearer toto") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) @@ -274,7 +271,7 @@ void putCode_noAuth() throws Exception { @Test void putCodeAsNotCodesListContributor() throws Exception { - configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("mauvais rôle")); + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("bad_role")); mvc.perform(put("/codeList/detailed/1/codes/2").header("Authorization", "Bearer toto") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) diff --git a/src/test/java/fr/insee/rmes/integration/authorizations/TestDocumentsResourcesEnvProd.java b/src/test/java/fr/insee/rmes/integration/authorizations/TestDocumentsResourcesEnvProd.java new file mode 100644 index 000000000..b3754e9a1 --- /dev/null +++ b/src/test/java/fr/insee/rmes/integration/authorizations/TestDocumentsResourcesEnvProd.java @@ -0,0 +1,233 @@ +package fr.insee.rmes.integration.authorizations; + +import fr.insee.rmes.bauhaus_services.DocumentsService; +import fr.insee.rmes.bauhaus_services.StampAuthorizationChecker; +import fr.insee.rmes.config.Config; +import fr.insee.rmes.config.auth.UserProviderFromSecurityContext; +import fr.insee.rmes.config.auth.security.BauhausMethodSecurityExpressionHandler; +import fr.insee.rmes.config.auth.security.CommonSecurityConfiguration; +import fr.insee.rmes.config.auth.security.DefaultSecurityContext; +import fr.insee.rmes.config.auth.security.OpenIDConnectSecurityContext; +import fr.insee.rmes.webservice.operations.DocumentsResources; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.security.oauth2.jwt.JwtDecoder; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.List; + +import static fr.insee.rmes.integration.authorizations.TokenForTestsConfiguration.*; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(controllers = DocumentsResources.class, + properties = {"fr.insee.rmes.bauhaus.env=PROD", + "jwt.stamp-claim=" + STAMP_CLAIM, + "jwt.role-claim=" + ROLE_CLAIM, + "jwt.id-claim=" + ID_CLAIM, + "jwt.role-claim.roles=" + KEY_FOR_ROLES_IN_ROLE_CLAIM, + "logging.level.org.springframework.security=DEBUG", + "logging.level.org.springframework.security.web.access=TRACE", + "logging.level.fr.insee.rmes.config.auth=TRACE", + "fr.insee.rmes.bauhaus.activeModules=operations"} +) +@Import({Config.class, + OpenIDConnectSecurityContext.class, + DefaultSecurityContext.class, + CommonSecurityConfiguration.class, + UserProviderFromSecurityContext.class, + BauhausMethodSecurityExpressionHandler.class}) + +class TestDocumentsResourcesEnvProd { + + @Autowired + private MockMvc mvc; + @MockBean + private JwtDecoder jwtDecoder; + @MockBean + private DocumentsService documentsService; + @MockBean + StampAuthorizationChecker stampAuthorizationChecker; + + private final String idep = "xxxxxx"; + private final String timbre = "XX59-YYY"; + + int documentId=10; + + + @Test + void getDocuments_ok() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("no particular role")); + + mvc.perform(get("/documents").header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isOk()); + } + + + @Test + void putDocumentAdmin_ok() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Administrateur_RMESGNCS")); + mvc.perform(put("/documents/document/" + documentId).header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content("{\"id\": \"10\"}")) + .andExpect(status().isOk()); + } + + @Test + void putDocumentAsSeriesContributor_ok() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Gestionnaire_serie_RMESGNCS")); + mvc.perform(put("/documents/document/" + documentId).header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content("{\"id\": \"10\"}")) + .andExpect(status().isOk()); + } + + @Test + void putDocumentAsIndicatorsContributor_ok() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Gestionnaire_indicateur_RMESGNCS")); + mvc.perform(put("/documents/document/" + documentId).header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content("{\"id\": \"10\"}")) + .andExpect(status().isOk()); + } + + @Test + void putDocumentBadRole() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Bad_role")); + mvc.perform(put("/documents/document/" + documentId).header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content("{\"id\": \"10\"}")) + .andExpect(status().isForbidden()); + } + + @Test + void putLinkAdmin_ok() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Administrateur_RMESGNCS")); + mvc.perform(put("/documents/link/" + documentId).header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content("{\"id\": \"10\"}")) + .andExpect(status().isOk()); + } + + @Test + void putLinkAsSeriesContributor_ok() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Gestionnaire_serie_RMESGNCS")); + mvc.perform(put("/documents/link/" + documentId).header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content("{\"id\": \"10\"}")) + .andExpect(status().isOk()); + } + + @Test + void putLinkAsIndicatorsContributor_ok() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Gestionnaire_indicateur_RMESGNCS")); + mvc.perform(put("/documents/link/" + documentId).header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content("{\"id\": \"10\"}")) + .andExpect(status().isOk()); + } + + @Test + void putLinkBadRole() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Bad_role")); + mvc.perform(put("/documents/link/" + documentId).header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content("{\"id\": \"10\"}")) + .andExpect(status().isForbidden()); + } + + @Test + void deleteDocumentAdmin_ok() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Administrateur_RMESGNCS")); + when(documentsService.deleteDocument(String.valueOf(documentId))).thenReturn(HttpStatus.OK); + mvc.perform(delete("/documents/document/" + documentId) + .header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } + + @Test + void deleteDocumentAsSeriesContributor_ok() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Gestionnaire_serie_RMESGNCS")); + when(documentsService.deleteDocument(String.valueOf(documentId))).thenReturn(HttpStatus.OK); + mvc.perform(delete("/documents/document/" + documentId) + .header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } + + @Test + void deleteDocumentAsIndicatorsContributor_ok() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Gestionnaire_indicateur_RMESGNCS")); + when(documentsService.deleteDocument(String.valueOf(documentId))).thenReturn(HttpStatus.OK); + mvc.perform(delete("/documents/document/" + documentId) + .header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } + + @Test + void deleteDocument_badRole() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Bad_role")); + when(documentsService.deleteDocument(String.valueOf(documentId))).thenReturn(HttpStatus.OK); + mvc.perform(delete("/documents/document/" + documentId) + .header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isForbidden()); + } + + + @Test + void deleteLinkAdmin_ok() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("Administrateur_RMESGNCS")); + when(documentsService.deleteLink(String.valueOf(documentId))).thenReturn(HttpStatus.OK); + mvc.perform(delete("/documents/link/" + documentId) + .header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } + + @Test + void deleteLink_badRole() throws Exception { + configureJwtDecoderMock(jwtDecoder, idep, timbre, List.of("bad_role")); + when(documentsService.deleteDocument(String.valueOf(documentId))).thenReturn(HttpStatus.OK); + mvc.perform(delete("/documents/link/" + documentId) + .header("Authorization", "Bearer toto") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isForbidden()); + } + + + + @Test + void postDocument_noAuth() throws Exception { + mvc.perform(post("/document/") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content("{\"id\": \"1\"}")) + .andExpect(status().isUnauthorized()); + } +}