Files
Hoard/codexInfo.md
T
Jonas b2984fcf1a Replace IsAdmin with role-based admin
Switch user admin handling from an AppUser boolean to ASP.NET Identity roles. Removed AppUser.IsAdmin and related configuration/model entries; added migration ReplaceIsAdminWithRoles to copy Users.IsAdmin=true into a persistent admin role and drop the IsAdmin column. CurrentUserResponse now exposes roles (string[]), AuthController returns ordered roles from UserManager, and IdentitySeedService now ensures the admin role exists and assigns/creates an initial admin user in that role. Program.cs registers an Admin-only policy (PolicyNames/RoleNames), adjusts cookie auth events to return 401/403 for API requests, and wires up authorization. Frontend updated to use roles: authSession normalizes roles, adds hasRole and ROLE_ADMIN, router and layout support meta.requiredRoles, and new Forbidden and AdminUsers pages/route are added. codexInfo.md updated to reflect the migration to role-based auth.
2026-04-20 19:57:49 +02:00

21 KiB
Raw Blame History

Projektübersicht self-hosted Datei- und Markdown-App

Projektidee

Ich baue eine einfache self-hosted Web-App, die sich funktional zwischen Google Drive, Notion und Obsidian einordnet. Der Schwerpunkt liegt aber klar auf einer Google-Drive-artigen Oberfläche mit Dateien und Ordnern. Markdown-Dateien sollen direkt im Browser bearbeitet werden können, andere Dateien sollen gespeichert und wenn möglich als Vorschau angezeigt werden.

Ziel des Projekts

Das Projekt ist ein kleines, bewusst einfach gehaltenes Solo-Projekt neben meiner Ausbildung. Es soll mehrere Benutzer unterstützen, aber technisch und funktional schlank bleiben. Wichtig ist ein realistisches MVP, das sauber läuft und später erweitert werden kann.

Geplanter Tech-Stack

  • Frontend: Vue 3
  • Markdown-Editor: md-editor-v3
  • Backend: ASP.NET Core mit C#
  • Datenbank: PostgreSQL
  • Dateispeicher: MinIO als S3-kompatibler Storage
  • Authentifizierung: klassische Cookie-basierte Authentifizierung, keine JWTs
  • Deployment: self-hosted Web-App auf meinem eigenen Server

Kernfunktionen für das MVP

  • Login mit bestehenden Accounts
  • Kein öffentliches Registrieren
  • Ein initialer Admin-Account wird zuerst erstellt
  • Weitere Benutzer werden später nur manuell durch den Admin angelegt
  • Dateien und Ordner anlegen, hochladen und öffnen
  • Durch Ordnerstrukturen navigieren
  • Google-Drive-artige Hauptansicht mit Dateiliste und Vorschau
  • Markdown-Dateien direkt im Browser bearbeiten
  • PDFs und Bilder als Vorschau anzeigen
  • Andere Dateien einfach speichern und bei Bedarf herunterladen oder öffnen

Was bewusst nicht Teil des MVP ist

  • Keine Registrierung für normale Nutzer
  • Kein Teilen oder Freigeben von Dateien
  • Keine Suche
  • Keine Versionierung oder Dateihistorie
  • Keine Echtzeit-Zusammenarbeit
  • Keine Desktop-App oder Mobile-App
  • Keine komplizierte Rechteverwaltung
  • Keine JWT-, OAuth- oder SSO-Lösung

Gewünschter Stil der Anwendung

Die Oberfläche soll sich eher an Google Drive orientieren als an Notion oder Obsidian. Wichtig sind Übersicht, einfache Navigation und ein klarer Fokus auf Dateien, Ordner, Vorschau und Bearbeitung. Die App soll schlicht, pragmatisch und gut allein umsetzbar sein.

Sprachregel für UI-Texte

  • Umlaute sind ausdrücklich erwünscht (ä, ö, ü, Ä, Ö, Ü).
  • Keine Umschreibungen mit ae, oe, ue in sichtbaren deutschen Texten.

Wie die App später wirken soll

Die Anwendung soll wie eine einfache Dateiverwaltung im Browser wirken. Man meldet sich an, sieht seine Ordner und Dateien, kann sich durch die Struktur klicken, PDFs und Bilder direkt ansehen und Markdown-Dateien öffnen und bearbeiten. Der Fokus liegt auf Einfachheit statt auf vielen Sonderfunktionen.

Technische Leitidee

Das Projekt soll möglichst einfach aufgebaut werden. Dateimetadaten liegen in PostgreSQL, die eigentlichen Dateien in MinIO. Das Backend verwaltet Login, Benutzer, Ordner, Dateien und Vorschau-Informationen. Das Frontend bildet hauptsächlich die Dateiverwaltung, Vorschau und Markdown-Bearbeitung ab. Die gesamte Architektur soll bewusst schlank bleiben, damit sie für ein Solo-Projekt realistisch ist.

Projektbeschreibung für eine KI

Ich baue alleine neben meiner Ausbildung eine einfache self-hosted Web-App für mehrere Benutzer. Die App kombiniert eine Google-Drive-artige Dateiverwaltung mit einfacher Markdown-Bearbeitung. Benutzer sollen durch Ordner und Dateien navigieren können, Bilder und PDFs in einer Vorschau sehen und Markdown-Dateien direkt im Browser bearbeiten. Es gibt keine öffentliche Registrierung, kein Teilen, keine Suche und keine Versionierung. Benutzerkonten werden manuell angelegt, beginnend mit einem initialen Admin-Account. Der Tech-Stack besteht aus Vue 3 im Frontend, md-editor-v3 als Markdown-Editor, ASP.NET Core mit C# im Backend, PostgreSQL für Metadaten, MinIO als S3-kompatiblen Dateispeicher und Cookie-basierter Authentifizierung.

Frontend-Designquelle (Style Guide)

  • Es gibt einen zentralen Design-Guide unter GUI/style.md.
  • Dieser Guide definiert die visuelle Richtung für Hoard: light-first, dateiorientiert, ruhige Flächen, gezielte Verwendung von Grün als Markenfarbe.
  • Enthalten sind Farbpalette, Typografie, Spacing, Border-Radien, Schatten, Komponentenregeln und Interaktionsprinzipien.

Angelegte globale CSS-Basis

  • Statt app.css wurde eine zentrale globale Datei GUI/src/global.css angelegt und verwendet.
  • Diese Datei wird in GUI/src/main.ts über import './global.css' eingebunden.
  • Zusätzlich wurden modulare globale CSS-Dateien angelegt: GUI/src/styles/global/page-layouts.css und GUI/src/styles/global/surface-patterns.css.
  • Beide Module werden ebenfalls zentral in GUI/src/main.ts eingebunden und bündeln wiederkehrende Layout-/Surface-Patterns.
  • Inhaltlich stellt global.css bereit:
    • Design-Tokens als CSS-Variablen (:root) für Farben, Spacing, Radius, Schatten, Typografie und Statusfarben.
    • Globale Basisstile für html, body, Links, Überschriften, Fokuszustände und Scrollbars.
    • Vuetify-nahe globale Anpassungen für App-Shell und Standardkomponenten (Topbar, Sidebar, Cards, Buttons, Inputs, Tabellen).
    • Wiederverwendbare Utility-/Pattern-Klassen für Hoard-Seiten, z. B. hoard-panel, hoard-toolbar, hoard-list-row, hoard-empty-state, hoard-status.
    • Responsive Verhalten für kleinere Viewports per Media Query.

Anleitung: CSS-Patterns verwenden

  • Neue Seiten standardmäßig mit hoard-page aufbauen; für zentrierte Vollhöhen-Ansichten zusätzlich hoard-page--centered.
  • Karten-/Shell-Container als hoard-shell-grid hoard-panel verwenden; Breite/Abstände pro Seite über CSS-Variablen setzen (--hoard-shell-width, --hoard-shell-gap, --hoard-shell-padding).
  • Wiederkehrende Headlines/Kicker mit hoard-kicker nutzen, Varianten bei Bedarf mit hoard-kicker--wide oder hoard-kicker--xs.
  • Button-/Link-Aktionszeilen mit hoard-action-row bauen statt pro Seite eigene Flex-Definitionen zu duplizieren.
  • Gradient-Flächen über hoard-panel-gradient + Variablen steuern (--hoard-gradient-angle, --hoard-gradient-start, --hoard-gradient-end, --hoard-gradient-end-stop), nicht pro Seite komplett neu definieren.
  • Lokales scoped CSS nur für wirklich seitenspezifische Styles verwenden; alles Wiederverwendbare zuerst in GUI/src/styles/global/page-layouts.css oder GUI/src/styles/global/surface-patterns.css ergänzen.

Aktueller Stand

  • GUI/src/Layout.vue bildet die zentrale App-Shell mit Topbar, Sidebar, Footer, Routen-Kontext und responsivem Drawer-Verhalten.
  • Darkmode (light/dark) ist global integriert (Toggle in der Topbar, Persistenz in localStorage, Theme-Tokens in CSS/Vuetify).
  • Öffentliche Kernseiten sind im einheitlichen Hoard-Stil umgesetzt: Home.vue (Landingpage), Login.vue, 404NotFound.vue, Impressum.vue.
  • Das Topbar-Branding nutzt das App-Icon aus GUI/src/assets/images/icon.svg.
  • Globale CSS-Struktur ist aktiv: GUI/src/global.css (Tokens/Basis) sowie GUI/src/styles/global/page-layouts.css und GUI/src/styles/global/surface-patterns.css für wiederverwendbare Patterns.
  • Sidebar-Sichtbarkeit unterstützt Visibility.Route mit optionalem visibilityRoute in GUI/src/plugins/routesLayout.ts.
  • Mobile-Touch-Optimierung ist für alle aktuellen öffentlichen Oberflächen aktiv (Shell, Home, Login, Impressum, 404), inklusive Safe-Area-Unterstützung.
  • Desktop-Ansicht bleibt unverändert, da alle neuen Anpassungen ausschließlich in mobilen Breakpoints (<= 960px, Feinschliff <= 600px) umgesetzt sind.
  • Backend-API enthält aktuell Basis-Endpunkte für Health (GET /api/health) und Auth (POST /auth/login, POST /auth/logout, GET /auth/me).
  • Swagger/OpenAPI ist im Backend nur im Development-Modus aktiv (/swagger).
  • Frontend-Build (npm run build im GUI-Projekt) schreibt direkt nach API/wwwroot; das Backend liefert die SPA und statische Assets aus.
  • Backend nutzt jetzt PostgreSQL über ConnectionStrings:Postgres mit EF Core (ApplicationDbContext) und führt Migrationen beim Start automatisch aus.
  • Backend nutzt ASP.NET Identity mit AppUser (Guid-Key, IsActive, MustChangePassword, CreatedAt, UpdatedAt) über PostgreSQL; Admin-Rechte laufen über Rollen (admin) statt User-Flag.
  • ApplicationDbContext basiert auf IdentityDbContext; Identity-Tabellen sind auf Users, Roles, UserRoles, UserClaims, UserLogins, RoleClaims und UserTokens gemappt.
  • Migration InitIdentity (API/Migrations/20260418192723_InitIdentity.cs) erstellt das Identity-Schema und wird beim Start automatisch angewendet.
  • Temporäre Test-Entity und Test-CRUD-Endpunkt (api/test-items) wurden wieder entfernt.
  • Nach den Migrationen wird per IdentitySeedService die Rolle admin sichergestellt und einem initialen Admin-Account zugewiesen, falls noch kein Admin in dieser Rolle existiert.
  • Für lokale Entwicklung liegt unter API/Dev/docker-compose.yml ein Stack mit PostgreSQL (localhost:5432) und pgAdmin (localhost:5050).
  • API lädt optional API/appsettings.custom.json; wenn vorhanden, überschreibt sie Werte aus appsettings.json.
  • API/appsettings.custom.json ist in .gitignore hinterlegt, damit lokale Konfigurationswerte nicht versehentlich committed werden.
  • Backend-Logging ist aktiviert mit strukturierter Console-Ausgabe (inkl. Zeitstempel) sowie HTTP-Request-Logging.
  • Beim Identity-Seeding wird explizit geloggt, wenn ein Admin-Account neu angelegt wurde.
  • Frontend-Auth ist jetzt aktiv: Login-Form (GUI/src/routes/authentication/Login.vue) sendet an POST /auth/login und zeigt API-Fehler als sichtbare Meldung.
  • Dashboard ist als geschützte Route auf / umgesetzt (GUI/src/routes/dashboard/Dashboard.vue) und zeigt die Antwort von GET /auth/me.
  • Router-Guards in GUI/src/router/index.ts leiten nicht eingeloggte Nutzer von geschützten Routen auf /login um und leiten eingeloggte Nutzer von /login zurück aufs Dashboard.
  • Öffentliche Landingpage wurde auf /welcome verschoben; 404- und Impressum-Links zur Startseite zeigen entsprechend auf /welcome.
  • Sidebar-Navigation berücksichtigt Auth-Status differenziert: Startseite wird nur unangemeldet angezeigt (inkl. unterem Drawer-Link), Dash nur angemeldet.
  • Topbar zeigt bei aktiver Anmeldung den Benutzernamen; die Abmelden-Aktion erscheint im Hover-Menü unter dem Benutzernamen (Desktop) bzw. im Account-Menü (Mobile).
  • Fehler werden jetzt global über einen Banner-Stack am unteren Seitenrand angezeigt (routeübergreifend, stapelbar, manuell schließbar).
  • Der globale Banner-Stack im Layout nutzt einen kontrollierten z-index und opake Hintergründe, damit Fehlermeldungen im Vordergrund bleiben und kaum durchscheinende Inhalte zeigen.
  • Klick auf Logo/Branding in der Topbar führt abhängig vom Auth-Status: angemeldet auf Dashboard, unangemeldet auf Welcome.
  • 404-Seite löst den Auth-Status auf und leitet automatisch weiter: angemeldet zu Dashboard, unangemeldet zu Welcome; primärer CTA ist entsprechend dynamisch.
  • Brand-Klick ist gegen Auth-Timing abgesichert: bei vorhandener Session führt Logo/Titel auch bei noch nicht synchronisiertem Layout-Status zuverlässig auf Dashboard.

Änderungen durch Codex

  • Grundlegender UI-Neuaufbau der App-Shell (GUI/src/Layout.vue) inklusive Navigation, Footer und Seitenkontext.
  • Einführung eines globalen Theme-Managements (light/dark) über GUI/src/plugins/vuetify.ts, GUI/src/global.css und localStorage.
  • Überarbeitung der zentralen öffentlichen Seiten (Home.vue, Login.vue, 404NotFound.vue, Impressum.vue) auf ein einheitliches Hoard-Design.
  • Erweiterung von GUI/src/plugins/routesLayout.ts um routeabhängige Sidebar-Sichtbarkeit (Visibility.Route, visibilityRoute).
  • Konsolidierung der UI-Texte auf deutsche Umlaute gemäß Sprachregel.
  • Aufbau und fortlaufende Konsolidierung der globalen CSS-Basis (global.css) inkl. Fokus-/Auswahl-Polish.
  • CSS-Debloat-Refactor: gemeinsame Oberflächen-Patterns in GUI/src/styles/global/page-layouts.css und GUI/src/styles/global/surface-patterns.css ausgelagert und zentral in GUI/src/main.ts eingebunden.
  • codexInfo.md um eine kompakte Nutzunganleitung für die globalen CSS-Patterns ergänzt.
  • Mobile-Usability über globale Styles erweitert: größere Touch-Ziele (v-btn, Navigationspunkte), Safe-Area-Paddings und mobile Spacing-Feinschliff in GUI/src/global.css sowie den globalen Pattern-Dateien.
  • GUI/src/Layout.vue für Mobile optimiert: entzerrte App-Bar-Abstände, touchfreundlicher Bottom-Sheet-Drawer und besser bedienbarer Footer auf kleinen Viewports.
  • Mobile-spezifische Detailoptimierungen in Home.vue, Login.vue, Impressum.vue und 404NotFound.vue ergänzt (Actions, Card-/Form-Spacing, CTA-Stacking), ohne Desktop-Basislayout zu verändern.
  • GUI/style.md um einen verbindlichen Abschnitt „Umsetzungsstandard Responsivität“ ergänzt (Breakpoints, Touch-Zielgrößen, Safe-Area, globale Pattern-Nutzung, QA-Checkliste), damit Folgeaufgaben denselben Stil beibehalten.
  • Topbar-Kontext in GUI/src/Layout.vue für schmalere Breiten beruhigt: auf Mobile wird der Seitenkontext komplett ausgeblendet, auf mittleren Breiten bleibt nur der Seitentitel (ohne Unterzeile), damit das Header-Layout sauber und nicht gequetscht wirkt.
  • Backend-Template-Code bereinigt: WeatherForecastController und WeatherForecast entfernt, OpenAPI-Templatepaket aus API/API.csproj entfernt.
  • Neuen Test-Controller API/Controllers/HealthController.cs angelegt (GET /api/health), der 200 OK zurückgibt.
  • GUI/vite.config.ts Build-Ausgabe auf API/wwwroot umgestellt (outDir) und Bereinigung des Zielordners beim Build aktiviert (emptyOutDir: true).
  • API/Program.cs erweitert, damit statische Dateien aus wwwroot inkl. SPA-Fallback (index.html) ausgeliefert werden.
  • SPA-Fallback im Backend aufgeteilt: Frontend-Routen liefern index.html, unbekannte /api/*-Routen bleiben korrekt 404 statt auf die SPA zu fallen.
  • Swagger im Backend ergänzt: Swashbuckle.AspNetCore eingebunden, Services registriert und UI nur in Development aktiviert.
  • PostgreSQL-Integration im Backend umgesetzt: Npgsql.EntityFrameworkCore.PostgreSQL + Microsoft.EntityFrameworkCore.Design in API/API.csproj ergänzt und Connection String ConnectionStrings:Postgres in den Settings hinterlegt.
  • API/Database/ApplicationDbContext.cs mit Test-Entity API/Models/Test/TestItem.cs angelegt; erste Migrationen in API/Migrations erstellt.
  • API/Program.cs um AddDbContext (Postgres) und Database.Migrate() beim Start erweitert, damit Migrationen automatisch angewendet werden.
  • API/Controllers/TestItemsController.cs als einfacher CRUD-Testcontroller (GET/POST/PUT/DELETE) unter api/test-items ergänzt.
  • Dev-Stack für lokale Datenbankarbeit ergänzt: API/Dev/docker-compose.yml startet PostgreSQL + pgAdmin.
  • API/Program.cs so erweitert, dass optional appsettings.custom.json geladen wird und bei vorhandener Datei bevorzugte lokale Overrides möglich sind.
  • Neue lokale Konfigurationsdatei API/appsettings.custom.json aus der bisherigen appsettings.json angelegt und in .gitignore ergänzt.
  • Test-Datentyp und Test-API wieder entfernt: API/Models/Test/TestItem.cs und API/Controllers/TestItemsController.cs gelöscht, ApplicationDbContext bereinigt.
  • Neue Migration RemoveTestItems erstellt (API/Migrations/20260418153650_RemoveTestItems.cs), die Tabelle test_items entfernt und den Snapshot aktualisiert.
  • API/API.csproj um Microsoft.AspNetCore.Identity.EntityFrameworkCore ergänzt und Microsoft.EntityFrameworkCore.Design auf 10.0.6 angehoben.
  • ASP.NET Identity eingeführt: API/Models/AppUser.cs angelegt und API/Database/ApplicationDbContext.cs auf IdentityDbContext<AppUser, IdentityRole<Guid>, Guid> umgestellt.
  • API/Database/Configurations/AppUserConfiguration.cs ergänzt, damit AppUser auf Users liegt und projektspezifische Pflichtfelder sauber konfiguriert sind.
  • Migration InitIdentity ergänzt (API/Migrations/20260418192723_InitIdentity.cs + Designer + Snapshot-Update) für User-/Role-/Claim-Tabellen.
  • Auth-Basis implementiert: DTOs unter API/Contracts/Auth/* und API/Controllers/Auth/AuthController.cs mit POST /auth/login, POST /auth/logout, GET /auth/me.
  • API/Program.cs um Identity-Service-Registrierung, Cookie-Konfiguration (hoard.auth), UseAuthentication/UseAuthorization und Startup-Seeding erweitert.
  • Backend-Logging in API/Program.cs ergänzt: AddSimpleConsole (Zeitstempel, Single-Line), AddDebug und AddHttpLogging/UseHttpLogging für Request-Logs.
  • API/Services/IdentitySeedService.cs neu ergänzt: erstellt beim ersten Start einen initialen Admin aus SeedAdmin:* und loggt Erfolg/Fehler nachvollziehbar.
  • Neues Frontend-Auth-Modul GUI/src/services/authSession.ts ergänzt (Login-Request, Session-Abfrage via /auth/me, Fehler-Mapping und Session-Cache).
  • Routing für Auth ergänzt: neue geschützte Dashboard-Route (/) mit meta.requiresAuth, Login als guestOnly und globaler Guard in GUI/src/router/index.ts.
  • Neue Seite GUI/src/routes/dashboard/Dashboard.vue ergänzt, die die /auth/me-Nutzerdaten anzeigt.
  • GUI/src/routes/authentication/Login.vue von statischer Maske auf echten Login-Flow mit Loading-State, Fehlermeldung und Redirect nach erfolgreicher Anmeldung umgestellt.
  • Öffentliche Home/Landing-Route auf /welcome verschoben und Navigation in Layout.vue, 404NotFound.vue und Impressum.vue entsprechend angepasst.
  • GUI/src/services/authSession.ts um logout() für POST /auth/logout ergänzt; Session-Cache wird beim Abmelden zuverlässig geleert.
  • GUI/src/plugins/routesLayout.ts angepasst: Dashboard-Navigationseintrag als Dash mit Visibility.Authenticated und Reihenfolge hinter Startseite.
  • GUI/src/Layout.vue erweitert: Sidebar filtert jetzt auch Visibility.Authenticated/Visibility.Unauthenticated, zeigt Trennlinie vor Auth-Einträgen, Topbar zeigt Benutzernamen bei Login und bietet Abmelden (Desktop + Mobile) inkl. Fehler-Snackbar.
  • GUI/src/plugins/routesLayout.ts weiter angepasst: Startseite nutzt jetzt Visibility.Unauthenticated, damit sie in der Sidebar nach Login nicht mehr auswählbar ist.
  • GUI/src/Layout.vue Topbar angepasst: separater Logout-Button entfernt; Logout ist jetzt als Menüpunkt unter dem Benutzernamen verfügbar (open-on-hover auf Desktop, Menü auf Mobile).
  • GUI/src/routes/authentication/Login.vue um Alert-Polish ergänzt: Fehler-Alert nutzt eigene Klasse mit stabiler Mindesthöhe und erhöhter Zeilenhöhe, damit Meldungen vollständig sichtbar sind.
  • Neuer Store GUI/src/stores/appBanners.ts ergänzt: globale Meldungen können aus jeder Seite per push/pushError hinzugefügt und einzeln geschlossen werden.
  • GUI/src/Layout.vue auf globalen Banner-Stack umgestellt: mehrere Meldungen werden unten rechts gestapelt angezeigt und bleiben beim Navigieren erhalten.
  • GUI/src/routes/authentication/Login.vue von lokalem Inline-Fehler-Alert auf globale Banner-Meldungen umgestellt.
  • GUI/src/Layout.vue Banner-Polish: Banner-Hintergründe je Typ explizit opak getönt, Overlay-/Underlay-Transparenz deaktiviert und z-index auf 2100 zurückgesetzt.
  • GUI/src/Layout.vue Brand-Navigation ergänzt: Logo/Titel-Button nutzt jetzt navigateToBrandTarget() und leitet eingeloggte Nutzer auf Dashboard, sonst auf Home (/welcome).
  • GUI/src/routes/404NotFound.vue angepasst: primärer CTA zeigt jetzt Zum Dashboard (Route Dashboard), Text aktualisiert und navigateBack() fällt ohne History ebenfalls auf Dashboard zurück.
  • GUI/src/Layout.vue Brand-Navigation nachgeschärft: navigateToBrandTarget() löst bei Klick zuerst die Session via fetchCurrentUser() auf (falls lokal noch null) und verhindert dadurch Fehlnavigation auf Welcome; Mobile-Account-Menütext auf Zum Dashboard vereinheitlicht.
  • Neuer globaler Skill codexinfo-komprimieren unter C:/Users/famil/.codex/skills/codexinfo-komprimieren erstellt; er liest codexInfo.md, verdichtet Änderungen durch Codex auf drei Kernzeilen und enthält ein Hilfsskript zum robusten Abschnitts-Update.
  • GUI/src/routes/404NotFound.vue erweitert: Seite ermittelt beim Laden den Login-Status über fetchCurrentUser(), setzt CTA/Icon dynamisch auf Zum Dashboard oder Zur Startseite und leitet nach kurzer Verzögerung automatisch auf das passende Ziel weiter.
  • Rollenbasiertes Auth-Modell umgesetzt: IsAdmin aus AppUser/Konfiguration entfernt, neue Rolle-Konstante admin eingeführt und Admin-Prüfungen auf Policy/Rollen (API/Security/*, Authorize(Policy = admin-only)) umgestellt.
  • Neue Migration ReplaceIsAdminWithRoles (API/Migrations/20260420174609_ReplaceIsAdminWithRoles.cs) ergänzt: migriert bestehende Users.IsAdmin = true idempotent in UserRoles (admin) und entfernt anschließend die Spalte IsAdmin.
  • GET /auth/me liefert jetzt roles: string[] statt isAdmin; GUI/src/services/authSession.ts wurde auf Rollen normalisiert und um hasRole() ergänzt.
  • Frontend-Autorisierung erweitert: Router unterstützt meta.requiredRoles, neue 403-Seite GUI/src/routes/Forbidden.vue und admin-spezifische Route GUI/src/routes/admin/AdminUsers.vue werden nur für Rolle admin zugänglich/angezeigt.