Repository navigation
fix: guest ticket JSON loops and leaks internal notes - #98
Merged
Merged
Conversation
Reply.ticket, TicketActivity.ticket and the other child-to-parent links serialised back into the ticket, so any endpoint returning a Ticket nested until Jackson gave up and sent truncated JSON under a 200. Mark the back-references @JsonIgnore, as Attachment and WorkflowLog already do. This covers the admin and agent ticket lists and show views, agent reply lists and the department endpoints.
The guest and widget token endpoints returned the Ticket and Reply entities. With the serialisation loop fixed, that hands a guest every internal note, the activity log and staff details. They now return GuestTicketDto and GuestReplyDto with public replies only, and the reply lists query public replies instead of all of them.
# Conflicts: # src/main/java/dev/escalated/controllers/widget/GuestAccessController.java # src/main/java/dev/escalated/controllers/widget/WidgetController.java
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Any endpoint that returned the
Ticketentity serialised it through child-to-parent back-references (Reply.ticket,TicketActivity.ticket, ...). The JSON nested until Jackson gave up, so the client got about 45 KB of truncated JSON it couldn't parse, under a 200.This also hid a security bug. The guest token endpoints returned the whole entity graph: every reply including internal notes, the activity log, the assigned agent's email, SLA data and so on. The truncation happened to cut the response off before the internal note. The guest reply lists (
GET .../tickets/{token}/replies) queried all replies. I checked this directly: with only the loop fixed and the old controllers, the new tests fail because the guest response contains the internal note, and the reply list holds 2 entries instead of 1.Fix
TicketDetailDto), so these follow that pattern.GET /escalated/api/{guest,widget}/tickets/{token}returnsGuestTicketDto:id, reference, subject, description, status, priority, channel, department{name}, requester_name, created_at, updated_at, resolved_at, closed_at, attachments, replies. Replies are public only, andattachmentsholds only the files filed on the ticket itself.GET .../tickets/{token}/repliesreturnsList<GuestReplyDto>with public replies only, usingfindByTicketIdAndInternalFalseOrderByCreatedAtAsc.POST .../tickets/{token}/repliesreturns aGuestReplyDto:id, body, author_name, author_type, is_agent, created_at, attachments.findGuestViewandfindGuestRepliesbuild the DTOs inside a read-only transaction.@JsonIgnore.AttachmentandWorkflowLogalready use this pattern. The new ones areReply.ticket,TicketActivity.ticket,CustomFieldValue.ticket,SatisfactionRating.ticket,SideConversation.ticket,SideConversationReply.sideConversation,TicketLink.sourceTicket/targetTicket,TicketSubjectLink.ticket,EscalationRule.slaPolicy,Tag.tickets,Department.tickets/agentsandAgentProfile.assignedTickets.Departmentwithticketsandagents.agents_countandtickets_count, and related tickets come fromTicketDetailDto.related_tickets.Field set compared
{ ticket, replies }, whereticketis the entity's columns andrepliescomes fromfindByTicketId(id, false), i.e. public replies with attachments.Guest/Show.vuereadssubject, reference, status, priority, department.name, satisfaction_rating, description, attachments, replies.guestAccessToken,assigneeId,requesterIdand SLA fields, because a guest has no use for them.satisfaction_rating. This port has no single-rating field to expose.Tests
TicketJsonShapeTestboots the host on a random port and sends real HTTP requests, with no stubs. The seeded ticket has an assigned admin, a tag, a public reply and an internal note.activitiesorguestAccessToken. JSON depth is bounded.WidgetControllerTest.getTicketByToken_shouldReturnTicketnow stubsfindGuestView.Results
./gradlew test(H2): 379 tests, 0 failures, 0 errors, 9 skipped (the skips were already there)./gradlew checkstyleMain checkstyleTest: BUILD SUCCESSFUL, with no warnings in the touched filesNotes
EntityNotFoundException, so fix: answer unknown guest tokens with 403 instead of an error page #97's 403 handling applies unchanged.name/emailfrom the request body. A guest can therefore set any author email on a reply, and omittingemailgives a NOT NULL error. That needs its own fix: use the ticket's requester.