Der X-API-Key identifiziert den Benutzer; alle Endpunkte waren bereits auf
dessen user_id gescoped (27 Operationen geprueft). Zwei Luecken blieben:
- Die Aufloesung Token -> Benutzer nahm bei mehrdeutigem Token per LIMIT 1
einfach den ersten Treffer. Haetten zwei Benutzer denselben Token, saehe
der eine die Daten des anderen. Jetzt: fail closed (401 + Logeintrag),
und /einstellungen weist einen bereits vergebenen Token mit 409 ab.
- Ein leerer Token galt als Wert: wer seine Einstellungen einmal gespeichert
hatte, besass eine API_TOKEN-Zeile mit ''. Leere Werte matchen jetzt nie.
Neu in den Einstellungen (Abschnitt REST-API):
- "Neu generieren" erzeugt einen zufaelligen Token (32 Byte, crypto.get-
RandomValues); er wird nur ins Feld gefuellt und erst beim Speichern
aktiv, ein Fehlklick laesst sich also verwerfen.
- "Kopieren" legt den Token in die Zwischenablage; das Auge blendet ihn ein
(bestand bereits fuer Secret-Felder).
API aktualisiert:
- PUT /settings kannte nur name/adresse/kundennummer, GET lieferte aber alle
acht Felder. Jetzt schreibt PUT alle (email, telefon, ort, webseite,
geburtsdatum) und aendert nur die im Body uebergebenen Felder; die Antwort
enthaelt den neuen Stand.
Swagger:
- Beschreibung sagte "konfiguriert via Umgebungsvariable API_TOKEN" - das
gilt seit der Multi-User-Umstellung nicht mehr. Jetzt dokumentiert:
Token pro Benutzer aus den Einstellungen, Zugriff nur auf eigene Daten,
fremde id -> 404, unbekannter/leerer/mehrdeutiger Token -> 401.
- Settings-Schema um die fehlenden fuenf Felder ergaenzt.
Verifiziert mit zwei Benutzern und je eigenem Key: Lesen, Aendern, Loeschen,
Timeline, Anhaenge, E-Mails, Generierung, Jobangebote und Blacklist des
jeweils anderen liefern durchgaengig 404; Listen, Export und Statistik
zeigen nur eigene Daten; kollidierender Token -> 409; mehrdeutiger Token in
der DB -> 401 fuer beide.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
config.get() ist bei einem nicht gesetzten Schluessel auf process.env
zurueckgefallen. Da die Env-Variablen die Konfiguration des Admins
enthalten (Docker-Env: MAIL_*, CALDAV_URL, OLLAMA_API_KEY, API_TOKEN),
hat damit JEDER neu angelegte Benutzer ohne eigene Einstellungen
stillschweigend die Zugangsdaten des Admins geerbt:
- /einstellungen zeigte ihm die Zugangsdaten des Admins an.
- mailer/caldav isConfigured() war true -> der IMAP-Poller hat fuer den
neuen Benutzer das Postfach des Admins abgerufen und dessen E-Mails in
sein Konto einsortiert; CalDAV synchronisierte den Kalender des Admins.
- Der bezahlte Ollama-Key des Admins wurde mitbenutzt.
Jetzt:
- config.get() loest ausschliesslich die Zeilen des aktuellen Benutzers auf,
sonst den eingebauten Standard (nicht-geheime Werte wie Modell, Host,
Ports, Intervalle). Alle Credentials sind bei neuen Benutzern leer,
d. h. Ollama/E-Mail/CalDAV/API sind fuer sie aus, bis sie sich selbst
etwas eintragen.
- Noch per Env gesetzte Konfiguration wird einmalig in die Zeilen des
ADMIN uebernommen (importEnvIntoAdmin, Aufruf beim Boot nachdem
app_state existiert - in runMigration war das bei Neuinstallationen ein
No-op, weil die Tabelle dort noch nicht angelegt ist).
- config.ensureLoaded(user.id) beim Aufloesen der Session bzw. des
X-API-Key. config.get() ist synchron und liest den Per-User-Cache; ohne
Warmladen las ein Web-Request die Werte als "nicht konfiguriert". Das
hat bisher der env-Fallback verdeckt (er hielt zufaellig die Werte des
Admins) - ohne ihn muss die Config pro Request wirklich geladen werden.
Verifiziert gegen eine Kopie der Produktions-DB mit Sentinel-Env-Werten:
Admin behaelt seine kompletten Einstellungen, der zweite Benutzer sieht
ueberall leere Credentials, Mail/CalDAV sind fuer ihn inaktiv, und der
Env-API-Token wird nicht mehr als gueltiger X-API-Key akzeptiert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Auth via Session-Cookie + Login-Seite (scrypt, lib/password.js, sessions-Tabelle)
- AsyncLocalStorage (lib/context.js) propagiert aktuellen Benutzer durch alle Libs
- user_id auf allen Datentabellen (FK->users ON DELETE CASCADE), per-user PK/UNIQUE
(app_state, settings, prompts, design, jobangebote) und per-user Dateispeicher
(data/<dir>/<userId>/)
- Alle Queries in server.js + lib/api.js nach user_id scope-iert
- Pro-Benutzer-Konfiguration (Ollama/Mail/CalDAV/API-Token) in app_state,
Live gelesen via config.get(); Hintergrund-Loops (IMAP/CalDAV) iterieren alle Benutzer
- REST-API /api/v1: X-API-Key loest den Token zu einem Benutzer auf, Anfragen
operieren nur auf dessen Daten
- Admin-Panel /admin: Benutzer anlegen, Passwort zuruecksetzen, loeschen (mit Daten)
- Idempotente Migration (lib/migrate-multiuser.js + scripts/migrate-to-multiuser.js):
bestehende Daten werden dem Benutzer admin:admin zugeordnet
Co-Authored-By: Claude <noreply@anthropic.com>
Neue /einstellungen-Seite (Zahnrad im Header) mit allen bisherigen .env-Werten
(Ollama, E-Mail, CalDAV, REST-API), gespeichert in SQLite (app_state, cfg:-Prefix).
Libs lesen per lib/config.js zur Laufzeit statt beim Start -> Aenderungen
wirken sofort, kein Neustart. Bestehende .env wird beim ersten Start einmalig
migriert.
Co-Authored-By: Claude <noreply@anthropic.com>