feat(api): add GET/POST/DELETE /api/persons/{id}/aliases endpoints
GET returns aliases (no permission required), POST requires WRITE_ALL, DELETE requires WRITE_ALL. 5 new controller tests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,10 +5,12 @@ import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
import org.raddatz.familienarchiv.dto.PersonNameAliasDTO;
|
||||
import org.raddatz.familienarchiv.dto.PersonSummaryDTO;
|
||||
import org.raddatz.familienarchiv.dto.PersonUpdateDTO;
|
||||
import org.raddatz.familienarchiv.model.Document;
|
||||
import org.raddatz.familienarchiv.model.Person;
|
||||
import org.raddatz.familienarchiv.model.PersonNameAlias;
|
||||
import org.raddatz.familienarchiv.security.Permission;
|
||||
import org.raddatz.familienarchiv.security.RequirePermission;
|
||||
import org.raddatz.familienarchiv.service.DocumentService;
|
||||
@@ -92,4 +94,24 @@ public class PersonController {
|
||||
}
|
||||
personService.mergePersons(id, UUID.fromString(targetIdStr));
|
||||
}
|
||||
|
||||
// ─── Alias endpoints ────────────────────────────────────────────────────
|
||||
|
||||
@GetMapping("/{id}/aliases")
|
||||
public List<PersonNameAlias> getAliases(@PathVariable UUID id) {
|
||||
return personService.getAliases(id);
|
||||
}
|
||||
|
||||
@PostMapping("/{id}/aliases")
|
||||
@RequirePermission(Permission.WRITE_ALL)
|
||||
public PersonNameAlias addAlias(@PathVariable UUID id, @RequestBody PersonNameAliasDTO dto) {
|
||||
return personService.addAlias(id, dto);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}/aliases/{aliasId}")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
@RequirePermission(Permission.WRITE_ALL)
|
||||
public void removeAlias(@PathVariable UUID id, @PathVariable UUID aliasId) {
|
||||
personService.removeAlias(id, aliasId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package org.raddatz.familienarchiv.controller;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.raddatz.familienarchiv.model.Document;
|
||||
import org.raddatz.familienarchiv.model.Person;
|
||||
import org.raddatz.familienarchiv.model.PersonNameAlias;
|
||||
import org.raddatz.familienarchiv.model.PersonNameAliasType;
|
||||
import org.raddatz.familienarchiv.security.PermissionAspect;
|
||||
import org.raddatz.familienarchiv.service.CustomUserDetailsService;
|
||||
import org.raddatz.familienarchiv.service.DocumentService;
|
||||
@@ -25,6 +27,7 @@ import org.raddatz.familienarchiv.dto.PersonSummaryDTO;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
@@ -393,4 +396,66 @@ class PersonControllerTest {
|
||||
.content("{\"targetPersonId\":\"" + UUID.randomUUID() + "\"}"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
// ─── GET /api/persons/{id}/aliases ────────────────────────────────────────
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
void getAliases_returns200_withList() throws Exception {
|
||||
UUID personId = UUID.randomUUID();
|
||||
PersonNameAlias alias = PersonNameAlias.builder()
|
||||
.id(UUID.randomUUID()).lastName("de Gruyter").type(PersonNameAliasType.BIRTH).sortOrder(0).build();
|
||||
when(personService.getAliases(personId)).thenReturn(List.of(alias));
|
||||
|
||||
mockMvc.perform(get("/api/persons/{id}/aliases", personId))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$[0].lastName").value("de Gruyter"));
|
||||
}
|
||||
|
||||
// ─── POST /api/persons/{id}/aliases ──────────────────────────────────────
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = "WRITE_ALL")
|
||||
void addAlias_returns200_whenValid() throws Exception {
|
||||
UUID personId = UUID.randomUUID();
|
||||
PersonNameAlias saved = PersonNameAlias.builder()
|
||||
.id(UUID.randomUUID()).lastName("de Gruyter").type(PersonNameAliasType.BIRTH).sortOrder(0).build();
|
||||
when(personService.addAlias(eq(personId), any())).thenReturn(saved);
|
||||
|
||||
mockMvc.perform(post("/api/persons/{id}/aliases", personId)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"lastName\":\"de Gruyter\",\"type\":\"BIRTH\"}"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.lastName").value("de Gruyter"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = "READ_ALL")
|
||||
void addAlias_returns403_withoutWritePermission() throws Exception {
|
||||
mockMvc.perform(post("/api/persons/{id}/aliases", UUID.randomUUID())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"lastName\":\"de Gruyter\",\"type\":\"BIRTH\"}"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
// ─── DELETE /api/persons/{id}/aliases/{aliasId} ──────────────────────────
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = "WRITE_ALL")
|
||||
void removeAlias_returns204_whenValid() throws Exception {
|
||||
UUID personId = UUID.randomUUID();
|
||||
UUID aliasId = UUID.randomUUID();
|
||||
|
||||
mockMvc.perform(delete("/api/persons/{id}/aliases/{aliasId}", personId, aliasId))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
verify(personService).removeAlias(personId, aliasId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = "READ_ALL")
|
||||
void removeAlias_returns403_withoutWritePermission() throws Exception {
|
||||
mockMvc.perform(delete("/api/persons/{id}/aliases/{aliasId}", UUID.randomUUID(), UUID.randomUUID()))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user