feat: display audit log on ticket details page#136
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
📝 WalkthroughWalkthroughController now accepts an AuditLogService, loads audit logs in the ticket details handler, and the ticket template was updated to render an Activity Log, adjust comments rendering, and change footer/navigation visibility based on status. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller as CaseController
participant CaseSvc as CaseService
participant CommentSvc as CommentService
participant AuditSvc as AuditLogService
participant View as Thymeleaf Template
Client->>Controller: GET /cases/{id}
Controller->>CaseSvc: fetch case by id
CaseSvc-->>Controller: case data
Controller->>CommentSvc: fetch comments for case
CommentSvc-->>Controller: comments
Controller->>AuditSvc: fetch audit logs for case
AuditSvc-->>Controller: auditLogs
Controller->>View: render "ticket" with model (case, comments, auditLogs)
View-->>Client: HTML page (ticket + comments + Activity Log)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/main/resources/templates/ticket.html (1)
39-40: AddgetDisplayName()method toAuditActionand format timestamps in user locale.
${entry.action}outputs the raw enum name (e.g.CASE_CREATED,CASE_STATUS_CHANGED). Add agetDisplayName()method toAuditActionsimilar toCaseStatus.getDisplayName()so the activity log reads naturally to users (e.g., "Case created", "Case status changed").
AuditLog.timestampis ajava.time.Instant. While#temporals.formatISOfromthymeleaf-extras-java8timedoes supportInstant, it formats using the system's default time zone, which may not match the user's locale. Consider formatting in the user's locale/zone (e.g.#temporals.format(entry.timestamp, 'yyyy-MM-dd HH:mm',#locale)after converting to aZonedDateTime).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/resources/templates/ticket.html` around lines 39 - 40, Add a human-friendly display method to the AuditAction enum (like CaseStatus.getDisplayName()) by implementing getDisplayName() that returns readable phrases (e.g., "Case created", "Case status changed"), then update the template to use that method/property instead of the raw enum (replace ${entry.action} with ${entry.action.displayName} or ${entry.action.getDisplayName()}); for timestamps, format the Instant in the user locale/zone by converting AuditLog.timestamp to a ZonedDateTime and using `#temporals.format` with a pattern and `#locale` (e.g., call `#temporals.format`(zonedTimestamp, 'yyyy-MM-dd HH:mm', `#locale`) — do the conversion either in the template or prepare a ZonedDateTime in the model before rendering).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/main/resources/templates/ticket.html`:
- Around line 47-48: The Close button is shown to non-owners and will 403 when
they click it; update the ownership check in the view: set an isOwner boolean in
CaseController.showTicketDetails (compute by comparing ticket.getOwner().getId()
to current user id) and include it in the model, then change the th:if on the
Close link in ticket.html to require both the status check and isOwner (or
alternatively use Spring Security sec:authorize with a model attribute). Ensure
CaseController.closeTicket behavior remains unchanged but the UI only renders
the Close anchor when model attribute isOwner is true and ticket.status is not
CLOSED or SOLVED.
---
Nitpick comments:
In `@src/main/resources/templates/ticket.html`:
- Around line 39-40: Add a human-friendly display method to the AuditAction enum
(like CaseStatus.getDisplayName()) by implementing getDisplayName() that returns
readable phrases (e.g., "Case created", "Case status changed"), then update the
template to use that method/property instead of the raw enum (replace
${entry.action} with ${entry.action.displayName} or
${entry.action.getDisplayName()}); for timestamps, format the Instant in the
user locale/zone by converting AuditLog.timestamp to a ZonedDateTime and using
`#temporals.format` with a pattern and `#locale` (e.g., call
`#temporals.format`(zonedTimestamp, 'yyyy-MM-dd HH:mm', `#locale`) — do the
conversion either in the template or prepare a ZonedDateTime in the model before
rendering).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 022c29fc-3900-4f90-aee7-18ce1e9271d7
📒 Files selected for processing (2)
src/main/java/org/example/untitled/usercase/controller/CaseController.javasrc/main/resources/templates/ticket.html
| <a th:if="${ticket.status.name() != 'CLOSED' and ticket.status.name() != 'SOLVED'}" | ||
| th:href="@{/tickets/{id}/close(id=${ticket.id})}" class="btn btn-danger">Close</a> |
There was a problem hiding this comment.
Close button shown to non-owners will 403.
The visibility predicate only checks status, but CaseController.closeTicket (lines 118–131) throws 403 FORBIDDEN for anyone who is not the ticket owner. A HANDLER/SUPERVISOR/ADMIN viewing a ticket they don't own will see this "Close" button and get an error page when clicking it.
Consider also gating it on ownership, e.g. by exposing an isOwner flag from the controller or using Spring Security's sec:authorize together with a model attribute:
Proposed fix
In CaseController.showTicketDetails:
+ boolean isOwner = !caseService.isNotOwner(ticket, userDetails.getUsername());
model.addAttribute("ticket", ticket);
model.addAttribute("comments", comments);
model.addAttribute("auditLogs", auditLogs);
+ model.addAttribute("isOwner", isOwner);In ticket.html:
- <a th:if="${ticket.status.name() != 'CLOSED' and ticket.status.name() != 'SOLVED'}"
- th:href="@{/tickets/{id}/close(id=${ticket.id})}" class="btn btn-danger">Close</a>
+ <a th:if="${isOwner and ticket.status.name() != 'CLOSED' and ticket.status.name() != 'SOLVED'}"
+ th:href="@{/tickets/{id}/close(id=${ticket.id})}" class="btn btn-danger">Close</a>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/resources/templates/ticket.html` around lines 47 - 48, The Close
button is shown to non-owners and will 403 when they click it; update the
ownership check in the view: set an isOwner boolean in
CaseController.showTicketDetails (compute by comparing ticket.getOwner().getId()
to current user id) and include it in the model, then change the th:if on the
Close link in ticket.html to require both the status check and isOwner (or
alternatively use Spring Security sec:authorize with a model attribute). Ensure
CaseController.closeTicket behavior remains unchanged but the UI only renders
the Close anchor when model attribute isOwner is true and ticket.status is not
CLOSED or SOLVED.
Summary by CodeRabbit
New Features
Improvements