FMwerkstatt DevLog #2 – Architektur, Fortschritt und Dashboard

Nach dem ersten Grundgerüst und den ersten Modulen haben wir in den letzten Wochen die Architektur von FMwerkstatt deutlich weiterentwickelt.
Das Projekt ist gewachsen, strukturierter geworden und bildet nun eine solide Basis für alle kommenden Features — von Multi-Tenancy über Authentifizierung bis hin zum SuperAdmin-Dashboard.

Architektur

Ich habe die Struktur erwetiert so das wir Clean Architecture treu sind:

  • FMwerkstatt.Web – Blazor Server Frontend mit komponentenbasierter, modularer Oberfläche
  • FMwerkstatt.Api – REST API mit Authentifizierung, Authorization (JWT) und Tenant-Handling
  • FMwerkstatt.Infrastructure – Datenbankzugriff (EF Core 9), Repositories, Seeding und externe Services
  • FMwerkstatt.Domain – Kernlogik, Entities, Aggregates und Geschäftsregeln
  • FMwerkstatt.Shared – Gemeinsame DTOs, Enums und Konstanten zwischen API und Frontend
  • FMwerkstatt.SharedKernel – Domain-übergreifende Basiskomponenten wie Value Objects, Result-Objekte und Basisentitäten

Datenbankstruktur

Wir haben die Datenbankstruktur überarbeitet und klar in drei Bounded Contexts aufgeteilt.
Damit ist das System jetzt deutlich übersichtlicher und besser wartbar. Es gibt nun den Identity-Kontext für Benutzer, Rollen und Berechtigungen, den Provider-Kontext für Mandanten- und Abonnementverwaltung sowie den WorkManagement-Kontext, in dem später alle Arbeitsaufträge, Tickets und Objekte verwaltet werden.
Diese Trennung sorgt dafür, dass jede Domäne unabhängig weiterentwickelt werden kann, ohne dass sich Änderungen gegenseitig beeinflussen.

Rollen und Persmissions

Wir haben ein zweigeteiltes Rollen- und Berechtigungssystem umgesetzt.
Die Rollen sind systemweit fest definiert – SuperAdmin, SuperAgent, TenantAdmin und User – und bilden die vier Hauptkategorien für alle Zugriffsstufen.
Das Permissionssystem arbeitet unabhängig davon und steuert fein granular, welche Aktionen innerhalb einer Rolle erlaubt sind.
Dadurch lassen sich Rollen klar abgrenzen, während Berechtigungen flexibel kombiniert und erweitert werden können, ohne das Rollensystem selbst zu verändern.

// Beispiel: Systemweit definierte Rollen
public static class SystemRoles
{
    public const string SuperAdmin = "SuperAdmin";
    public const string SuperAgent = "SuperAgent";
    public const string TenantAdmin = "TenantAdmin";
    public const string User = "User";
}

// Beispiel: Definierte Berechtigungen
public static class Permissions
{
    public const string ManageTenants = "tenant.manage";
    public const string ManageUsers = "user.manage";
    public const string ViewWorkOrders = "workorder.view";
    public const string EditWorkOrders = "workorder.edit";
}

// Beispiel: Zuordnung von Berechtigungen zu Rollen
public static class RolePermissions
{
    public static readonly Dictionary<string, string[]> Mapping = new()
    {
        [SystemRoles.SuperAdmin] = new[] 
        { 
            Permissions.ManageTenants, 
            Permissions.ManageUsers, 
            Permissions.ViewWorkOrders, 
            Permissions.EditWorkOrders 
        },

        [SystemRoles.SuperAgent] = new[]
        { 
            Permissions.ManageUsers, 
            Permissions.ViewWorkOrders 
        },

        [SystemRoles.TenantAdmin] = new[]
        { 
            Permissions.ManageUsers, 
            Permissions.ViewWorkOrders, 
            Permissions.EditWorkOrders 
        },

        [SystemRoles.User] = new[]
        { 
            Permissions.ViewWorkOrders 
        }
    };
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace FMwerkstatt.Api.Controllers;

[ApiController]
[Route("api/[controller]")]
public class WorkOrdersController : ControllerBase
{
    // Zugriff nur für Benutzer mit der Rolle "TenantAdmin"
    [Authorize(Roles = "TenantAdmin")]
    [HttpPost("create")]
    public IActionResult CreateWorkOrder()
    {
        return Ok("Work order created.");
    }

    // Zugriff nur für Benutzer mit einer bestimmten Permission
    [Authorize(Policy = "workorder.edit")]
    [HttpPut("{id:guid}")]
    public IActionResult EditWorkOrder(Guid id)
    {
        return Ok($"Work order {id} updated.");
    }

    // Zugriff für mehrere Rollen
    [Authorize(Roles = "SuperAdmin,SuperAgent")]
    [HttpGet("overview")]
    public IActionResult GetSystemOverview()
    {
        return Ok("System overview data.");
    }
}

Frontend / SuperAdmin Bereich

Wir haben jetzt auch den SuperAdmin-Bereich umgesetzt, über den das komplette Tenant-Management gesteuert wird.
SuperAdmins können dort alle Mandanten einsehen, Details aufrufen und in einem übersichtlichen Dashboard Informationen wie Plan, Benutzeranzahl, Status oder Abrechnungsdaten einsehen.
Von hier aus lassen sich künftig auch weitere Bereiche wie Benutzerverwaltung, Abonnements oder Systemeinstellungen pro Tenant öffnen.
Das Dashboard ist modular aufgebaut und wird Schritt für Schritt erweitert – als Nächstes folgen die Detailseiten für jeden Abschnitt, z. B. „Users & Roles“ oder „Billing“.
Der Screenshot zeigt die aktuelle Version dieser Oberfläche.

Damit sind wir fürs Erste ganz gut vorangekommen. Der SuperAdmin-Bereich läuft, das Dashboard steht und die Basis fürs Rollen- und Berechtigungssystem funktioniert so, wie wir’s wollten.
Als Nächstes geht’s dann an die einzelnen Detailseiten – da kommt also noch einiges dazu.

Schreibe einen Kommentar