233 lines
6.5 KiB
Markdown
233 lines
6.5 KiB
Markdown
# 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 <repo-url>
|
||
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" "<dein-passwort>"
|
||
dotnet user-secrets set "PostgreSqlSettings:Host" "localhost"
|
||
dotnet user-secrets set "EmailSettings:From" "deine-email@gmail.com"
|
||
dotnet user-secrets set "EmailSettings:Password" "<app-passwort>"
|
||
```
|
||
|
||
> 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.
|