feat: Datenmodell und Regeln fuer die oeffentliche Schnittstelle

Gespeichert wird nur der Hash eines Tokens. Der Klartext existiert genau
einmal — beim Anlegen, auf dem Bildschirm. Ein Token ist ein Passwort;
es gibt keinen Grund, es zurueckzulesen, und jeden Grund, es nicht zu
koennen.

Drei Rechte, und keines schliesst ein anderes ein. Ein Dienst, der nur
meldet "hier ist etwas Neues", braucht den Bestand nicht zu sehen — genau
das ist der haeufigste Fall und der, bei dem ein mitgelesener Token am
wenigsten anrichtet.

Der sichtbare Anfang "planer_..." ist Absicht: Wer so einen Wert
versehentlich in ein oeffentliches Verzeichnis schiebt, soll ihn beim
Durchsehen erkennen.

30 Tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-12 11:09:03 +02:00
co-authored by Claude Opus 5
parent bbac268c59
commit d5c7974af3
4 changed files with 405 additions and 0 deletions
+32
View File
@@ -39,6 +39,7 @@ model Benutzer {
pushGeraete PushGeraet[]
meldungen Meldungsnachweis[]
telegramChats TelegramChat[]
apiTokens ApiToken[]
@@index([aktiv])
@@map("benutzer")
@@ -538,3 +539,34 @@ model TelegramKopplung {
@@index([gueltigBis])
@@map("telegram_kopplung")
}
/// Zugangstoken fuer die oeffentliche Schnittstelle.
///
/// Gespeichert wird nur der Hash. Der Klartext existiert genau einmal – beim
/// Anlegen, auf dem Bildschirm. Ein Token ist ein Passwort; wer es verliert,
/// legt ein neues an, statt das alte irgendwo nachzuschlagen.
model ApiToken {
id String @id @default(cuid())
benutzerId String
name String
/// Sichtbarer Anfang, macht die Zeile auffindbar und wiedererkennbar.
praefix String @unique
/// SHA-256 des vollstaendigen Tokens.
hash String @unique
/// Kommagetrennt, siehe src/lib/api.ts.
rechte String
gueltigBis DateTime?
letzteNutzung DateTime?
/// Gesetzt heisst: gilt nicht mehr. Die Zeile bleibt fuer das Protokoll.
widerrufenAm DateTime?
erstelltAm DateTime @default(now())
benutzer Benutzer @relation(fields: [benutzerId], references: [id], onDelete: Cascade)
@@index([benutzerId])
@@map("api_token")
}