diff --git a/src/main/java/org/gridsuite/study/server/controller/NetworkModificationController.java b/src/main/java/org/gridsuite/study/server/controller/NetworkModificationController.java index b58aa8a74..52bd03d34 100644 --- a/src/main/java/org/gridsuite/study/server/controller/NetworkModificationController.java +++ b/src/main/java/org/gridsuite/study/server/controller/NetworkModificationController.java @@ -45,13 +45,14 @@ public ResponseEntity getLineTypeWithLimits(@PathVariable UUID uuid, @Re @GetMapping(value = "/network-composite-modifications/network-modifications") public ResponseEntity getNetworkModificationsFromComposite(@RequestParam("uuids") List compositeModificationUuids, - @RequestParam(name = "onlyMetadata", defaultValue = "true") boolean onlyMetadata) { - return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(networkModificationService.getNetworkModificationsFromComposite(compositeModificationUuids, onlyMetadata)); + @RequestParam(name = "onlyMetadata", defaultValue = "true") boolean onlyMetadata, + @RequestHeader(HEADER_USER_ID) String userId) { + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(networkModificationService.getNetworkModificationsFromComposite(compositeModificationUuids, onlyMetadata, userId)); } @GetMapping(value = "/network-modifications/{uuid}") - public ResponseEntity getNetworkModification(@PathVariable UUID uuid) { - return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(networkModificationService.getNetworkModification(uuid)); + public ResponseEntity getNetworkModification(@PathVariable UUID uuid, @RequestHeader(HEADER_USER_ID) String userId) { + return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(networkModificationService.getNetworkModification(uuid, userId)); } @GetMapping(value = "/network-modifications/busbar-sections-for-new-coupler") diff --git a/src/main/java/org/gridsuite/study/server/controller/StudyController.java b/src/main/java/org/gridsuite/study/server/controller/StudyController.java index 093d7f7e5..b706cebba 100644 --- a/src/main/java/org/gridsuite/study/server/controller/StudyController.java +++ b/src/main/java/org/gridsuite/study/server/controller/StudyController.java @@ -963,9 +963,10 @@ public ResponseEntity getNetworkModifications(@Parameter(description = " @Parameter(description = "Node UUID") @PathVariable("nodeUuid") UUID nodeUuid, @RequestParam(name = "onlyStashed", required = false, defaultValue = "false") Boolean onlyStashed, @Parameter(description = "Only metadata") @RequestParam(name = "onlyMetadata", required = false, - defaultValue = "false") Boolean onlyMetadata) { + defaultValue = "false") Boolean onlyMetadata, + @RequestHeader(HEADER_USER_ID) String userId) { studyService.assertIsStudyAndNodeExist(studyUuid, nodeUuid); - return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(networkModificationTreeService.getNetworkModifications(nodeUuid, onlyStashed, onlyMetadata)); + return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(networkModificationTreeService.getNetworkModifications(nodeUuid, onlyStashed, onlyMetadata, userId)); } @GetMapping(value = "/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications/export", produces = MediaType.APPLICATION_JSON_VALUE) diff --git a/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java b/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java index 01a4b9c1d..07816105e 100644 --- a/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java +++ b/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java @@ -89,6 +89,22 @@ private String buildPathFrom(UUID networkUuid) { .toUriString(); } + private static HttpEntity userIdEntity(String userId) { + return userIdEntity(userId, null); + } + + private static HttpEntity userIdEntity(String userId, T body) { + if (userId == null) { + return null; + } + HttpHeaders headers = new HttpHeaders(); + headers.set(HEADER_USER_ID, userId); + if (body != null) { + headers.setContentType(MediaType.APPLICATION_JSON); + } + return new HttpEntity<>(body, headers); + } + public String getLineTypesCatalog() { return restTemplate.getForObject(getNetworkModificationServerURI(false) + NETWORK_MODIFICATIONS_PATH + "/catalog/line_types", String.class); } @@ -107,17 +123,17 @@ public String getLineTypeWithLimits(UUID lineTypeUuid, String area, String tempe return restTemplate.getForObject(getNetworkModificationServerURI(false) + path, String.class); } - public String getNetworkModificationsFromComposite(List compositeModificationUuids, boolean onlyMetadata) { + public String getNetworkModificationsFromComposite(List compositeModificationUuids, boolean onlyMetadata, String userId) { String path = UriComponentsBuilder.fromPath(COMPOSITE_PATH + NETWORK_MODIFICATIONS_PATH) .queryParam(UUIDS, compositeModificationUuids) .queryParam("onlyMetadata", onlyMetadata) .build().toUriString(); - return restTemplate.getForObject(getNetworkModificationServerURI(false) + path, String.class); + return restTemplate.exchange(getNetworkModificationServerURI(false) + path, HttpMethod.GET, userIdEntity(userId), String.class).getBody(); } - public String getNetworkModification(UUID networkModificationUuid) { + public String getNetworkModification(UUID networkModificationUuid, String userId) { String path = UriComponentsBuilder.fromPath(NETWORK_MODIFICATIONS_PATH + "/{uuid}").buildAndExpand(networkModificationUuid).toUriString(); - return restTemplate.getForObject(getNetworkModificationServerURI(false) + path, String.class); + return restTemplate.exchange(getNetworkModificationServerURI(false) + path, HttpMethod.GET, userIdEntity(userId), String.class).getBody(); } public String getBusBarSectionsForNewCoupler(String voltageLevelId, Integer busBarCount, Integer sectionCount, List switchKindList) { @@ -146,7 +162,10 @@ public void updateNetworkModificationsMetadata(List networkModificationUui restTemplate.exchange(getNetworkModificationServerURI(false) + path, HttpMethod.PUT, new HttpEntity<>(metadata, headers), Void.class); } - public String getModifications(UUID groupUUid, boolean stashedModifications, boolean onlyMetadata) { + /** + * @param userId the user the modifications are read for, to supply if permissions are needed + */ + public String getModifications(UUID groupUUid, boolean stashedModifications, boolean onlyMetadata, String userId) { Objects.requireNonNull(groupUUid); var path = UriComponentsBuilder.fromPath(GROUP_PATH + DELIMITER + NETWORK_MODIFICATIONS_PATH) .queryParam(QUERY_PARAM_ERROR_ON_GROUP_NOT_FOUND, false) @@ -155,7 +174,7 @@ public String getModifications(UUID groupUUid, boolean stashedModifications, boo .buildAndExpand(groupUUid) .toUriString(); - return restTemplate.exchange(getNetworkModificationServerURI(false) + path, HttpMethod.GET, null, String.class).getBody(); + return restTemplate.exchange(getNetworkModificationServerURI(false) + path, HttpMethod.GET, userIdEntity(userId), String.class).getBody(); } public String getModificationsToExport(UUID groupUUid) { @@ -244,13 +263,7 @@ public void updateModification(String createEquipmentAttributes, UUID modificati .buildAndExpand() .toUriString(); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.set(HEADER_USER_ID, userId); - - HttpEntity httpEntity = new HttpEntity<>(createEquipmentAttributes, headers); - - restTemplate.exchange(path, HttpMethod.PUT, httpEntity, Void.class); + restTemplate.exchange(path, HttpMethod.PUT, userIdEntity(userId, createEquipmentAttributes), Void.class); } public void stashModifications(UUID groupUUid, List modificationsUuids, String userId) { @@ -282,12 +295,7 @@ public void updateModificationsMetadata(UUID groupUUid, List modifications .buildAndExpand() .toUriString(); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.set(HEADER_USER_ID, userId); - - HttpEntity httpEntity = new HttpEntity<>(metadata, headers); - restTemplate.exchange(path, HttpMethod.PUT, httpEntity, Void.class); + restTemplate.exchange(path, HttpMethod.PUT, userIdEntity(userId, metadata), Void.class); } public void restoreModifications(UUID groupUUid, List modificationsUuids, UUID studyUuid, UUID nodeUuid, String userId) { @@ -742,10 +750,7 @@ public void assertReferencedModificationsAreWritable(List containerUuids, .queryParam(UUIDS, containerUuids) .build().toUriString(); - HttpHeaders headers = new HttpHeaders(); - headers.set(HEADER_USER_ID, userId); - - restTemplate.exchange(getNetworkModificationServerURI(false) + path, HttpMethod.GET, new HttpEntity<>(headers), Void.class); + restTemplate.exchange(getNetworkModificationServerURI(false) + path, HttpMethod.GET, userIdEntity(userId), Void.class); } /** diff --git a/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java b/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java index b4ecc24e6..c8303b920 100644 --- a/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java +++ b/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java @@ -820,8 +820,8 @@ public UUID getModificationGroupUuid(UUID nodeUuid) { } @Transactional(readOnly = true) - public String getNetworkModifications(@NonNull UUID nodeUuid, boolean onlyStashed, boolean onlyMetadata) { - return networkModificationService.getModifications(self.getModificationGroupUuid(nodeUuid), onlyStashed, onlyMetadata); + public String getNetworkModifications(@NonNull UUID nodeUuid, boolean onlyStashed, boolean onlyMetadata, String userId) { + return networkModificationService.getModifications(self.getModificationGroupUuid(nodeUuid), onlyStashed, onlyMetadata, userId); } private Integer getNetworkModificationsCount(@NonNull UUID nodeUuid, boolean stashed) { diff --git a/src/main/java/org/gridsuite/study/server/service/StudyService.java b/src/main/java/org/gridsuite/study/server/service/StudyService.java index 09f46323d..eaeceaafa 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -2408,7 +2408,7 @@ public String getVoltageInitModifications(@NonNull UUID nodeUuid, @NonNull UUID throw new StudyException(NO_VOLTAGE_INIT_RESULTS_FOR_NODE, String.format("Missing results for rootNetwork %s on node %s", rootNetworkUuid, nodeUuid)); } UUID voltageInitModificationsGroupUuid = voltageInitRestService.getModificationsGroupUuid(nodeUuid, resultUuid); - return networkModificationService.getModifications(voltageInitModificationsGroupUuid, false, false); + return networkModificationService.getModifications(voltageInitModificationsGroupUuid, false, false, null); } @Transactional diff --git a/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java b/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java index b1bf0489a..a02ae1b78 100644 --- a/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java +++ b/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java @@ -88,6 +88,7 @@ import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; +import static org.gridsuite.study.server.StudyConstants.HEADER_USER_ID; import static org.gridsuite.study.server.error.StudyBusinessErrorCode.NOT_FOUND; import static org.gridsuite.study.server.notification.NotificationService.*; import static org.gridsuite.study.server.service.NetworkModificationTreeService.ROOT_NODE_NAME; @@ -1544,17 +1545,17 @@ void testGetNetworkModificationsNode() throws Exception { randomUuidsResultStack(), BuildStatus.BUILT); createNode(root.getStudyId(), root, node, userId); - mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), node.getId())) + mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), node.getId()).header(HEADER_USER_ID, "userId")) .andExpect(status().isNotFound()); // No network modification for a root node - mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), root.getId())) + mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), root.getId()).header(HEADER_USER_ID, "userId")) .andExpect(status().isNotFound()); node = NetworkModificationTreeTest.buildNetworkModificationConstructionNode("modification node 2", "", MODIFICATION_GROUP_UUID, VARIANT_ID, randomUuidsResultStack(), BuildStatus.BUILT); createNode(root.getStudyId(), root, node, userId); - mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), node.getId())) + mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), node.getId()).header(HEADER_USER_ID, "userId")) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); } @@ -1600,7 +1601,7 @@ void testGetNetworkModificationsToRestoreByNode() throws Exception { randomUuidsResultStack(), BuildStatus.BUILT); createNode(root.getStudyId(), root, node, userId); - mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), node.getId(), true)) + mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), node.getId(), true).header(HEADER_USER_ID, "userId")) .andExpect(status().isNotFound()); node = NetworkModificationTreeTest.buildNetworkModificationConstructionNode("modification node 3", "", UUID.fromString(MODIFICATION_GROUP_UUID_STRING), VARIANT_ID, @@ -1623,11 +1624,11 @@ void testGetNetworkModificationsToStashByNode() throws Exception { randomUuidsResultStack(), BuildStatus.BUILT); createNode(root.getStudyId(), root, node, userId); - mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), node.getId(), false)) + mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), node.getId(), false).header(HEADER_USER_ID, "userId")) .andExpect(status().isNotFound()); // No network modification for a root node - mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), root.getId(), false)) + mockMvc.perform(get("/v1/studies/{studyUuid}/nodes/{nodeUuid}/network-modifications", root.getStudyId(), root.getId(), false).header(HEADER_USER_ID, "userId")) .andExpect(status().isNotFound()); node = NetworkModificationTreeTest.buildNetworkModificationConstructionNode("modification node 3", "", UUID.fromString(MODIFICATION_GROUP_UUID_STRING), VARIANT_ID, diff --git a/src/test/java/org/gridsuite/study/server/controller/NetworkModificationControllerTest.java b/src/test/java/org/gridsuite/study/server/controller/NetworkModificationControllerTest.java index bc3b9f695..2856d571d 100644 --- a/src/test/java/org/gridsuite/study/server/controller/NetworkModificationControllerTest.java +++ b/src/test/java/org/gridsuite/study/server/controller/NetworkModificationControllerTest.java @@ -21,6 +21,7 @@ import static org.gridsuite.study.server.StudyConstants.HEADER_USER_ID; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; @@ -90,29 +91,38 @@ void testGetLineTypeWithLimits() throws Exception { void testGetNetworkModificationsFromComposite() throws Exception { UUID firstUuid = UUID.randomUUID(); UUID secondUuid = UUID.randomUUID(); - when(networkModificationService.getNetworkModificationsFromComposite(List.of(firstUuid, secondUuid), false)).thenReturn(RESPONSE); + when(networkModificationService.getNetworkModificationsFromComposite(List.of(firstUuid, secondUuid), false, USER_ID)).thenReturn(RESPONSE); mockMvc.perform(get(BASE_URL + "/network-composite-modifications/network-modifications") .param("uuids", firstUuid.toString(), secondUuid.toString()) - .param("onlyMetadata", "false")) + .param("onlyMetadata", "false") + .header(HEADER_USER_ID, USER_ID)) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().json(RESPONSE)); - verify(networkModificationService).getNetworkModificationsFromComposite(List.of(firstUuid, secondUuid), false); + verify(networkModificationService).getNetworkModificationsFromComposite(List.of(firstUuid, secondUuid), false, USER_ID); } @Test void testGetNetworkModification() throws Exception { UUID modificationUuid = UUID.randomUUID(); - when(networkModificationService.getNetworkModification(modificationUuid)).thenReturn(RESPONSE); + when(networkModificationService.getNetworkModification(modificationUuid, USER_ID)).thenReturn(RESPONSE); - mockMvc.perform(get(BASE_URL + "/network-modifications/{uuid}", modificationUuid)) + mockMvc.perform(get(BASE_URL + "/network-modifications/{uuid}", modificationUuid).header(HEADER_USER_ID, USER_ID)) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().json(RESPONSE)); - verify(networkModificationService).getNetworkModification(modificationUuid); + verify(networkModificationService).getNetworkModification(modificationUuid, USER_ID); + } + + @Test + void testReadingAModificationWithoutUserIsRejected() throws Exception { + mockMvc.perform(get(BASE_URL + "/network-modifications/{uuid}", UUID.randomUUID())) + .andExpect(status().isBadRequest()); + + verifyNoInteractions(networkModificationService); } @Test diff --git a/src/test/java/org/gridsuite/study/server/service/NetworkModificationServiceTest.java b/src/test/java/org/gridsuite/study/server/service/NetworkModificationServiceTest.java index de5da3578..77833c40c 100644 --- a/src/test/java/org/gridsuite/study/server/service/NetworkModificationServiceTest.java +++ b/src/test/java/org/gridsuite/study/server/service/NetworkModificationServiceTest.java @@ -84,18 +84,18 @@ void testGetNetworkModificationsFromComposite() { UUID firstUuid = UUID.randomUUID(); UUID secondUuid = UUID.randomUUID(); String expectedUrl = NETWORK_MODIFICATION_SERVER_URI + "/v1/network-composite-modifications/network-modifications?uuids=" + firstUuid + "&uuids=" + secondUuid + "&onlyMetadata=false"; - when(restTemplate.getForObject(expectedUrl, String.class)).thenReturn(RESPONSE); + expectUserIdIsForwarded(expectedUrl); - assertThat(networkModificationService.getNetworkModificationsFromComposite(List.of(firstUuid, secondUuid), false)).isEqualTo(RESPONSE); + assertThat(networkModificationService.getNetworkModificationsFromComposite(List.of(firstUuid, secondUuid), false, USER_ID)).isEqualTo(RESPONSE); } @Test void testGetNetworkModification() { UUID modificationUuid = UUID.randomUUID(); String expectedUrl = NETWORK_MODIFICATION_SERVER_URI + "/v1/network-modifications/" + modificationUuid; - when(restTemplate.getForObject(expectedUrl, String.class)).thenReturn(RESPONSE); + expectUserIdIsForwarded(expectedUrl); - assertThat(networkModificationService.getNetworkModification(modificationUuid)).isEqualTo(RESPONSE); + assertThat(networkModificationService.getNetworkModification(modificationUuid, USER_ID)).isEqualTo(RESPONSE); } @Test @@ -266,4 +266,11 @@ void testHasModificationReferences() { networkModificationService.hasModificationReferences(List.of(modificationUuid)); verify(restTemplate).getForObject(eq(expectedUrl), eq(Boolean.class)); } + + private void expectUserIdIsForwarded(String expectedUrl) { + HttpHeaders headers = new HttpHeaders(); + headers.set(HEADER_USER_ID, USER_ID); + when(restTemplate.exchange(eq(expectedUrl), eq(HttpMethod.GET), eq(new HttpEntity<>(headers)), eq(String.class))) + .thenReturn(ResponseEntity.ok(RESPONSE)); + } }