feat(person): require READ_ALL permission on GET /api/persons and /api/persons/{id}
Defense in depth: until now both list and single-person reads only required authentication, while the write endpoints (POST/PUT/DELETE) were already gated with @RequirePermission. The hover-card and typeahead introduced in issue #362 expose person details (life dates, notes, family relationships) to anyone who can authenticate — adding READ_ALL aligns the GETs with the write endpoints and matches the access tier already enforced for documents and transcription blocks. Two new controller-slice tests assert 403 when an authenticated user lacks READ_ALL; existing 200-path tests now stipulate `authorities = "READ_ALL"` explicitly. Refs #362 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -34,11 +34,13 @@ public class PersonController {
|
||||
private final DocumentService documentService;
|
||||
|
||||
@GetMapping
|
||||
@RequirePermission(Permission.READ_ALL)
|
||||
public ResponseEntity<List<PersonSummaryDTO>> getPersons(@RequestParam(required = false) String q) {
|
||||
return ResponseEntity.ok(personService.findAll(q));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@RequirePermission(Permission.READ_ALL)
|
||||
public Person getPerson(@PathVariable UUID id) {
|
||||
return personService.getById(id);
|
||||
}
|
||||
|
||||
@@ -57,6 +57,13 @@ class PersonControllerTest {
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
void getPersons_returns403_whenMissingReadAllPermission() throws Exception {
|
||||
mockMvc.perform(get("/api/persons"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = "READ_ALL")
|
||||
void getPersons_returns200_withEmptyList() throws Exception {
|
||||
when(personService.findAll(null)).thenReturn(Collections.emptyList());
|
||||
mockMvc.perform(get("/api/persons"))
|
||||
@@ -64,7 +71,7 @@ class PersonControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@WithMockUser(authorities = "READ_ALL")
|
||||
void getPersons_delegatesQueryParam_toService() throws Exception {
|
||||
PersonSummaryDTO dto = mockPersonSummary("Hans", "Müller");
|
||||
when(personService.findAll("Hans")).thenReturn(List.of(dto));
|
||||
@@ -100,6 +107,13 @@ class PersonControllerTest {
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
void getPerson_returns403_whenMissingReadAllPermission() throws Exception {
|
||||
mockMvc.perform(get("/api/persons/{id}", UUID.randomUUID()))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = "READ_ALL")
|
||||
void getPerson_returns200_whenFound() throws Exception {
|
||||
UUID id = UUID.randomUUID();
|
||||
Person person = Person.builder().id(id).firstName("Anna").lastName("Schmidt").build();
|
||||
|
||||
Reference in New Issue
Block a user