Initial commit with inital CMS

This commit is contained in:
2026-06-15 17:00:16 +02:00
commit 95d986790e
132 changed files with 7624 additions and 0 deletions
@@ -0,0 +1,35 @@
# Auth Service Design — Unit 02: Identity & RBAC
Dit document beschrijft de `IAuthService` die verantwoordelijk is voor token-management.
## 1. Interface definitie
```csharp
public interface IAuthService
{
Task<TokenResponse> AuthenticateAsync(string email, string password);
Task<TokenResponse> RefreshTokenAsync(string accessToken, string refreshToken);
Task RevokeTokenAsync(string refreshToken);
}
```
## 2. JWT Configuratie
- **Signing Key**: Wordt uit de environment variable `JWT_SIGNING_KEY` gelezen.
- **Issuer/Audience**: Worden geconfigureerd in `appsettings.json`.
- **Claims**:
- `sub`: UserId.
- `email`: Gebruikers e-mail.
- `role`: Gebruikers rol (bijv. "Administrator").
- `exp`: Expiration time.
## 3. Refresh Token Rotation Logic
Bij een refresh request:
1. Valideer de `refreshToken` string tegen de database.
2. Controleer op Re-use: Indien de `IsUsed` vlag al op `true` staat, trek dan **alle** tokens van die gebruiker in (NFR-ID-SEC-03).
3. Indien geldig:
- Markeer huidig token als `IsUsed = true`.
- Genereer een nieuw cryptografisch veilig geheim (32 bytes Base64).
- Sla het nieuwe token op met een nieuwe `ExpiryDate`.
- Retourneer het nieuwe `AccessToken` en `RefreshToken`.
@@ -0,0 +1,52 @@
# Authorization Design — Unit 02: Identity & RBAC
Dit document beschrijft de technische implementatie van de hiërarchische autorisatie.
## 1. HierarchicalRoleRequirement
We maken gebruik van een custom requirement om rollen te vergelijken.
```csharp
public class HierarchicalRoleRequirement : IAuthorizationRequirement
{
public HierarchicalRoleRequirement(string minimumRequiredRole)
{
MinimumRequiredRole = minimumRequiredRole;
}
public string MinimumRequiredRole { get; }
}
```
## 2. HierarchicalRoleHandler
De handler valideert of de rollen-hiërarchie wordt gerespecteerd.
- **Logic**:
1. Haal de rol-claim op van de huidige gebruiker.
2. Haal de doel-gebruiker op uit de route of body.
3. Vergelijk de numerieke waarden van beide rollen.
4. Slaag alleen als de huidige gebruiker een hogere of gelijke rol heeft (afhankelijk van de actie).
## 3. Setup Endpoint Protection
Het `SetupController.Init` endpoint controleert direct in de database of er al een Owner bestaat:
```csharp
[HttpPost("init")]
public async Task<IActionResult> Init(SetupRequest request)
{
var anyOwner = await _userManager.GetUsersInRoleAsync("Owner");
if (anyOwner.Any())
{
return Forbidden("Systeem is reeds geïnitialiseerd.");
}
// Verwerk creatie...
}
```
## 4. Module-specifieke Policies
Er worden dynamische policies aangemaakt voor module-permissies:
- Patroon: `Module:{ModuleName}:{Permission}` (bijv. `Module:Blog:Delete`).
- De handler controleert de `ModulePermissions` tabel voor de huidige gebruiker.
@@ -0,0 +1,52 @@
# Database Design — Unit 02: Identity & RBAC
Dit document beschrijft de database schema configuratie voor de identiteitsmodule.
## 1. DbContext Mapping (Identity)
De `ApplicationDbContext` erft over van `IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid>`.
In `OnModelCreating` worden de tabelnamen geconfigureerd:
```csharp
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationUser>(entity => { entity.ToTable("Users"); });
builder.Entity<IdentityRole<Guid>>(entity => { entity.ToTable("Roles"); });
builder.Entity<IdentityUserRole<Guid>>(entity => { entity.ToTable("UserRoles"); });
builder.Entity<IdentityUserClaim<Guid>>(entity => { entity.ToTable("UserClaims"); });
builder.Entity<IdentityUserLogin<Guid>>(entity => { entity.ToTable("UserLogins"); });
builder.Entity<IdentityRoleClaim<Guid>>(entity => { entity.ToTable("RoleClaims"); });
builder.Entity<IdentityUserToken<Guid>>(entity => { entity.ToTable("UserTokens"); });
}
```
## 2. Aanvullende Tabellen
### RefreshTokens
- **Tabel**: `RefreshTokens`
- **PK**: `Id` (Guid)
- **FK**: `UserId` -> `Users.Id`
- **Index**: `Token` (Unique)
### Invitations
- **Tabel**: `Invitations`
- **PK**: `Id` (Guid)
- **Index**: `Token` (Unique)
- **Email**: `NVARCHAR(256)`
### ModulePermissions
- **Tabel**: `ModulePermissions`
- **Composite PK**: `(UserId, ModuleName, Permission)`
- **FK**: `UserId` -> `Users.Id`
## 3. Auditing (NFR-ID-SEC-03)
Er wordt een aparte `AuditLogs` tabel aangemaakt voor het loggen van mutaties:
- `Id` (Guid)
- `Timestamp` (DateTimeOffset)
- `ActorId` (Guid - De uitvoerder)
- `Action` (String - bijv. "RoleChange", "UserCreated")
- `EntityId` (Guid - Het doelobject)
- `Details` (JSON/String - Oude vs Nieuwe waarden)
@@ -0,0 +1,40 @@
# Invitation Design — Unit 02: Identity & RBAC
Dit document beschrijft de technische implementatie van het uitnodigingssysteem.
## 1. IInvitationService
```csharp
public interface IInvitationService
{
Task<string> CreateInvitationAsync(string email, string role);
Task<bool> ValidateInvitationAsync(string token);
Task CompleteInvitationAsync(string token, string password);
}
```
## 2. Token Generatie
Het `InvitationToken` wordt gegenereerd met de `RandomNumberGenerator`:
```csharp
public string GenerateSecureToken()
{
var bytes = new byte[32];
RandomNumberGenerator.Fill(bytes);
return Convert.ToBase64String(bytes);
}
```
## 3. Workflow Details
1. **Creatie**:
- Een `Invitation` record wordt aangemaakt in de database.
- Het `Token` wordt gehasht opgeslagen (net als een wachtwoord) om misbruik bij database-lekken te voorkomen.
2. **Validatie**:
- Het systeem zoekt het record op basis van de token-string.
- Controleert `ExpiryDate` en `IsAccepted`.
3. **Afronding**:
- Bij `CompleteInvitationAsync` wordt de `ApplicationUser` aangemaakt via de `UserManager`.
- De rol wordt toegekend.
- Het uitnodigingsrecord wordt gemarkeerd als `IsAccepted = true`.