fix(tracks): removing a track writes a track_remove audit row (#6294)
release / govulncheck (push) Successful in 17s
release / web (push) Successful in 1m21s
release / go (push) Successful in 1m39s
release / integration (push) Successful in 5m13s
release / android (push) Successful in 5m19s
release / Build signed APK (releases and dev) (push) Successful in 5m32s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 16s
release / Verify release artifacts (tag releases only) (push) Skipped

RemoveTrack took the admin's id and dropped it, so a merge left an
audit trail and the more destructive removal did not. It now reads the
track's title, artist, album and file path before the delete and writes
them, with whether the album and artist went too, under the new
track_remove action.

The audit action groups lose their plan-era U1/U2/U3 headings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-23 14:16:41 -04:00
co-authored by Claude Opus 5.5
parent 0d0b04bff0
commit 1aba1a41e6
3 changed files with 82 additions and 12 deletions
+12 -9
View File
@@ -20,14 +20,13 @@ import (
"git.fabledsword.com/bvandeusen/minstrel/internal/db/dbq"
)
// Action is the discriminator stored in audit_log.action. New values
// added in U2/U3 + future tasks; declare them here so callers don't
// stringly-type and so a future audit-search UI has a single source
// of truth for the vocabulary.
// Action is the discriminator stored in audit_log.action. Every value is
// declared here, so callers never stringly-type an action and the vocabulary
// has one source.
type Action string
const (
// U1
// Accounts and invites.
ActionRegister Action = "register"
ActionPromoteAdmin Action = "promote_admin"
ActionDemoteAdmin Action = "demote_admin"
@@ -35,15 +34,13 @@ const (
ActionInviteRedeem Action = "invite_redeem"
ActionInviteRevoke Action = "invite_revoke"
// U2 (declared early; callers in U1 don't use them yet, but
// having them here means U2's diff is purely additive on the
// caller side, not also touching this file).
// Admin user management.
ActionCreateUserAdmin Action = "create_user_admin"
ActionDeleteUser Action = "delete_user"
ActionPasswordResetAdmin Action = "password_reset_admin"
ActionAutoApproveToggle Action = "auto_approve_toggle"
// U3
// Credentials.
ActionPasswordChangeSelf Action = "password_change_self"
ActionTokenRegenerate Action = "token_regenerate"
ActionForgotPasswordInit Action = "forgot_password_initiated"
@@ -65,6 +62,12 @@ const (
ActionDuplicateDismiss Action = "duplicate_dismiss"
ActionDuplicateWrongFile Action = "duplicate_wrong_file"
// An admin removing a track: its file and row are deleted, with every
// like, play and playlist entry that hung off the row. The metadata names
// the track and its file, so the log can say what went after the row is
// gone.
ActionTrackRemove Action = "track_remove"
// Subsonic password: generated in Settings for t/s-only clients.
ActionSubsonicPasswordSet Action = "subsonic_password_set"
ActionSubsonicPasswordClear Action = "subsonic_password_clear"