Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -653,17 +653,17 @@ public ResponseEntity<String> searchElements(
.body(directoryService.searchElements(userInput, directoryUuid, userId));
}

@GetMapping(value = "/explore/elements/{elementUuid}")
@Operation(summary = "Check if user has a given right on a directory, or a single element by checking its parent")
@GetMapping(value = "/explore/elements/accessible", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Filter the given elements to the ones the user has the given permission on, "
+ "a directory being checked on itself and any other element on its parent directory")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "The user has the right on the element"),
@ApiResponse(responseCode = "204", description = "The user has not the right on the element"),
@ApiResponse(responseCode = "200", description = "The uuids of the given elements the user has that permission on"),
})
public ResponseEntity<Void> hasRight(@PathVariable("elementUuid") UUID elementUuid,
@RequestParam(name = "permission") PermissionType permission,
@RequestHeader(QUERY_PARAM_USER_ID) String userId) {
directoryService.checkPermission(List.of(elementUuid), null, userId, permission);
return ResponseEntity.ok().build();
public ResponseEntity<List<UUID>> getAccessibleElements(@RequestParam("ids") List<UUID> elementUuids,
@RequestParam(name = "accessType") PermissionType permissionType,
@RequestHeader(QUERY_PARAM_USER_ID) String userId) {
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON)
.body(directoryService.getAccessibleElements(elementUuids, userId, permissionType));
}

@GetMapping(value = "/explore/elements/{elementUuid}/referencing-element-infos", produces = MediaType.APPLICATION_JSON_VALUE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,26 @@ public void checkPermission(List<UUID> elementUuids, UUID targetDirectoryUuid, S
restTemplate.exchange(directoryServerBaseUri + path, HttpMethod.GET, new HttpEntity<>(headers), Void.class);
}

/** Tells which of the given elements the user may access. */
public List<UUID> getAccessibleElements(List<UUID> elementUuids, String userId, PermissionType permissionType) {
String ids = elementUuids.stream().map(UUID::toString).collect(Collectors.joining(","));
HttpHeaders headers = new HttpHeaders();
headers.add(HEADER_USER_ID, userId);

String path = UriComponentsBuilder.fromPath(ELEMENTS_SERVER_ROOT_PATH + "/accessible")
.queryParam(PARAM_ACCESS_TYPE, permissionType)
.queryParam(PARAM_IDS, ids)
.buildAndExpand()
.toUriString();

List<UUID> accessibleUuids = restTemplate
.exchange(directoryServerBaseUri + path, HttpMethod.GET, new HttpEntity<>(headers),
new ParameterizedTypeReference<List<UUID>>() {
})
.getBody();
return Objects.requireNonNullElse(accessibleUuids, Collections.emptyList());
}

public List<PermissionDTO> getDirectoryPermissions(UUID directoryUuid, String userId) {
String path = UriComponentsBuilder
.fromPath(DIRECTORIES_SERVER_DIRECTORIES_ROOT_PATH + "/{directoryUuid}/permissions")
Expand Down
67 changes: 30 additions & 37 deletions src/test/java/org/gridsuite/explore/server/ExploreTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -467,14 +467,6 @@ public MockResponse dispatch(RecordedRequest request) {
return new MockResponse(409);
} else if (path.matches("/v1/elements/authorized\\?forDeletion=true&ids=.*") || path.matches("/v1/elements\\?forUpdate=true&ids=.*")) {
return new MockResponse(200);
} else if (path.matches("/v1/elements/authorized\\?accessType=READ&ids=" + TEST_ACCESS_DIRECTORY_UUID_ALLOWED + "&targetDirectoryUuid&recursiveCheck=.*")) {
return new MockResponse(200);
} else if (path.matches("/v1/elements/authorized\\?accessType=READ&ids=" + TEST_ACCESS_DIRECTORY_UUID_FORBIDDEN + "&targetDirectoryUuid&recursiveCheck=.*")) {
return new MockResponse(403);
} else if (path.matches("/v1/elements/authorized\\?accessType=WRITE&ids=" + TEST_ACCESS_DIRECTORY_UUID_ALLOWED + "&targetDirectoryUuid&recursiveCheck=.*")) {
return new MockResponse(200);
} else if (path.matches("/v1/elements/authorized\\?accessType=WRITE&ids=" + TEST_ACCESS_DIRECTORY_UUID_FORBIDDEN + "&targetDirectoryUuid&recursiveCheck=.*")) {
return new MockResponse(403);
} else if (path.matches("/v1/elements/authorized\\?accessType=.*&ids=.*&targetDirectoryUuid.*&recursiveCheck=.*")) {
return new MockResponse(200);
}
Expand Down Expand Up @@ -1440,38 +1432,39 @@ void testSearchElement(final MockWebServer server) throws Exception {
}

@Test
void testHasRights(final MockWebServer server) throws Exception {
// test read access allowed
mockMvc.perform(head("/v1/explore/elements/" + TEST_ACCESS_DIRECTORY_UUID_ALLOWED + "?permission=READ")
.header("userId", NOT_ADMIN_USER)
).andExpect(status().isOk());

var requests = TestUtils.getRequestsWithBodyDone(1, server);
assertTrue(requests.stream().anyMatch(r -> r.getPath().contains("v1/elements/authorized?accessType=READ&ids=" + TEST_ACCESS_DIRECTORY_UUID_ALLOWED + "&targetDirectoryUuid")));

// test read access forbidden
mockMvc.perform(head("/v1/explore/elements/" + TEST_ACCESS_DIRECTORY_UUID_FORBIDDEN + "?permission=READ")
.header("userId", NOT_ADMIN_USER)
).andExpect(status().isForbidden());

requests = TestUtils.getRequestsWithBodyDone(1, server);
assertTrue(requests.stream().anyMatch(r -> r.getPath().contains("v1/elements/authorized?accessType=READ&ids=" + TEST_ACCESS_DIRECTORY_UUID_FORBIDDEN + "&targetDirectoryUuid")));

// test write access forbidden
mockMvc.perform(head("/v1/explore/elements/" + TEST_ACCESS_DIRECTORY_UUID_FORBIDDEN + "?permission=WRITE")
.header("userId", NOT_ADMIN_USER)
).andExpect(status().isForbidden());
@UsesWireMock
void testGetAccessibleElements() throws Exception {
wireMockServer.stubFor(WireMock.get(WireMock.urlPathEqualTo("/v1/elements/accessible"))
.withQueryParam("accessType", WireMock.equalTo("WRITE"))
.withQueryParam("ids", WireMock.equalTo(TEST_ACCESS_DIRECTORY_UUID_ALLOWED + "," + TEST_ACCESS_DIRECTORY_UUID_FORBIDDEN))
.willReturn(WireMock.ok()
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.withBody(mapper.writeValueAsString(List.of(TEST_ACCESS_DIRECTORY_UUID_ALLOWED)))));
wireMockServer.stubFor(WireMock.get(WireMock.urlPathEqualTo("/v1/elements/accessible"))
.withQueryParam("accessType", WireMock.equalTo("READ"))
.withQueryParam("ids", WireMock.equalTo(TEST_ACCESS_DIRECTORY_UUID_FORBIDDEN.toString()))
.willReturn(WireMock.ok()
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.withBody(mapper.writeValueAsString(List.of()))));

requests = TestUtils.getRequestsWithBodyDone(1, server);
assertTrue(requests.stream().anyMatch(r -> r.getPath().contains("v1/elements/authorized?accessType=WRITE&ids=" + TEST_ACCESS_DIRECTORY_UUID_FORBIDDEN + "&targetDirectoryUuid")));
// only the allowed one comes back
MvcResult result = mockMvc.perform(get("/v1/explore/elements/accessible"
+ "?ids=" + TEST_ACCESS_DIRECTORY_UUID_ALLOWED + "," + TEST_ACCESS_DIRECTORY_UUID_FORBIDDEN
+ "&accessType=WRITE")
.header("userId", NOT_ADMIN_USER)
).andExpect(status().isOk())
.andReturn();
assertEquals("[\"" + TEST_ACCESS_DIRECTORY_UUID_ALLOWED + "\"]", result.getResponse().getContentAsString());

// test write access allowed (admin)
mockMvc.perform(get("/v1/explore/elements/" + TEST_ACCESS_DIRECTORY_UUID_ALLOWED + "?permission=WRITE")
.header("userId", USER1)
).andExpect(status().isOk());
// a forbidden element alone answers an empty list
result = mockMvc.perform(get("/v1/explore/elements/accessible"
+ "?ids=" + TEST_ACCESS_DIRECTORY_UUID_FORBIDDEN + "&accessType=READ")
.header("userId", NOT_ADMIN_USER)
).andExpect(status().isOk())
.andReturn();
assertEquals("[]", result.getResponse().getContentAsString());

requests = TestUtils.getRequestsWithBodyDone(1, server);
assertTrue(requests.stream().anyMatch(r -> r.getPath().contains("v1/elements/authorized?accessType=WRITE&ids=" + TEST_ACCESS_DIRECTORY_UUID_ALLOWED + "&targetDirectoryUuid")));
wireMockServer.verify(2, WireMock.getRequestedFor(WireMock.urlPathEqualTo("/v1/elements/accessible")));
}

@Test
Expand Down
Loading