Einstellungen strikt pro Benutzer: kein process.env-Fallback mehr
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>
This commit is contained in:
@@ -45,7 +45,7 @@ const config = require('./lib/config');
|
||||
const { userContext, currentUser, currentUserId } = require('./lib/context');
|
||||
const password = require('./lib/password');
|
||||
const migrate = require('./lib/migrate-multiuser');
|
||||
const { runMigration } = migrate;
|
||||
const { runMigration, importEnvIntoAdmin } = migrate;
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3000;
|
||||
@@ -110,6 +110,12 @@ app.use(async (req, res, next) => {
|
||||
const user = await loadSessionUser(cookies[SESSION_COOKIE]);
|
||||
req.user = user;
|
||||
res.locals.user = user;
|
||||
// Warm this user's cfg rows before anything reads them: config.get() is
|
||||
// synchronous and answers from the per-user cache, so a user whose rows were
|
||||
// never loaded would silently read as "unconfigured". Until now the process
|
||||
// .env fallback papered over that (it happened to hold the admin's values);
|
||||
// with the fallback gone, the config must actually be loaded per request.
|
||||
if (user) await config.ensureLoaded(user.id);
|
||||
userContext.run(user, next);
|
||||
} catch (e) {
|
||||
console.error('Session-Laden fehlgeschlagen:', e.message);
|
||||
@@ -1216,11 +1222,19 @@ async function initializeDatabase() {
|
||||
initializeDatabase().then(async () => {
|
||||
console.log('Database initialized successfully');
|
||||
|
||||
// Load configuration from the DB (migrates any still-present .env values
|
||||
// once). Must run before the boot checks below (mailer/caldav configured?) and
|
||||
// before any route that reads config — values live in the DB now, not in .env.
|
||||
// Load configuration from the DB. Must run before the boot checks below
|
||||
// (mailer/caldav configured?) and before any route that reads config — values
|
||||
// live in the DB now, not in the environment.
|
||||
await config.init({ dbAll, dbRun });
|
||||
|
||||
// Import any config still supplied via the environment into the *admin's* rows
|
||||
// (one-time, idempotent). Env config is the admin's: config.get() has no
|
||||
// process.env fallback, precisely so that a newly created user does not
|
||||
// inherit the admin's mailbox, calendar, Ollama key and API token. This runs
|
||||
// here rather than inside runMigration() because on a fresh install app_state
|
||||
// does not exist yet while the migration is running.
|
||||
await importEnvIntoAdmin({ dbAll, dbGet });
|
||||
|
||||
// Current user's id — set by the auth middleware (lib/context.js). Guaranteed
|
||||
// to be present inside any protected route or background-per-user task.
|
||||
const uid = () => currentUserId();
|
||||
|
||||
Reference in New Issue
Block a user