From 5b2183677d279ed33c82eb34937eb431618bc7e0 Mon Sep 17 00:00:00 2001 From: joshua Date: Fri, 28 Aug 2026 14:48:17 +0200 Subject: [PATCH] Also log staff cancellations via PUT /api/registrations/:id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Registrations can be cancelled two ways: DELETE /:id (owner or admin, already logged registration_cancelled) and PUT /:id (staff+, status change endpoint) — the latter was silently unlogged. Since PUT /:id is staff-only, any transition into 'cancelled' there is inherently a staff-initiated cancellation, so it's now logged the same way. Audited all six categories promised in the 1.10.0 changelog entry (refunds, donation assign/unassign, manual registrations, staff-initiated cancellations, event create/update/delete, settings changes) against their actual logAdminAction call sites and route wiring — this was the only other gap found. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01CSWFWQsjTc9GyffPiXEDQT --- CHANGELOG.md | 1 + .../src/controllers/registrationController.js | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9be170b..a8cd13d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project follows [Semantic Versioning](https://semver.org/). ### Fixed - Creating an event was never recorded in the admin audit log — 1.10.0 added `event_created` as a logged action on the frontend's filter list, but the backend's `createEvent` never actually called `logAdminAction`, only `updateEvent`/`deleteEvent` did. Event creation is now logged the same way. +- Staff cancelling a registration via `PUT /api/registrations/:id` (the staff status-change endpoint, separate from the owner-facing `DELETE /:id` cancel route) wasn't logged at all — only the `DELETE` path logged `registration_cancelled`. Both paths now log it, verified against all six audit categories promised in 1.10.0 (refunds, donation assign/unassign, manual registrations, staff-initiated cancellations, event create/update/delete, settings changes) with no other gaps found. - Added a "Back to dashboard" link to Admin → Audit log, matching the back-link pattern already used on the Cashup page. ## [1.10.2] - 2026-08-28 diff --git a/backend/src/controllers/registrationController.js b/backend/src/controllers/registrationController.js index fafb112..3f22e84 100644 --- a/backend/src/controllers/registrationController.js +++ b/backend/src/controllers/registrationController.js @@ -626,6 +626,22 @@ const updateRegistrationStatus = async (req, res) => { } }); + // This is the staff-only status-change endpoint (separate from the owner-facing + // DELETE /:id cancel route), so any transition into 'cancelled' here is always a + // staff-initiated cancellation — log it the same way DELETE /:id does, so both + // paths land under the one 'registration_cancelled' filter in the audit log. + if (status === 'cancelled' && registration.status !== 'cancelled') { + logAdminAction({ + actorId: req.user.id, + actorRole: req.user.role, + action: 'registration_cancelled', + targetType: 'Registration', + targetId: req.params.id, + metadata: { registrationOwnerId: registration.userId, previousStatus: registration.status }, + ip: getClientIp(req), + }); + } + // Generate tickets and email them when status is manually set to 'paid' by staff if (status === 'paid') { (async () => {