feat(comments): add CommentController and CreateCommentDTO (green)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-03-24 10:36:33 +01:00
parent ee49bac2ef
commit 3e5d296b09
2 changed files with 130 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
package org.raddatz.familienarchiv.controller;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.raddatz.familienarchiv.dto.CreateCommentDTO;
import org.raddatz.familienarchiv.model.AppUser;
import org.raddatz.familienarchiv.model.DocumentComment;
import org.raddatz.familienarchiv.security.Permission;
import org.raddatz.familienarchiv.security.RequirePermission;
import org.raddatz.familienarchiv.service.CommentService;
import org.raddatz.familienarchiv.service.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.UUID;
@RestController
@RequiredArgsConstructor
@Slf4j
public class CommentController {
private final CommentService commentService;
private final UserService userService;
// ─── General document comments ────────────────────────────────────────────
@GetMapping("/api/documents/{documentId}/comments")
public List<DocumentComment> getDocumentComments(@PathVariable UUID documentId) {
return commentService.getCommentsForDocument(documentId);
}
@PostMapping("/api/documents/{documentId}/comments")
@ResponseStatus(HttpStatus.CREATED)
@RequirePermission(Permission.ANNOTATE_ALL)
public DocumentComment postDocumentComment(
@PathVariable UUID documentId,
@RequestBody CreateCommentDTO dto,
Authentication authentication) {
AppUser author = resolveUser(authentication);
return commentService.postComment(documentId, null, dto.getContent(), author);
}
@PostMapping("/api/documents/{documentId}/comments/{commentId}/replies")
@ResponseStatus(HttpStatus.CREATED)
@RequirePermission(Permission.ANNOTATE_ALL)
public DocumentComment replyToDocumentComment(
@PathVariable UUID documentId,
@PathVariable UUID commentId,
@RequestBody CreateCommentDTO dto,
Authentication authentication) {
AppUser author = resolveUser(authentication);
return commentService.replyToComment(documentId, commentId, dto.getContent(), author);
}
// ─── Annotation comments ──────────────────────────────────────────────────
@GetMapping("/api/documents/{documentId}/annotations/{annotationId}/comments")
public List<DocumentComment> getAnnotationComments(@PathVariable UUID annotationId) {
return commentService.getCommentsForAnnotation(annotationId);
}
@PostMapping("/api/documents/{documentId}/annotations/{annotationId}/comments")
@ResponseStatus(HttpStatus.CREATED)
@RequirePermission(Permission.ANNOTATE_ALL)
public DocumentComment postAnnotationComment(
@PathVariable UUID documentId,
@PathVariable UUID annotationId,
@RequestBody CreateCommentDTO dto,
Authentication authentication) {
AppUser author = resolveUser(authentication);
return commentService.postComment(documentId, annotationId, dto.getContent(), author);
}
@PostMapping("/api/documents/{documentId}/annotations/{annotationId}/comments/{commentId}/replies")
@ResponseStatus(HttpStatus.CREATED)
@RequirePermission(Permission.ANNOTATE_ALL)
public DocumentComment replyToAnnotationComment(
@PathVariable UUID documentId,
@PathVariable UUID commentId,
@RequestBody CreateCommentDTO dto,
Authentication authentication) {
AppUser author = resolveUser(authentication);
return commentService.replyToComment(documentId, commentId, dto.getContent(), author);
}
// ─── Edit and delete (shared) ─────────────────────────────────────────────
@PatchMapping("/api/documents/{documentId}/comments/{commentId}")
@RequirePermission(Permission.ANNOTATE_ALL)
public DocumentComment editComment(
@PathVariable UUID documentId,
@PathVariable UUID commentId,
@RequestBody CreateCommentDTO dto,
Authentication authentication) {
AppUser currentUser = resolveUser(authentication);
return commentService.editComment(documentId, commentId, dto.getContent(), currentUser);
}
@DeleteMapping("/api/documents/{documentId}/comments/{commentId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteComment(
@PathVariable UUID documentId,
@PathVariable UUID commentId,
Authentication authentication) {
AppUser currentUser = resolveUser(authentication);
commentService.deleteComment(documentId, commentId, currentUser);
}
// ─── private helpers ──────────────────────────────────────────────────────
private AppUser resolveUser(Authentication authentication) {
if (authentication == null || !authentication.isAuthenticated()) return null;
try {
return userService.findByUsername(authentication.getName());
} catch (Exception e) {
log.warn("Could not resolve user for comment: {}", e.getMessage());
return null;
}
}
}

View File

@@ -0,0 +1,8 @@
package org.raddatz.familienarchiv.dto;
import lombok.Data;
@Data
public class CreateCommentDTO {
private String content;
}