mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
feat(audit): route every LogAudit call through a best-effort WriteAudit helper
Audit writes stay best-effort — a LogAudit failure must never fail or abort the request — but a failed write must no longer be silently discarded. Add db.WriteAudit(auditor, actor, action, targetType, targetID, detail), which logs a failed write with actor/action/target context (never the detail string, which may be sensitive) and never propagates the error. The Auditor interface is satisfied structurally by both *db.DB and the service-layer Store, so api/admin/ws/service all reach the helper without an import cycle. Converts all ~26 call sites from `_ = LogAudit(...)` (and the two backup handlers' inline `if err` blocks) to db.WriteAudit. Pinned by db/audit_test.go: failure logged and not propagated, success logs nothing, detail never leaks. Resolves the repo-wide LogAudit policy question flagged by the D8 note. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -52,10 +52,8 @@ func handleBackup(database *db.DB) http.Handler {
|
||||
actor := actorFromContext(r)
|
||||
backupName := filepath.Base(backupPath)
|
||||
slog.Info("database backup created", "actor_id", actor, "name", backupName)
|
||||
if err := database.LogAudit(actor, "backup_create", "server", 0,
|
||||
fmt.Sprintf("backup saved: %s", backupName)); err != nil {
|
||||
slog.Error("audit log write failed", "action", "backup_create", "actor_id", actor, "error", err)
|
||||
}
|
||||
db.WriteAudit(database, actor, "backup_create", "server", 0,
|
||||
fmt.Sprintf("backup saved: %s", backupName))
|
||||
|
||||
writeJSON(w, http.StatusOK, map[string]string{
|
||||
"path": filepath.Base(backupPath),
|
||||
@@ -138,9 +136,7 @@ func handleDeleteBackup(database *db.DB) http.Handler {
|
||||
|
||||
actor := actorFromContext(r)
|
||||
slog.Info("backup deleted", "actor_id", actor, "name", name)
|
||||
if err := database.LogAudit(actor, "backup_delete", "server", 0, "deleted backup "+name); err != nil {
|
||||
slog.Error("audit log write failed", "action", "backup_delete", "actor_id", actor, "error", err)
|
||||
}
|
||||
db.WriteAudit(database, actor, "backup_delete", "server", 0, "deleted backup "+name)
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
|
||||
@@ -108,7 +108,7 @@ func handlePutChannelPermission(database *db.DB, hub HubBroadcaster, permInvalid
|
||||
actor := actorFromContext(r)
|
||||
slog.Info("channel permissions updated", "actor_id", actor, "channel_id", ch.ID,
|
||||
"role_id", roleID, "allow", allow, "deny", deny)
|
||||
_ = database.LogAudit(actor, "channel_perms_update", "channel", ch.ID,
|
||||
db.WriteAudit(database, actor, "channel_perms_update", "channel", ch.ID,
|
||||
fmt.Sprintf("set overrides for role %s on #%s (allow=%#x deny=%#x)", role.Name, ch.Name, allow, deny))
|
||||
|
||||
if permInvalidator != nil {
|
||||
@@ -147,7 +147,7 @@ func handleDeleteChannelPermission(database *db.DB, hub HubBroadcaster, permInva
|
||||
|
||||
actor := actorFromContext(r)
|
||||
slog.Info("channel permissions cleared", "actor_id", actor, "channel_id", ch.ID, "role_id", roleID)
|
||||
_ = database.LogAudit(actor, "channel_perms_clear", "channel", ch.ID,
|
||||
db.WriteAudit(database, actor, "channel_perms_clear", "channel", ch.ID,
|
||||
fmt.Sprintf("cleared overrides for role %d on #%s", roleID, ch.Name))
|
||||
|
||||
if permInvalidator != nil {
|
||||
|
||||
@@ -115,7 +115,7 @@ func handleCreateChannel(database *db.DB, hub HubBroadcaster) http.HandlerFunc {
|
||||
}
|
||||
actor := actorFromContext(r)
|
||||
slog.Info("channel created", "actor_id", actor, "channel", req.Name, "type", req.Type)
|
||||
_ = database.LogAudit(actor, "channel_create", "channel", id,
|
||||
db.WriteAudit(database, actor, "channel_create", "channel", id,
|
||||
fmt.Sprintf("created #%s (%s)", req.Name, req.Type))
|
||||
if hub != nil {
|
||||
hub.BroadcastChannelCreate(ch)
|
||||
@@ -171,7 +171,7 @@ func handlePatchChannel(database *db.DB, hub HubBroadcaster) http.HandlerFunc {
|
||||
|
||||
actor := actorFromContext(r)
|
||||
slog.Info("channel updated", "actor_id", actor, "channel_id", id, "name", req.Name)
|
||||
_ = database.LogAudit(actor, "channel_update", "channel", id,
|
||||
db.WriteAudit(database, actor, "channel_update", "channel", id,
|
||||
fmt.Sprintf("updated #%s", req.Name))
|
||||
|
||||
updated, err := database.GetChannel(id)
|
||||
@@ -210,7 +210,7 @@ func handleDeleteChannel(database *db.DB, hub HubBroadcaster) http.HandlerFunc {
|
||||
}
|
||||
actor := actorFromContext(r)
|
||||
slog.Warn("channel deleted", "actor_id", actor, "channel_id", id, "name", existing.Name)
|
||||
_ = database.LogAudit(actor, "channel_delete", "channel", id,
|
||||
db.WriteAudit(database, actor, "channel_delete", "channel", id,
|
||||
fmt.Sprintf("deleted #%s", existing.Name))
|
||||
if hub != nil {
|
||||
hub.BroadcastChannelDelete(id)
|
||||
|
||||
@@ -79,7 +79,7 @@ func handlePatchSettings(database *db.DB) http.HandlerFunc {
|
||||
}
|
||||
for key := range normalizedUpdates {
|
||||
slog.Info("setting changed", "actor_id", actor, "key", key)
|
||||
_ = database.LogAudit(actor, "setting_change", "setting", 0,
|
||||
db.WriteAudit(database, actor, "setting_change", "setting", 0,
|
||||
fmt.Sprintf("%s updated", key))
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ func handlePatchUser(database *db.DB, hub HubBroadcaster, permInvalidator Permis
|
||||
if permInvalidator != nil {
|
||||
permInvalidator.InvalidateUser(id)
|
||||
}
|
||||
_ = database.LogAudit(actor, "role_change", "user", id,
|
||||
db.WriteAudit(database, actor, "role_change", "user", id,
|
||||
fmt.Sprintf("changed %s role to %d", user.Username, *req.RoleID))
|
||||
if role, err := database.GetRoleByID(*req.RoleID); err == nil && role != nil {
|
||||
if hub != nil {
|
||||
@@ -171,7 +171,7 @@ func handleForceLogout(database *db.DB) http.HandlerFunc {
|
||||
}
|
||||
actor := actorFromContext(r)
|
||||
slog.Info("force logout", "actor_id", actor, "target_user_id", id)
|
||||
_ = database.LogAudit(actor, "force_logout", "user", id, "all sessions terminated")
|
||||
db.WriteAudit(database, actor, "force_logout", "user", id, "all sessions terminated")
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ func handleSetup(database *db.DB, limiter *auth.RateLimiter, allowedOrigins []st
|
||||
}
|
||||
|
||||
slog.Info("server setup completed", "owner", req.Username, "user_id", uid)
|
||||
_ = database.LogAudit(uid, "server_setup", "server", 0,
|
||||
db.WriteAudit(database, uid, "server_setup", "server", 0,
|
||||
"initial setup: owner account created, default channel and invite generated")
|
||||
|
||||
writeJSON(w, http.StatusCreated, setupResponse{
|
||||
|
||||
Reference in New Issue
Block a user