From 1b4c93b4d38b26b0eaa2b246145a6951247998e3 Mon Sep 17 00:00:00 2001 From: Florent MILLOT <75525996+flomillot@users.noreply.github.com> Date: Thu, 24 Sep 2026 11:53:59 +0200 Subject: [PATCH 1/6] Carry the user to the network-modification server when reading modifications The network-modification server now answers, on each shared modification, the permission its reader holds on it, which it resolves against the directory. It needs to know who is reading: the three reads the study serves to the front-end carry the user along. A read of our own carries no user, and the voltage init modifications are read that way: they hold no shared modification for a permission to be resolved on. Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com> --- .../NetworkModificationController.java | 11 +++++--- .../server/controller/StudyController.java | 5 ++-- .../service/NetworkModificationService.java | 28 +++++++++++++++---- .../NetworkModificationTreeService.java | 4 +-- .../study/server/service/StudyService.java | 2 +- .../server/NetworkModificationTreeTest.java | 13 +++++---- .../NetworkModificationControllerTest.java | 24 ++++++++++++---- .../NetworkModificationServiceTest.java | 18 +++++++++--- 8 files changed, 74 insertions(+), 31 deletions(-) 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 ece979d6c..07bc27411 100644 --- a/src/main/java/org/gridsuite/study/server/controller/NetworkModificationController.java +++ b/src/main/java/org/gridsuite/study/server/controller/NetworkModificationController.java @@ -15,6 +15,8 @@ import java.util.List; import java.util.UUID; +import static org.gridsuite.study.server.StudyConstants.HEADER_USER_ID; + @RestController @RequestMapping(value = "/" + StudyApi.API_VERSION) public class NetworkModificationController { @@ -43,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 089a623b3..c1f98ad52 100644 --- a/src/main/java/org/gridsuite/study/server/controller/StudyController.java +++ b/src/main/java/org/gridsuite/study/server/controller/StudyController.java @@ -966,9 +966,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 3529d0b54..80004be54 100644 --- a/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java +++ b/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java @@ -107,17 +107,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) { @@ -145,7 +145,11 @@ 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, null for a read of our own: the network-modification + * server then answers no permission on the shared modifications, which it has no one to resolve them for + */ + 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) @@ -154,7 +158,19 @@ 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(); + } + + /** + * @return what carries the user to the network-modification server, nothing when there is no user to carry + */ + private static HttpEntity userIdEntity(String userId) { + if (userId == null) { + return null; + } + HttpHeaders headers = new HttpHeaders(); + headers.set(HEADER_USER_ID, userId); + return new HttpEntity<>(headers); } public String getModificationsToExport(UUID groupUUid) { 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 b915f096c..e7b4ef10f 100644 --- a/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java +++ b/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java @@ -813,8 +813,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 f026f373c..55980447b 100644 --- a/src/main/java/org/gridsuite/study/server/service/StudyService.java +++ b/src/main/java/org/gridsuite/study/server/service/StudyService.java @@ -2456,7 +2456,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 466cc6338..7fa56ba35 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; @@ -1538,17 +1539,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(); } @@ -1594,7 +1595,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, @@ -1617,11 +1618,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 1838dde26..e9333e76a 100644 --- a/src/test/java/org/gridsuite/study/server/controller/NetworkModificationControllerTest.java +++ b/src/test/java/org/gridsuite/study/server/controller/NetworkModificationControllerTest.java @@ -19,7 +19,9 @@ import java.util.List; import java.util.UUID; +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; @@ -31,6 +33,7 @@ class NetworkModificationControllerTest { private static final String BASE_URL = "/v1"; private static final String RESPONSE = "{\"name\":\"modification\"}"; + private static final String USER_ID = "userId"; @Mock private NetworkModificationService networkModificationService; @@ -88,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 be19d3d28..6fb213208 100644 --- a/src/test/java/org/gridsuite/study/server/service/NetworkModificationServiceTest.java +++ b/src/test/java/org/gridsuite/study/server/service/NetworkModificationServiceTest.java @@ -18,6 +18,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import java.util.List; @@ -25,6 +26,7 @@ import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; +import static org.gridsuite.study.server.StudyConstants.HEADER_USER_ID; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -35,6 +37,7 @@ class NetworkModificationServiceTest { private static final String NETWORK_MODIFICATION_SERVER_URI = "http://network-modification-server"; private static final String RESPONSE = "{\"id\":\"modification\"}"; + private static final String USER_ID = "userId"; @Mock private RemoteServicesProperties remoteServicesProperties; @@ -84,18 +87,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 @@ -196,4 +199,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)); + } } From 10496cb3a578bde545d713cfcffb9cd42fce15b4 Mon Sep 17 00:00:00 2001 From: Florent MILLOT <75525996+flomillot@users.noreply.github.com> Date: Thu, 24 Sep 2026 18:31:16 +0200 Subject: [PATCH 2/6] State the user parameter as a caller rule Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com> --- .../study/server/service/NetworkModificationService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 5e65e9ffb..5cc911a41 100644 --- a/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java +++ b/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java @@ -146,8 +146,7 @@ public void updateNetworkModificationsMetadata(List networkModificationUui } /** - * @param userId the user the modifications are read for, null for a read of our own: the network-modification - * server then answers no permission on the shared modifications, which it has no one to resolve them for + * @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); From 6e6caff434059932ce382f5e60bd4f1f74166951 Mon Sep 17 00:00:00 2001 From: Florent MILLOT <75525996+flomillot@users.noreply.github.com> Date: Fri, 2 Oct 2026 15:02:16 +0200 Subject: [PATCH 3/6] Remove the user id constant duplicated when merging main Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com> --- .../study/server/service/NetworkModificationServiceTest.java | 1 - 1 file changed, 1 deletion(-) 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 1e7f077c0..2ff955681 100644 --- a/src/test/java/org/gridsuite/study/server/service/NetworkModificationServiceTest.java +++ b/src/test/java/org/gridsuite/study/server/service/NetworkModificationServiceTest.java @@ -35,7 +35,6 @@ class NetworkModificationServiceTest { private static final String NETWORK_MODIFICATION_SERVER_URI = "http://network-modification-server"; private static final String USER_ID = "userId"; private static final String RESPONSE = "{\"id\":\"modification\"}"; - private static final String USER_ID = "userId"; @Mock private RemoteServicesProperties remoteServicesProperties; From 4795c19625fc98440161fccdc331bf9280f316cd Mon Sep 17 00:00:00 2001 From: Florent MILLOT <75525996+flomillot@users.noreply.github.com> Date: Fri, 2 Oct 2026 15:02:17 +0200 Subject: [PATCH 4/6] Carry the user through the same entity builder everywhere in the file Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com> --- .../service/NetworkModificationService.java | 32 +++++++------------ 1 file changed, 11 insertions(+), 21 deletions(-) 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 3844fd256..7393a18c6 100644 --- a/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java +++ b/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java @@ -158,16 +158,20 @@ public String getModifications(UUID groupUUid, boolean stashedModifications, boo return restTemplate.exchange(getNetworkModificationServerURI(false) + path, HttpMethod.GET, userIdEntity(userId), String.class).getBody(); } - /** - * @return what carries the user to the network-modification server, nothing when there is no user to carry - */ 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); - return new HttpEntity<>(headers); + if (body != null) { + headers.setContentType(MediaType.APPLICATION_JSON); + } + return new HttpEntity<>(body, headers); } public String getModificationsToExport(UUID groupUUid) { @@ -256,13 +260,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) { @@ -293,12 +291,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) { @@ -732,10 +725,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); } /** From ccb6499ee4ade383ba2961c927fa4a08b9e2f4bd Mon Sep 17 00:00:00 2001 From: Florent MILLOT <75525996+flomillot@users.noreply.github.com> Date: Fri, 2 Oct 2026 15:37:30 +0200 Subject: [PATCH 5/6] Move the user entity builders up with the other private helpers Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com> --- .../service/NetworkModificationService.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) 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 7393a18c6..aa9f16cef 100644 --- a/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java +++ b/src/main/java/org/gridsuite/study/server/service/NetworkModificationService.java @@ -87,6 +87,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); } @@ -158,22 +174,6 @@ public String getModifications(UUID groupUUid, boolean stashedModifications, boo return restTemplate.exchange(getNetworkModificationServerURI(false) + path, HttpMethod.GET, userIdEntity(userId), String.class).getBody(); } - 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 getModificationsToExport(UUID groupUUid) { Objects.requireNonNull(groupUUid); var path = UriComponentsBuilder.fromPath(GROUP_PATH + DELIMITER + NETWORK_MODIFICATIONS_PATH + DELIMITER + "export") From 39d7e048a43f94d2bd0c241b937361a83af704b8 Mon Sep 17 00:00:00 2001 From: Florent MILLOT <75525996+flomillot@users.noreply.github.com> Date: Fri, 2 Oct 2026 15:44:12 +0200 Subject: [PATCH 6/6] Remove the user id constant duplicated by the merge Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com> --- .../server/controller/NetworkModificationControllerTest.java | 1 - 1 file changed, 1 deletion(-) 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 61a55b61d..2856d571d 100644 --- a/src/test/java/org/gridsuite/study/server/controller/NetworkModificationControllerTest.java +++ b/src/test/java/org/gridsuite/study/server/controller/NetworkModificationControllerTest.java @@ -34,7 +34,6 @@ class NetworkModificationControllerTest { private static final String BASE_URL = "/v1"; private static final String USER_ID = "userId"; private static final String RESPONSE = "{\"name\":\"modification\"}"; - private static final String USER_ID = "userId"; @Mock private NetworkModificationService networkModificationService;