Multi-User-Plattform: jeder Benutzer hat eigene, isolierte Daten
- 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>
This commit is contained in:
@@ -63,6 +63,18 @@
|
||||
<span class="hidden sm:inline">Einstellungen</span>
|
||||
</a>
|
||||
|
||||
<% if (typeof user !== 'undefined' && user && user.is_admin) { %>
|
||||
<!-- Admin: user management -->
|
||||
<a href="/admin"
|
||||
class="flex items-center gap-1.5 px-3 py-2 rounded-md bg-white/20 hover:bg-white/30 transition-colors text-white text-sm font-medium"
|
||||
title="Benutzer verwalten">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a4 4 0 00-3-3.87M9 20H4v-2a4 4 0 013-3.87m6-2a4 4 0 100-8 4 4 0 000 8z"></path>
|
||||
</svg>
|
||||
<span class="hidden sm:inline">Benutzer</span>
|
||||
</a>
|
||||
<% } %>
|
||||
|
||||
<!-- Notification bell: unread received e-mails (incl. auto-assigned replies) -->
|
||||
<div class="relative" id="notifWrap">
|
||||
<button id="notifBtn" type="button"
|
||||
@@ -82,6 +94,21 @@
|
||||
<div id="notifEmpty" class="px-4 py-8 text-center text-sm text-gray-400 dark:text-gray-500">Keine ungelesenen Nachrichten</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if (typeof user !== 'undefined' && user) { %>
|
||||
<!-- Signed-in user + logout -->
|
||||
<div class="flex items-center gap-2 pl-1">
|
||||
<span class="text-white/90 text-sm font-medium hidden sm:inline"><%= user.username %><% if (user.is_admin) { %> <span class="text-white/60">(Admin)</span><% } %></span>
|
||||
<a href="/logout"
|
||||
class="flex items-center gap-1.5 px-3 py-2 rounded-md bg-white/20 hover:bg-white/30 transition-colors text-white text-sm font-medium"
|
||||
title="Abmelden">
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>
|
||||
</svg>
|
||||
<span class="hidden sm:inline">Abmelden</span>
|
||||
</a>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user