diff --git a/src/main/java/org/example/alfs/controllers/TicketCommentController.java b/src/main/java/org/example/alfs/controllers/TicketCommentController.java index 57a2ade..03f0b7a 100644 --- a/src/main/java/org/example/alfs/controllers/TicketCommentController.java +++ b/src/main/java/org/example/alfs/controllers/TicketCommentController.java @@ -9,6 +9,8 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.List; @Controller @@ -27,22 +29,28 @@ public TicketCommentController(TicketCommentService commentService, @PostMapping("/{ticketId}/comments") public String addComment( @PathVariable Long ticketId, - @Valid @ModelAttribute CommentCreateDTO dto + @Valid @ModelAttribute CommentCreateDTO dto, + @RequestParam(required = false) String token ) { - User user = getCurrentUserOrNull(); // unauthenticated users currently have no access; anonymous flow will be added later. + User user = getCurrentUserOrNull(); - commentService.addComment(ticketId, dto, user); + commentService.addComment(ticketId, dto, user, token); - return "redirect:/view/id/" + ticketId; + String base = "redirect:/view/id/" + ticketId; + return token != null + ? base + "?token=" + URLEncoder.encode(token, StandardCharsets.UTF_8) + : base; } @GetMapping("/{ticketId}/comments") @ResponseBody - public List getComments(@PathVariable Long ticketId) { - + public List getComments( + @PathVariable Long ticketId, + @RequestParam(required = false) String token + ) { User user = getCurrentUserOrNull(); - return commentService.getComments(ticketId, user); + return commentService.getComments(ticketId, user, token); } private User getCurrentUserOrNull() { diff --git a/src/main/java/org/example/alfs/services/TicketCommentService.java b/src/main/java/org/example/alfs/services/TicketCommentService.java index 8f98ee1..1cc1c95 100644 --- a/src/main/java/org/example/alfs/services/TicketCommentService.java +++ b/src/main/java/org/example/alfs/services/TicketCommentService.java @@ -32,13 +32,13 @@ public TicketCommentService(TicketRepository ticketRepository, } @Transactional - public CommentViewDTO addComment(Long ticketId, CommentCreateDTO dto, User author) { + public CommentViewDTO addComment(Long ticketId, CommentCreateDTO dto, User author, String token) { Ticket ticket = ticketRepository.findById(ticketId) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Ticket not found")); boolean internalNote = dto.isInternalNote(); - checkAccess(ticket, author); + checkAccess(ticket, author, token); checkInternalNotePermission(internalNote, author); TicketComment comment = new TicketComment(); @@ -52,16 +52,17 @@ public CommentViewDTO addComment(Long ticketId, CommentCreateDTO dto, User autho } @Transactional(readOnly = true) - public List getComments(Long ticketId, User actor) { + public List getComments(Long ticketId, User user, String token) { Ticket ticket = ticketRepository.findById(ticketId) .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Ticket not found")); - checkAccess(ticket, actor); + checkAccess(ticket, user, token); - boolean isReporter = actor.getRole() == Role.REPORTER; + boolean isReporter = user != null && user.getRole() == Role.REPORTER; + boolean isAnonymous = user == null; - List all = isReporter + List all = (isReporter || isAnonymous) ? ticketCommentRepository.findByTicketIdAndInternalNoteFalseOrderByCreatedAtAsc(ticketId) : ticketCommentRepository.findByTicketIdOrderByCreatedAtAsc(ticketId); @@ -71,32 +72,31 @@ public List getComments(Long ticketId, User actor) { } // helpers - private void checkAccess(Ticket ticket, User user) { + private void checkAccess(Ticket ticket, User user, String token) { + // Authenticated + if (user != null) { + if (user.getRole() == Role.ADMIN) return; - // If no user (anonymous) → deny access for now. Will be fixed later. - if (user == null) { - throw new ResponseStatusException( - HttpStatus.UNAUTHORIZED, "Authentication required"); - } - - if (user.getRole() == Role.ADMIN) return; - - if (user.getRole() == Role.INVESTIGATOR) { - if (ticket.getInvestigator() != null && + if (user.getRole() == Role.INVESTIGATOR && + ticket.getInvestigator() != null && ticket.getInvestigator().getId().equals(user.getId())) { return; } - } - if (user.getRole() == Role.REPORTER) { - if (ticket.getReporter() != null && + if (user.getRole() == Role.REPORTER && + ticket.getReporter() != null && ticket.getReporter().getId().equals(user.getId())) { return; } } - throw new ResponseStatusException( - HttpStatus.FORBIDDEN, "Access denied"); + // Anonymous + if (token != null && !token.isBlank() + && token.equals(ticket.getReporterToken())) { + return; + } + + throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Access denied"); } private void checkInternalNotePermission(boolean internalNote, User author) {