feat(bereiche): Bereiche verwalten mit Rollenprüfung und Audit
Bereiche mit Farbe, Arbeitsfenster und Tageskapazität – die erste schreibende Funktion und damit der Beleg, dass die Kette trägt: zod prüft jede Eingabe, die Rolle wird in der Seite und noch einmal in der Server Action geprüft, jede Änderung hinterlässt einen Audit-Eintrag. Die Audit-Details werden vor dem Speichern gesäubert: Felder, deren Name nach Passwort, Token, Betreff oder Mailinhalt aussieht, werden ersetzt. Das gilt auch in verschachtelten Objekten und Listen. Dazu die Protokollseite für die Verwaltung und die Startseite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
cc013fd6a1
commit
e9a2b4b463
@@ -0,0 +1,44 @@
|
||||
import 'server-only'
|
||||
import type { Prisma } from '@/generated/prisma/client'
|
||||
import { auditDetails } from '@/lib/audit'
|
||||
import { db } from '@/server/db'
|
||||
import { aktuelleInstanz } from '@/server/instanz'
|
||||
|
||||
/**
|
||||
* Nachweis jeder schreibenden Aktion. Die Details werden vorher gesaeubert
|
||||
* (siehe @/lib/audit), damit keine Geheimnisse in der Datenbank landen.
|
||||
*/
|
||||
|
||||
export type AuditAkteur = {
|
||||
id: string | null
|
||||
email: string
|
||||
}
|
||||
|
||||
export type AuditEingabe = {
|
||||
akteur: AuditAkteur
|
||||
/** Was geschah, in der Form "objekt.verb", z. B. "bereich.angelegt". */
|
||||
aktion: string
|
||||
objektTyp: string
|
||||
objektId?: string | null
|
||||
details?: Record<string, unknown> | undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Schreibt einen Audit-Eintrag. Schlaegt das fehl, darf die eigentliche
|
||||
* Aktion nicht als geglueckt gelten – deshalb wird der Fehler weitergereicht
|
||||
* und nicht verschluckt.
|
||||
*/
|
||||
export async function auditSchreiben(eingabe: AuditEingabe): Promise<void> {
|
||||
const details = auditDetails(eingabe.details)
|
||||
await db.auditEintrag.create({
|
||||
data: {
|
||||
benutzerId: eingabe.akteur.id,
|
||||
benutzerEmail: eingabe.akteur.email,
|
||||
aktion: eingabe.aktion,
|
||||
objektTyp: eingabe.objektTyp,
|
||||
objektId: eingabe.objektId ?? null,
|
||||
...(details ? { details: details as Prisma.InputJsonObject } : {}),
|
||||
instanz: aktuelleInstanz(),
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user