feat(auth): Anmeldung, Rollen und Benutzerverwaltung (#21)
OIDC mit Discovery, PKCE, state und nonce; lokaler Login mit argon2 als Notfallzugang; Rechte in einer Tabelle, Prüfung ausschließlich serverseitig, Rolle und Aktiv-Status pro Anfrage aus der Datenbank. Ein unabhängiger Review fand eine offene Weiterleitung: die Präfix-Prüfung des Rücksprungziels ließ /<TAB>/fremd.example durch, woraus der Browser //fremd.example macht. Das Ziel wird jetzt aufgelöst und die Herkunft verglichen. Dazu acht weitere Befunde, alle behoben. 274 Tests. Closes #7 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit was merged in pull request #21.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import type { Rolle } from "@/generated/prisma/enums";
|
||||
import { prisma } from "@/lib/db";
|
||||
|
||||
/** Lesemodelle der Benutzerverwaltung (#007). */
|
||||
|
||||
export type BenutzerZeile = {
|
||||
readonly id: string;
|
||||
readonly email: string;
|
||||
readonly name: string;
|
||||
readonly rolle: Rolle;
|
||||
readonly aktiv: boolean;
|
||||
/** true, wenn das Konto ein Passwort hat, sich also lokal anmelden kann. */
|
||||
readonly mitPasswort: boolean;
|
||||
readonly ueberOidc: boolean;
|
||||
readonly letzteAnmeldungAm: Date | null;
|
||||
};
|
||||
|
||||
export async function benutzerListe(): Promise<readonly BenutzerZeile[]> {
|
||||
const zeilen = await prisma.benutzer.findMany({
|
||||
orderBy: [{ aktiv: "desc" }, { name: "asc" }],
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
name: true,
|
||||
rolle: true,
|
||||
aktiv: true,
|
||||
// Der Hash selbst verlaesst die Service-Schicht nie – nur die Auskunft,
|
||||
// ob ueberhaupt einer da ist.
|
||||
passwortHash: true,
|
||||
oidcSub: true,
|
||||
letzteAnmeldungAm: true,
|
||||
},
|
||||
});
|
||||
|
||||
return zeilen.map((zeile) => ({
|
||||
id: zeile.id,
|
||||
email: zeile.email,
|
||||
name: zeile.name,
|
||||
rolle: zeile.rolle,
|
||||
aktiv: zeile.aktiv,
|
||||
mitPasswort: zeile.passwortHash !== null,
|
||||
ueberOidc: zeile.oidcSub !== null,
|
||||
letzteAnmeldungAm: zeile.letzteAnmeldungAm,
|
||||
}));
|
||||
}
|
||||
Reference in New Issue
Block a user