# DotNetAngular Full-Stack Webanwendung mit **ASP.NET Core (.NET 10)** und **Angular 21**, basierend auf **Clean Architecture** mit **PostgreSQL** als Datenbank. --- ## Architektur ``` src/ ├── API # ASP.NET Core Web API (Controller, Middleware, Swagger) ├── Application # Anwendungslogik (Services, DTOs, Validatoren) ├── Domain # Entitäten, Repository-Interfaces, Value Objects └── Infrastructure # EF Core DbContext, Repositories, Migrations tests/ ├── Application.UnitTest # xUnit-Unit-Tests └── Application.FunctionalTest # xUnit-Funktionstests ``` ### Patterns - **Clean Architecture** mit 4 Schichten (API → Application → Domain ← Infrastructure) - **Repository & Unit of Work** Pattern - **Result Pattern** für explizite Erfolgs-/Fehlerrückgaben (keine Exceptions für Flow-Control) - **FluentValidation** für Request-Validierung - **JWT-Authentifizierung** mit Refresh-Token - **Role-Based Access Control** (SuperAdmin, Admin, User) --- ## Technologien | Bereich | Technologie | Version | |---|---|---| | **Backend** | ASP.NET Core | .NET 10 | | **ORM** | Entity Framework Core | 10.0.7 | | **Datenbank** | PostgreSQL (Npgsql) | 10.0.1 | | **Auth** | JWT Bearer (System.IdentityModel.Tokens.Jwt) | 8.18.0 | | **Validierung** | FluentValidation | 12.1.1 | | **E-Mail** | MailKit / MimeKit | 4.16.0 | | **API-Dokumentation** | Swagger (Swashbuckle) | 10.1.7 | | **Frontend** | Angular (Standalone Components) | 21.2 | | **UI-Framework** | Bootstrap + Bootstrap Icons | 5.3.8 / 1.13.1 | | **JWT Frontend** | @auth0/angular-jwt | 5.2.0 | | **Tests Backend** | xUnit v3 | 3.2.2 | | **Tests Frontend** | Karma + Jasmine | 6.4 / 5.2 | --- ## Features - **Registrierung & Login** mit JWT-Token (Access + Refresh Token) - **Passwort-Reset** per E-Mail (MailKit, HTML-Template) - **Rollensystem**: SuperAdmin, Admin, User - **Benutzerverwaltung**: CRUD, Rollenzuweisung/-entzug - **Paginierte Benutzerliste** - **Dark Mode** - **Toast-Benachrichtigungen** - **Route-Guards** (Authenticated, Admin, Guest) - **Token-Interceptor** mit automatischem Refresh bei 401 --- ## Voraussetzungen - [.NET 10 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/10.0) - [Node.js (LTS)](https://nodejs.org/) (≥18) - [Angular CLI](https://angular.dev/tools/cli) - PostgreSQL (lokal oder per Docker) - Ein Chrome/Chromium für Headless-Tests --- ## Setup ### 1. Repository klonen ```bash git clone cd DotNetAngular ``` ### 2. Angular-Abhängigkeiten installieren ```bash cd src/ClientApp npm install cd ../.. ``` ### 3. Datenbank konfigurieren Die Verbindungsdaten werden über **User Secrets** gesetzt: ```bash cd src/API dotnet user-secrets set "PostgreSqlSettings:Password" "" dotnet user-secrets set "PostgreSqlSettings:Host" "localhost" dotnet user-secrets set "EmailSettings:From" "deine-email@gmail.com" dotnet user-secrets set "EmailSettings:Password" "" ``` > Standard-Datenbank: `template_db`, Standard-User: `natlinux` (aus `appsettings.json`). ### 4. Datenbank erstellen ```bash dotnet ef database update ``` > `dotnet-ef` ist als lokales Tool in `dotnet-tools.json` definiert. ### 5. Anwendung starten **Mit Angular-Dev-Proxy (empfohlen):** ```bash cd src/API dotnet run --launch-profile Angular_dev ``` - Angular Frontend: [http://localhost:44492](http://localhost:44492) - API (direkt): [http://localhost:5184](http://localhost:5184) / [https://localhost:7091](https://localhost:7091) **Nur API mit Swagger:** ```bash dotnet run --launch-profile swagger_dev ``` - Swagger UI: [https://localhost:7091/swagger](https://localhost:7091/swagger) --- ## Tests **Status:** 76 .NET-Tests + 132 Angular-Tests — alle grün. ### Backend (xUnit) ```bash # Alle Tests dotnet test # Nur Unit-Tests dotnet test tests/Application.UnitTest # Nur Funktionstests dotnet test tests/Application.FunctionalTest ``` Getestete Komponenten: `Result`/`PagedResult` (Edge Cases), `JwtService` (Token-Generierung, Refresh-Validierung), `EmailService` (SMTP-Interaktion), `AuthenticationService`. ### Frontend (Karma + Jasmine) ```bash cd src/ClientApp # Interaktiv (Browser) npm test # Headless CI npm run test:ci # Mit Coverage npm run test:coverage # Report: src/ClientApp/coverage/index.html ``` ```bash # Headless (benötigt Chromium-Pfad) CHROME_BIN=/usr/bin/chromium npx ng test --no-watch --browsers=ChromeHeadless ``` Getestete Komponenten: `tokenInterceptor` (401-Refresh-Flow), `HeaderComponent` (Logout/Rolle/Username), `authService` (HTTP-Login/Register/Renew), `DarkModeService` (localStorage-Persistenz), `ToastComponent` (Auto-Dismiss), `PopupModalComponent` (Inputs/Outputs), `ForgetPasswordPopupComponent` (Close/Error/Success). --- ## NPM-Skripte (Frontend) | Befehl | Beschreibung | |---|---| | `npm start` | `ng serve --port 44492` | | `npm run build` | Produktions-Build | | `npm test` | Tests (Watch-Modus) | | `npm run test:ci` | Headless CI-Tests | | `npm run test:coverage` | Tests mit Coverage | | `npm run watch` | Dev-Build mit Watch | --- ## API-Endpunkte Basis: `http://localhost:5184/api` (Dev) / `https://localhost:7091/api` ### Auth (`/api/auth`) | Methode | Pfad | Auth | Beschreibung | |---|---|---|---| | POST | `/register` | - | Benutzer registrieren | | POST | `/login` | - | Login (gibt JWT + Refresh-Token) | | POST | `/refresh-token` | - | Access-Token erneuern | | POST | `/send-reset-email/{email}` | - | Passwort-Reset-Mail senden | | POST | `/reset-password` | - | Passwort zurücksetzen | ### User (`/api/user`) | Methode | Pfad | Auth | Beschreibung | |---|---|---|---| | GET | `/` | Admin/SuperAdmin | Paginierte Benutzerliste | | GET | `/{id}` | Authenticated | Benutzer per ID | | PUT | `/` | Authenticated | Benutzer aktualisieren | | DELETE | `/{id}` | Authenticated | Benutzer löschen (außer sich selbst) | | POST | `/assign-role` | SuperAdmin | Rolle zuweisen | | DELETE | `/revoke-role` | SuperAdmin | Rolle entziehen | --- ## Standard-Rollen | Rolle | ID | Berechtigungen | |---|---|---| | SuperAdmin | 1 | Vollzugriff, Rollenverwaltung | | Admin | 2 | Benutzerliste, Dashboard | | User | 3 | Eigenes Dashboard, Profil bearbeiten | Seed-Daten: SuperAdmin (ID 1) und Admin (ID 2) werden automatisch angelegt. --- ## Hinweise - Der JWT-Secret-Key in `appsettings.json` ist ein Platzhalter und sollte in Produktion überschrieben werden (z. B. über User Secrets, Umgebungsvariablen oder `appsettings.Production.json`). - E-Mail-Versand verwendet Gmail SMTP – es wird ein [App-Passwort](https://support.google.com/accounts/answer/185833) benötigt.