70 lines
2.8 KiB
Plaintext
70 lines
2.8 KiB
Plaintext
// R-P2a S4 — serverseitige Sessions (Postgres als Source-of-Truth, Redis-Cache davor, AD-4).
|
|
// Eigenes Modul-Schema (AD-21): neue Modelle NICHT in accounts.prisma/core.prisma; die
|
|
// Rueck-Relation auf User bleibt minimal (User.userSessions).
|
|
//
|
|
// Das Login-Cookie traegt einen opaken Zufalls-Token; gespeichert wird nur dessen SHA-256-Hash
|
|
// (tokenHash). Eine Session ist gueltig, solange revokedAt = null und expiresAt in der Zukunft
|
|
// liegt. Die Geraete-Liste (Settings > Sicherheit), Revoke-einzeln und "ueberall abmelden"
|
|
// arbeiten auf diesen Zeilen.
|
|
|
|
model UserSession {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
// Nur der Hash des Cookie-Tokens wird persistiert (kein Klartext-Token in der DB).
|
|
tokenHash String @unique
|
|
|
|
createdAt DateTime @default(now())
|
|
lastSeenAt DateTime @default(now())
|
|
expiresAt DateTime
|
|
revokedAt DateTime?
|
|
|
|
// Trust-Device (S5/2FA): markiert eine Session als vertrauenswuerdig, damit fuer sie kein
|
|
// erneuter TOTP-Code verlangt wird.
|
|
trustedAt DateTime?
|
|
|
|
// Kontext fuer die Geraete-Liste. AD-22: KEINE Klartext-IP persistieren — nur der Hash (hashIp)
|
|
// zur "gleiches Geraet"-Wiedererkennung; angezeigt wird das Land (approxLocation via geoip).
|
|
ipHash String?
|
|
userAgent String?
|
|
deviceLabel String?
|
|
approxLocation String?
|
|
browserFingerprint String?
|
|
|
|
@@index([userId])
|
|
@@index([userId, revokedAt])
|
|
@@index([expiresAt])
|
|
}
|
|
|
|
// D1 (Trust-Device) — "diesem Geraet vertrauen" beim 2FA-Login. UEBERLEBT den Logout (anders als
|
|
// UserSession.trustedAt, das per Session lebt) -> eigene, langlebige Tabelle. Das Geraete-Cookie
|
|
// traegt einen opaken Zufalls-Token; persistiert wird nur dessen SHA-256-Hash (tokenHash). Ein Geraet
|
|
// ueberspringt den zweiten Faktor, solange revokedAt = null und expiresAt in der Zukunft liegt. Die
|
|
// Geraete-Liste (Settings > Sicherheit), Revoke-einzeln und "ueberall vergessen" arbeiten auf diesen
|
|
// Zeilen -> erfuellt den DoD-Screen "Trust-Device-Revoke" (R-P2a) widerrufbar statt nur Cookie.
|
|
model TrustedDevice {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
// Nur der Hash des Cookie-Tokens wird persistiert (kein Klartext-Token in der DB).
|
|
tokenHash String @unique
|
|
|
|
createdAt DateTime @default(now())
|
|
lastUsedAt DateTime @default(now())
|
|
expiresAt DateTime
|
|
revokedAt DateTime?
|
|
|
|
// Kontext fuer die Geraete-Liste. AD-22: KEINE Klartext-IP persistieren — nur der Hash (hashIp);
|
|
// angezeigt wird das Land (approxLocation via geoip).
|
|
ipHash String?
|
|
userAgent String?
|
|
deviceLabel String?
|
|
approxLocation String?
|
|
|
|
@@index([userId])
|
|
@@index([userId, revokedAt])
|
|
@@index([expiresAt])
|
|
}
|