Initial commit with inital CMS
This commit is contained in:
+38
@@ -0,0 +1,38 @@
|
||||
# Business Rules — Unit 02: Identity & RBAC
|
||||
|
||||
Dit document beschrijft de validatieregels en logica voor identiteitsbeheer en autorisatie.
|
||||
|
||||
## 1. Hiërarchische Rollen (BR-ID-01)
|
||||
|
||||
- **Hiërarchie**: Owner (100) > Administrator (50) > User (10).
|
||||
- **Beperking**: Een gebruiker kan alleen acties uitvoeren op gebruikers met een **lagere** rol in de hiërarchie.
|
||||
- Uitzondering: Een Owner kan acties uitvoeren op andere Owners (bijv. de-activeren, mits niet de laatste Owner).
|
||||
- Een Administrator kan een User beheren, maar geen andere Administrator of Owner.
|
||||
- **Rolverandering**: Een gebruiker kan een andere gebruiker nooit een rol toekennen die hoger is dan zijn eigen rol.
|
||||
|
||||
## 2. Gebruikerscreatie & Uitnodiging (BR-ID-02)
|
||||
|
||||
- **Geen Zelfregistratie**: Het systeem staat geen publieke registratie toe.
|
||||
- **Uitnodigingsflow**:
|
||||
1. Administrator/Owner maakt een uitnodiging aan (e-mail + rol).
|
||||
2. Systeem genereert een `InvitationToken` met een beperkte geldigheidsduur (bijv. 24 uur).
|
||||
3. Gebruiker moet via een specifiek endpoint (`POST /api/setup/complete-invitation`) zijn wachtwoord instellen met dit token.
|
||||
4. Na succesvolle instelling wordt het token ongeldig en het account geactiveerd.
|
||||
|
||||
## 3. Bootstrapping (BR-ID-03)
|
||||
|
||||
- **Setup Endpoint**: Bij een lege database is een eenmalig endpoint `POST /api/setup/init` beschikbaar.
|
||||
- **Eerste Owner**: Dit endpoint accepteert de gegevens voor de eerste Owner. Na succesvolle aanmaak wordt dit endpoint permanent geblokkeerd of verwijderd uit de routing.
|
||||
|
||||
## 4. Authenticatie & Sessies (BR-ID-04)
|
||||
|
||||
- **Wachtwoord Hashen**: Wachtwoorden moeten gehasht worden volgens de ASP.NET Core Identity standaard (PBKDF2 met HMAC-SHA256).
|
||||
- **Refresh Tokens**:
|
||||
- Refresh tokens zijn gekoppeld aan een specifieke gebruiker en client/apparaat.
|
||||
- Refresh tokens kunnen maar één keer worden gebruikt (Rotation-principe).
|
||||
- Bij gebruik van een oud refresh token worden alle actieve sessies van die gebruiker ongeldig gemaakt (beveiligingsmaatregel tegen token diefstal).
|
||||
|
||||
## 5. Module-specifieke Rechten (BR-ID-05)
|
||||
|
||||
- **Fine-grained Access**: Naast de globale rollen kunnen Beheerders specifieke rechten per module toekennen aan Users.
|
||||
- **Default**: Zonder expliciete module-rechten heeft een User alleen leesrechten of basisrechten binnen een module (afhankelijk van de module-implementatie).
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
# Domain Entities — Unit 02: Identity & RBAC
|
||||
|
||||
Dit document beschrijft de data-entiteiten die nodig zijn voor identiteitsbeheer.
|
||||
|
||||
## 1. ApplicationUser
|
||||
|
||||
Breidt de standaard `IdentityUser` uit.
|
||||
|
||||
- **Email**: Unieke identifier.
|
||||
- **Role**: De primaire hiërarchische rol (`Owner`, `Administrator`, `User`).
|
||||
- **IsActive**: Boolean status.
|
||||
- **CreatedAt**: Tijdstip van aanmaak.
|
||||
- **ModulePermissions**: Navigatie-eigenschap naar module-specifieke rechten.
|
||||
|
||||
## 2. RefreshToken
|
||||
|
||||
- **Id**: Guid.
|
||||
- **Token**: De gehashte token string.
|
||||
- **UserId**: Link naar de `ApplicationUser`.
|
||||
- **ExpiryDate**: Wanneer het token verloopt.
|
||||
- **IsUsed**: Boolean (voor re-use detection).
|
||||
- **IsRevoked**: Boolean (handmatige intrekking).
|
||||
- **CreatedByIp**: IP adres voor audit trail.
|
||||
|
||||
## 3. Invitation
|
||||
|
||||
- **Email**: Adres waar de uitnodiging naar verzonden is.
|
||||
- **Role**: De toegekende rol na acceptatie.
|
||||
- **Token**: Unieke GUID/String.
|
||||
- **ExpiryDate**: Geldigheidsduur van de uitnodiging.
|
||||
- **IsAccepted**: Boolean.
|
||||
|
||||
## 4. ModulePermission
|
||||
|
||||
- **UserId**: Link naar `ApplicationUser`.
|
||||
- **ModuleName**: Naam van de module.
|
||||
- **Permission**: De specifieke string-gebaseerde permissie (bijv. "Write", "Admin").
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
# Business Logic Model — Unit 02: Identity & RBAC
|
||||
|
||||
Dit document beschrijft de processen en datastromen voor authenticatie en autorisatie.
|
||||
|
||||
## 1. Authenticatie Flow (JWT)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client
|
||||
participant AuthController
|
||||
participant AuthService
|
||||
participant UserManager
|
||||
participant Database
|
||||
|
||||
Client->>AuthController: Login(Email, Password)
|
||||
AuthController->>AuthService: AuthenticateAsync(Email, Password)
|
||||
AuthService->>UserManager: FindByEmailAsync(Email)
|
||||
UserManager->>Database: Get User
|
||||
Database-->>UserManager: User Data
|
||||
UserManager->>UserManager: CheckPasswordAsync(User, Password)
|
||||
AuthService->>AuthService: GenerateTokens(User)
|
||||
AuthService->>Database: Save RefreshToken
|
||||
AuthService-->>AuthController: AccessToken, RefreshToken
|
||||
AuthController-->>Client: 200 OK (Tokens)
|
||||
```
|
||||
|
||||
## 2. Uitnodigingsproces
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Admin/Owner] -->|Create Invitation| B(InvitationService)
|
||||
B -->|Generate Token| C(InvitationToken)
|
||||
C -->|Save to DB| D[(Database)]
|
||||
B -->|Send Email| E[User]
|
||||
E -->|Click Link| F[Setup Page]
|
||||
F -->|Submit Password + Token| G(SetupController)
|
||||
G -->|Validate Token| B
|
||||
B -->|Create Account| H(UserManager)
|
||||
H -->|Activate User| D
|
||||
```
|
||||
|
||||
## 3. Hiërarchische Autorisatie Logic
|
||||
|
||||
De autorisatie wordt afgehandeld via ASP.NET Core `AuthorizationPolicies`.
|
||||
|
||||
- **Policy: `RequireLowerRole`**:
|
||||
- Haalt de rol van de huidige gebruiker (X) en de doelgebruiker (Y) op.
|
||||
- Vergelijkt de numerieke waarden van de rollen.
|
||||
- Slaagt alleen als `RoleValue(X) > RoleValue(Y)` (of `X == Y` en `X == Owner`).
|
||||
|
||||
## 4. Token Refresh Logic
|
||||
|
||||
1. Client stuurt `Expired Access Token` + `Refresh Token`.
|
||||
2. Systeem controleert of `Refresh Token` bestaat in de database en niet verlopen is.
|
||||
3. Systeem controleert of `Refresh Token` al eerder is gebruikt (Re-use detection).
|
||||
4. Indien geldig:
|
||||
- Genereer nieuw `Access Token`.
|
||||
- Genereer nieuw `Refresh Token` (Rotation).
|
||||
- Verwijder/Invalideer het oude `Refresh Token`.
|
||||
5. Indien ongeldig of re-use:
|
||||
- Trek alle tokens van de gebruiker in.
|
||||
- Retourneer `401 Unauthorized`.
|
||||
+35
@@ -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`.
|
||||
+52
@@ -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.
|
||||
+52
@@ -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)
|
||||
+40
@@ -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`.
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# NFR Requirements — Unit 02: Identity & RBAC
|
||||
|
||||
Dit document specificeert de non-functionele vereisten voor identiteitsbeheer en autorisatie.
|
||||
|
||||
## 1. Beveiliging (Security)
|
||||
|
||||
- **ID-SEC-01: Wachtwoordbeleid**:
|
||||
- Minimale lengte: 8 tekens.
|
||||
- Geen verplichte complexiteitseisen (hoofdletters/cijfers), focus op lengte voor gebruiksvriendelijkheid.
|
||||
- **ID-SEC-02: Token Lifecycle**:
|
||||
- Access Token (JWT) vervaltijd: 1 uur.
|
||||
- Refresh Token vervaltijd: 7 dagen.
|
||||
- **ID-SEC-03: Audit Logging**:
|
||||
- Verplichte persistente logging van:
|
||||
- Gebruikerscreatie en uitnodigingen.
|
||||
- Rolwijzigingen.
|
||||
- Activatie/Deactivatie van accounts.
|
||||
- Mislukte login pogingen.
|
||||
- **ID-SEC-04: Data Privacy**:
|
||||
- Wachtwoorden worden nooit in plain-text opgeslagen.
|
||||
- Persoonlijke gegevens (PII) worden alleen via HTTPS ontsloten.
|
||||
|
||||
## 2. Performance
|
||||
|
||||
- **ID-PERF-01: Token Validatie**:
|
||||
- De validatie van het JWT token bij elk request mag niet meer dan 5ms overhead toevoegen.
|
||||
- **ID-PERF-02: Database Querying**:
|
||||
- Het ophalen van een gebruiker inclusief rollen en permissies moet binnen 20ms gebeuren (geïndexeerd op Email).
|
||||
|
||||
## 3. Onderhoudbaarheid (Maintainability)
|
||||
|
||||
- **ID-MAINT-01: Database Schema**:
|
||||
- Gebruik van schone tabelnamen zonder `AspNet` prefix (bijv. `Users`, `Roles`, `UserRoles`).
|
||||
- **ID-MAINT-02: EF Core Migrations**:
|
||||
- Alle wijzigingen aan het identiteitsschema worden via code-first migrations bijgehouden.
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# Tech Stack Decisions — Unit 02: Identity & RBAC
|
||||
|
||||
Dit document beschrijft de definitieve technische keuzes voor Unit 02.
|
||||
|
||||
## 1. Core Frameworks
|
||||
|
||||
- **Identity**: Microsoft.AspNetCore.Identity.
|
||||
- **ORM**: Entity Framework Core.
|
||||
- **Database**: Microsoft SQL Server.
|
||||
|
||||
## 2. Authenticatie & Autorisatie
|
||||
|
||||
- **JWT Library**: Microsoft.AspNetCore.Authentication.JwtBearer.
|
||||
- **Policy Engine**: Native ASP.NET Core Authorization Policies & RequirementHandlers.
|
||||
- **Hashing**: PBKDF2 (standaard Identity).
|
||||
|
||||
## 3. Database Schema Mapping
|
||||
|
||||
Conform ID-MAINT-01 worden de standaard Identity tabellen hernoemd in de `OnModelCreating` van de `DbContext`:
|
||||
|
||||
| Standaard Naam | Nieuwe Naam |
|
||||
|---|---|
|
||||
| AspNetUsers | Users |
|
||||
| AspNetRoles | Roles |
|
||||
| AspNetUserRoles | UserRoles |
|
||||
| AspNetUserClaims | UserClaims |
|
||||
| AspNetUserLogins | UserLogins |
|
||||
| AspNetRoleClaims | RoleClaims |
|
||||
| AspNetUserTokens | UserTokens |
|
||||
|
||||
## 4. Testing Tools
|
||||
|
||||
- **Unit Tests**: xUnit + FluentAssertions + NSubstitute.
|
||||
- **Data Generation**: AutoFixture.
|
||||
- **PBT**: FsCheck (alleen voor token-logic en mapping functies, conform NFR-06).
|
||||
Reference in New Issue
Block a user