diff --git a/backend/src/main/java/org/raddatz/familienarchiv/relationship/RelationshipController.java b/backend/src/main/java/org/raddatz/familienarchiv/relationship/RelationshipController.java new file mode 100644 index 00000000..1a94cc29 --- /dev/null +++ b/backend/src/main/java/org/raddatz/familienarchiv/relationship/RelationshipController.java @@ -0,0 +1,92 @@ +package org.raddatz.familienarchiv.relationship; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.raddatz.familienarchiv.model.Person; +import org.raddatz.familienarchiv.relationship.dto.CreateRelationshipRequest; +import org.raddatz.familienarchiv.relationship.dto.FamilyMemberPatchDTO; +import org.raddatz.familienarchiv.relationship.dto.InferredRelationshipDTO; +import org.raddatz.familienarchiv.relationship.dto.InferredRelationshipWithPersonDTO; +import org.raddatz.familienarchiv.relationship.dto.NetworkDTO; +import org.raddatz.familienarchiv.relationship.dto.RelationshipDTO; +import org.raddatz.familienarchiv.security.Permission; +import org.raddatz.familienarchiv.security.RequirePermission; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import java.util.List; +import java.util.UUID; + +/** + * Stammbaum API. Endpoints split across two roots: + * + */ +@RestController +@RequiredArgsConstructor +public class RelationshipController { + + private final RelationshipService relationshipService; + + @GetMapping("/api/network") + public NetworkDTO getNetwork() { + return relationshipService.getFamilyNetwork(); + } + + @GetMapping("/api/persons/{id}/relationships") + public List getRelationships(@PathVariable UUID id) { + return relationshipService.getRelationships(id); + } + + @GetMapping("/api/persons/{id}/inferred-relationships") + public List getInferredRelationships(@PathVariable UUID id) { + return relationshipService.getInferredRelationships(id); + } + + @GetMapping("/api/persons/{aId}/relationship-to/{bId}") + public InferredRelationshipDTO getRelationshipBetween(@PathVariable UUID aId, @PathVariable UUID bId) { + return relationshipService.getRelationshipBetween(aId, bId) + .orElseThrow(() -> new ResponseStatusException( + HttpStatus.NOT_FOUND, "No relationship path between " + aId + " and " + bId)); + } + + @PostMapping("/api/persons/{id}/relationships") + @RequirePermission(Permission.WRITE_ALL) + public ResponseEntity addRelationship( + @PathVariable UUID id, + @Valid @RequestBody CreateRelationshipRequest dto) { + validateRelationType(dto.relationType()); + return ResponseEntity.status(HttpStatus.CREATED) + .body(relationshipService.addRelationship(id, dto)); + } + + @DeleteMapping("/api/persons/{id}/relationships/{relId}") + @ResponseStatus(HttpStatus.NO_CONTENT) + @RequirePermission(Permission.WRITE_ALL) + public void deleteRelationship(@PathVariable UUID id, @PathVariable UUID relId) { + relationshipService.deleteRelationship(id, relId); + } + + @PatchMapping("/api/persons/{id}/family-member") + @RequirePermission(Permission.WRITE_ALL) + public Person patchFamilyMember(@PathVariable UUID id, @RequestBody FamilyMemberPatchDTO dto) { + return relationshipService.setFamilyMember(id, dto.familyMember()); + } + + private static void validateRelationType(String typeName) { + if (typeName == null || typeName.isBlank()) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "relationType is required"); + } + try { + RelationType.valueOf(typeName); + } catch (IllegalArgumentException e) { + throw new ResponseStatusException( + HttpStatus.BAD_REQUEST, "Unknown relationType: " + typeName); + } + } +} diff --git a/backend/src/main/java/org/raddatz/familienarchiv/relationship/dto/FamilyMemberPatchDTO.java b/backend/src/main/java/org/raddatz/familienarchiv/relationship/dto/FamilyMemberPatchDTO.java new file mode 100644 index 00000000..74d0bcb5 --- /dev/null +++ b/backend/src/main/java/org/raddatz/familienarchiv/relationship/dto/FamilyMemberPatchDTO.java @@ -0,0 +1,4 @@ +package org.raddatz.familienarchiv.relationship.dto; + +/** Body for {@code PATCH /api/persons/{id}/family-member}. */ +public record FamilyMemberPatchDTO(boolean familyMember) {}