feat(security): audit-log session termination (single + all-others)
The two session-revocation endpoints wrote no audit entry. Added a 'session' EntityType (+ Czech label 'Relace') and logAudit on both deletes, so revoking sessions is recorded in the forensic trail. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -36,4 +36,5 @@ export const ENTITY_TYPE_LABELS: Record<string, string> = {
|
||||
work_plan_entry: "Plán prací – záznam",
|
||||
work_plan_override: "Plán prací – přepsání dne",
|
||||
plan_category: "Plán prací – kategorie",
|
||||
session: "Relace",
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import prisma from "../../config/database";
|
||||
import { requireAuth } from "../../middleware/auth";
|
||||
import { success, error, parseId } from "../../utils/response";
|
||||
import { hashToken } from "../../services/auth";
|
||||
import { logAudit } from "../../services/audit";
|
||||
|
||||
/** Parse user-agent string into browser, OS, and device icon */
|
||||
function parseUserAgent(ua: string | null): {
|
||||
@@ -94,6 +95,14 @@ export default async function sessionsRoutes(
|
||||
where: { id },
|
||||
data: { replaced_at: new Date() },
|
||||
});
|
||||
await logAudit({
|
||||
request,
|
||||
authData,
|
||||
action: "delete",
|
||||
entityType: "session",
|
||||
entityId: id,
|
||||
description: `Ukončena relace #${id} (${session.ip_address ?? "?"})`,
|
||||
});
|
||||
return success(reply, null, 200, "Relace ukončena");
|
||||
},
|
||||
);
|
||||
@@ -112,7 +121,7 @@ export default async function sessionsRoutes(
|
||||
return error(reply, "Nelze identifikovat aktuální relaci", 400);
|
||||
}
|
||||
|
||||
await prisma.refresh_tokens.updateMany({
|
||||
const terminated = await prisma.refresh_tokens.updateMany({
|
||||
where: {
|
||||
user_id: authData.userId,
|
||||
replaced_at: null,
|
||||
@@ -120,6 +129,13 @@ export default async function sessionsRoutes(
|
||||
},
|
||||
data: { replaced_at: new Date() },
|
||||
});
|
||||
await logAudit({
|
||||
request,
|
||||
authData,
|
||||
action: "delete",
|
||||
entityType: "session",
|
||||
description: `Ukončeny všechny ostatní relace (${terminated.count})`,
|
||||
});
|
||||
return success(reply, null, 200, "Všechny ostatní relace ukončeny");
|
||||
}
|
||||
|
||||
|
||||
@@ -146,4 +146,5 @@ export type EntityType =
|
||||
| "warehouse_receipt_attachment"
|
||||
| "work_plan_entry"
|
||||
| "work_plan_override"
|
||||
| "plan_category";
|
||||
| "plan_category"
|
||||
| "session";
|
||||
|
||||
Reference in New Issue
Block a user