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,77 @@
|
||||
import type { Metadata } from 'next'
|
||||
import { PasskeyVerwaltung } from '@/app/(app)/einstellungen/passkey-verwaltung'
|
||||
import {
|
||||
Card,
|
||||
CardBeschreibung,
|
||||
CardInhalt,
|
||||
CardKopf,
|
||||
CardTitel,
|
||||
} from '@/components/ui/card'
|
||||
import { ROLLEN_NAME } from '@/lib/rollen'
|
||||
import { alsDatumUhrzeit } from '@/lib/zeit'
|
||||
import { verlangeAnmeldung } from '@/server/berechtigung'
|
||||
import { db } from '@/server/db'
|
||||
|
||||
export const metadata: Metadata = { title: 'Einstellungen' }
|
||||
|
||||
export default async function EinstellungenSeite() {
|
||||
const benutzer = await verlangeAnmeldung('/einstellungen')
|
||||
|
||||
const passkeys = await db.passkey.findMany({
|
||||
where: { benutzerId: benutzer.id },
|
||||
orderBy: { erstelltAm: 'asc' },
|
||||
select: {
|
||||
id: true,
|
||||
bezeichnung: true,
|
||||
erstelltAm: true,
|
||||
zuletztBenutzt: true,
|
||||
gesichert: true,
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-8">
|
||||
<header>
|
||||
<h1 className="text-2xl font-semibold tracking-tight">Einstellungen</h1>
|
||||
</header>
|
||||
|
||||
<Card>
|
||||
<CardKopf>
|
||||
<CardTitel className="text-base">Konto</CardTitel>
|
||||
</CardKopf>
|
||||
<CardInhalt>
|
||||
<dl className="grid gap-2 text-sm sm:grid-cols-[10rem_1fr]">
|
||||
<dt className="text-gedaempft-vordergrund">Name</dt>
|
||||
<dd>{benutzer.name ?? '—'}</dd>
|
||||
<dt className="text-gedaempft-vordergrund">E-Mail</dt>
|
||||
<dd>{benutzer.email}</dd>
|
||||
<dt className="text-gedaempft-vordergrund">Rolle</dt>
|
||||
<dd>{ROLLEN_NAME[benutzer.rolle]}</dd>
|
||||
</dl>
|
||||
</CardInhalt>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardKopf>
|
||||
<CardTitel className="text-base">Passkeys</CardTitel>
|
||||
<CardBeschreibung>
|
||||
Mit einem Passkey meldest du dich per Fingerabdruck, Gesicht oder Geräte-PIN
|
||||
an – ohne Passwort. Hinterlege am besten zwei, damit du bei Verlust eines
|
||||
Geräts nicht ausgesperrt bist.
|
||||
</CardBeschreibung>
|
||||
</CardKopf>
|
||||
<CardInhalt>
|
||||
<PasskeyVerwaltung
|
||||
passkeys={passkeys.map((p) => ({
|
||||
id: p.id,
|
||||
bezeichnung: p.bezeichnung,
|
||||
erstelltAm: alsDatumUhrzeit(p.erstelltAm),
|
||||
zuletztBenutzt: p.zuletztBenutzt ? alsDatumUhrzeit(p.zuletztBenutzt) : null,
|
||||
gesichert: p.gesichert,
|
||||
}))}
|
||||
/>
|
||||
</CardInhalt>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user