Skip to content

Commit 7f6e8fe

Browse files
authored
Add managing directory permissions endpoints (#138)
Signed-off-by: achour94 <[email protected]>
1 parent c2a7949 commit 7f6e8fe

File tree

5 files changed

+153
-0
lines changed

5 files changed

+153
-0
lines changed

src/main/java/org/gridsuite/explore/server/ExploreController.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,4 +663,33 @@ public ResponseEntity<Void> hasRight(@PathVariable("directoryUuid") UUID directo
663663
return ResponseEntity.noContent().build();
664664
}
665665
}
666+
667+
@GetMapping(value = "/explore/directories/{directoryUuid}/permissions", produces = MediaType.APPLICATION_JSON_VALUE)
668+
@Operation(summary = "Get permissions for a directory")
669+
@ApiResponses(value = {
670+
@ApiResponse(responseCode = "200", description = "The permissions for the directory"),
671+
@ApiResponse(responseCode = "403", description = "Not authorized to view permissions for this directory"),
672+
@ApiResponse(responseCode = "404", description = "The directory was not found")
673+
})
674+
@PreAuthorize("@authorizationService.isAuthorized(#userId, #directoryUuid, null, T(org.gridsuite.explore.server.dto.PermissionType).READ)")
675+
public ResponseEntity<List<PermissionDTO>> getDirectoryPermissions(@PathVariable("directoryUuid") UUID directoryUuid,
676+
@RequestHeader(QUERY_PARAM_USER_ID) String userId) {
677+
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON)
678+
.body(directoryService.getDirectoryPermissions(directoryUuid, userId));
679+
}
680+
681+
@PutMapping(value = "/explore/directories/{directoryUuid}/permissions", consumes = MediaType.APPLICATION_JSON_VALUE)
682+
@Operation(summary = "Set permissions for a directory")
683+
@ApiResponses(value = {
684+
@ApiResponse(responseCode = "200", description = "Permissions were successfully updated"),
685+
@ApiResponse(responseCode = "403", description = "Not authorized to update permissions for this directory"),
686+
@ApiResponse(responseCode = "404", description = "The directory was not found")
687+
})
688+
@PreAuthorize("@authorizationService.isAuthorized(#userId, #directoryUuid, null, T(org.gridsuite.explore.server.dto.PermissionType).MANAGE)")
689+
public ResponseEntity<Void> setDirectoryPermissions(@PathVariable("directoryUuid") UUID directoryUuid,
690+
@RequestBody List<PermissionDTO> permissions,
691+
@RequestHeader(QUERY_PARAM_USER_ID) String userId) {
692+
directoryService.setDirectoryPermissions(directoryUuid, permissions, userId);
693+
return ResponseEntity.ok().build();
694+
}
666695
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.explore.server.dto;
8+
9+
import lombok.AllArgsConstructor;
10+
import lombok.Getter;
11+
import lombok.NoArgsConstructor;
12+
import lombok.Setter;
13+
14+
import java.util.List;
15+
import java.util.UUID;
16+
17+
/**
18+
* @author Achour BERRAHMA <achour.berrahma at rte-france.com>
19+
*/
20+
@Getter
21+
@Setter
22+
@NoArgsConstructor
23+
@AllArgsConstructor
24+
public class PermissionDTO {
25+
private boolean allUsers;
26+
private List<UUID> groups;
27+
private PermissionType type;
28+
}

src/main/java/org/gridsuite/explore/server/dto/PermissionType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@
1212
public enum PermissionType {
1313
READ,
1414
WRITE,
15+
MANAGE,
1516
}

src/main/java/org/gridsuite/explore/server/services/DirectoryService.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import org.gridsuite.explore.server.ExploreException;
1010
import org.gridsuite.explore.server.dto.ElementAttributes;
11+
import org.gridsuite.explore.server.dto.PermissionDTO;
1112
import org.gridsuite.explore.server.dto.PermissionType;
1213
import org.gridsuite.explore.server.utils.ParametersType;
1314
import org.springframework.core.ParameterizedTypeReference;
@@ -415,6 +416,42 @@ public boolean hasPermission(List<UUID> elementUuids, UUID targetDirectoryUuid,
415416
return !HttpStatus.NO_CONTENT.equals(response.getStatusCode());
416417
}
417418

419+
public List<PermissionDTO> getDirectoryPermissions(UUID directoryUuid, String userId) {
420+
String path = UriComponentsBuilder
421+
.fromPath(DIRECTORIES_SERVER_DIRECTORIES_ROOT_PATH + "/{directoryUuid}/permissions")
422+
.buildAndExpand(directoryUuid)
423+
.toUriString();
424+
425+
HttpHeaders headers = new HttpHeaders();
426+
headers.add(HEADER_USER_ID, userId);
427+
headers.setContentType(MediaType.APPLICATION_JSON);
428+
ResponseEntity<List<PermissionDTO>> response = restTemplate.exchange(
429+
directoryServerBaseUri + path,
430+
HttpMethod.GET,
431+
new HttpEntity<>(headers),
432+
new ParameterizedTypeReference<List<PermissionDTO>>() { }
433+
);
434+
435+
return response.getBody();
436+
}
437+
438+
public void setDirectoryPermissions(UUID directoryUuid, List<PermissionDTO> permissions, String userId) {
439+
String path = UriComponentsBuilder
440+
.fromPath(DIRECTORIES_SERVER_DIRECTORIES_ROOT_PATH + "/{directoryUuid}/permissions")
441+
.buildAndExpand(directoryUuid)
442+
.toUriString();
443+
444+
HttpHeaders headers = new HttpHeaders();
445+
headers.add(HEADER_USER_ID, userId);
446+
headers.setContentType(MediaType.APPLICATION_JSON);
447+
restTemplate.exchange(
448+
directoryServerBaseUri + path,
449+
HttpMethod.PUT,
450+
new HttpEntity<>(permissions, headers),
451+
Void.class
452+
);
453+
}
454+
418455
private void handleException(HttpStatusCodeException e) {
419456
if (HttpStatus.FORBIDDEN.equals(e.getStatusCode())) {
420457
throw new ExploreException(NOT_ALLOWED);

src/test/java/org/gridsuite/explore/server/ExploreTest.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import okio.Buffer;
2121
import org.gridsuite.explore.server.dto.CaseAlertThresholdMessage;
2222
import org.gridsuite.explore.server.dto.ElementAttributes;
23+
import org.gridsuite.explore.server.dto.PermissionDTO;
24+
import org.gridsuite.explore.server.dto.PermissionType;
2325
import org.gridsuite.explore.server.services.*;
2426
import org.gridsuite.explore.server.utils.ContingencyListType;
2527
import org.gridsuite.explore.server.utils.ParametersType;
@@ -205,6 +207,11 @@ void setup(final MockWebServer server) throws Exception {
205207
String newElementUuidAsString = mapper.writeValueAsString(ELEMENT_COPY_UUID);
206208
String newElementAttributesAsString = mapper.writeValueAsString(new ElementAttributes(ELEMENT_UUID, STUDY1, "STUDY", USER1, 0, null));
207209
String listElementsAsString = "[" + newElementAttributesAsString + "," + publicStudyAttributesAsString + "]";
210+
String parentDirectoryPermissions = mapper.writeValueAsString(List.of(
211+
new PermissionDTO(false, List.of(UUID.randomUUID(), UUID.randomUUID()), PermissionType.READ),
212+
new PermissionDTO(false, List.of(UUID.randomUUID()), PermissionType.WRITE),
213+
new PermissionDTO(false, List.of(), PermissionType.MANAGE)
214+
));
208215

209216
final Dispatcher dispatcher = new Dispatcher() {
210217
@SneakyThrows(JsonProcessingException.class)
@@ -381,6 +388,18 @@ public MockResponse dispatch(RecordedRequest request) {
381388
return new MockResponse(200, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), invalidElementAsString);
382389
} else if (path.matches("/v1/cases-alert-threshold")) {
383390
return new MockResponse(200, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), "40");
391+
} else if (path.matches("/v1/directories/" + PARENT_DIRECTORY_UUID + "/permissions")) {
392+
return new MockResponse(200, Headers.of(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE), parentDirectoryPermissions);
393+
} else if (path.matches("/v1/directories/" + PARENT_DIRECTORY_UUID_FORBIDDEN + "/permissions") &&
394+
USER_NOT_ALLOWED.equals(request.getHeaders().get("userId"))) {
395+
return new MockResponse(403);
396+
}
397+
} else if ("PUT".equals(request.getMethod())) {
398+
if (path.matches("/v1/directories/" + PARENT_DIRECTORY_UUID + "/permissions")) {
399+
return new MockResponse(200);
400+
} else if (path.matches("/v1/directories/" + PARENT_DIRECTORY_UUID_FORBIDDEN + "/permissions") &&
401+
USER_NOT_ALLOWED.equals(request.getHeaders().get("userId"))) {
402+
return new MockResponse(403);
384403
}
385404
} else if ("DELETE".equals(request.getMethod())) {
386405
if (path.matches("/v1/filters/" + FILTER_UUID)) {
@@ -945,6 +964,45 @@ void testModifyCompositeModifications(final MockWebServer server) throws Excepti
945964
).andExpect(status().isOk());
946965
}
947966

967+
@Test
968+
void testGetDirectoryPermissions() throws Exception {
969+
MvcResult result = mockMvc.perform(get("/v1/explore/directories/{directoryUuid}/permissions", PARENT_DIRECTORY_UUID)
970+
.header("userId", USER1))
971+
.andExpect(status().isOk())
972+
.andReturn();
973+
String responseJson = result.getResponse().getContentAsString();
974+
List<PermissionDTO> returnedPermissions = mapper.readValue(responseJson, new TypeReference<List<PermissionDTO>>() { });
975+
assertEquals(3, returnedPermissions.size());
976+
977+
// Execute the test with a forbidden directory ID
978+
mockMvc.perform(get("/v1/explore/directories/{directoryUuid}/permissions", PARENT_DIRECTORY_UUID_FORBIDDEN)
979+
.header("userId", USER_NOT_ALLOWED))
980+
.andExpect(status().isForbidden());
981+
}
982+
983+
@Test
984+
void testSetDirectoryPermissions() throws Exception {
985+
List<PermissionDTO> permissions = List.of(
986+
new PermissionDTO(false, List.of(UUID.randomUUID(), UUID.randomUUID()), PermissionType.READ),
987+
new PermissionDTO(false, List.of(UUID.randomUUID()), PermissionType.WRITE),
988+
new PermissionDTO(false, List.of(), PermissionType.MANAGE)
989+
);
990+
String permissionsJson = mapper.writeValueAsString(permissions);
991+
992+
mockMvc.perform(put("/v1/explore/directories/{directoryUuid}/permissions", PARENT_DIRECTORY_UUID)
993+
.header("userId", USER1)
994+
.contentType(MediaType.APPLICATION_JSON)
995+
.content(permissionsJson))
996+
.andExpect(status().isOk());
997+
998+
// Execute the test with a forbidden directory ID
999+
mockMvc.perform(put("/v1/explore/directories/{directoryUuid}/permissions", PARENT_DIRECTORY_UUID_FORBIDDEN)
1000+
.header("userId", USER_NOT_ALLOWED)
1001+
.contentType(MediaType.APPLICATION_JSON)
1002+
.content(permissionsJson))
1003+
.andExpect(status().isForbidden());
1004+
}
1005+
9481006
@Test
9491007
void testGetModificationMetadata() throws Exception {
9501008
final String expectedResult = mapper.writeValueAsString(new ElementAttributes(MODIFICATION_UUID, "one modif", "MODIFICATION", USER1, 0L, null, modificationSpecificMetadata));

0 commit comments

Comments
 (0)