Architektur Übersicht aktualisiert

Daniel Krähenbühl
2026-05-20 12:17:57 +02:00
parent 54a7744080
commit 4c5c8b94d5
@@ -1,122 +1,122 @@
# Architektur-Übersicht
## Stack
| Schicht | Technologie |
|---|---|
| Frontend | Angular 21, Standalone Components, Signals |
| Styling | Tailwind CSS v4, Flowbite Design System |
| Charts | ApexCharts 3.46 |
| i18n | ngx-translate (DE, FR, IT, EN) |
| Backend | Django REST Framework, Python 3.12 |
| Auth | SimpleJWT (Access 60min, Refresh 7d, Rotation + Blacklist) |
| Datenbank | PostgreSQL |
| E-Mail | Brevo SMTP (`smtp-relay.brevo.com:587`) |
| Server | Hetzner Ubuntu 24.04, Gunicorn + Nginx, Certbot (HTTPS) |
| Font | Roboto via `@fontsource/roboto` (selbst-gehostet, DSGVO-konform) |
## Verzeichnisstruktur
```
armarium-suite/
├── backend/
│ ├── core/ # Django-Projektkonfiguration (settings, urls)
│ ├── finance/ # Haupt-App (Models, Views, Serializers)
│ │ ├── migrations/
│ │ ├── models.py
│ │ ├── views.py
│ │ ├── serializers.py
│ │ ├── email.py # send_email() Helper
│ │ └── backends.py # EmailAuthBackend
│ ├── templates/emails/ # HTML + Plaintext E-Mail-Templates
│ ├── requirements.txt
│ └── .env # Nicht im Repo
└── frontend/
├── src/app/
│ ├── auth/ # Login, Register, ForgotPassword, ResetPassword, VerifyEmail
│ ├── dashboard/
│ ├── services/ # ApiService, AuthService, FinancialYearService, ...
│ ├── layout/ # Shell, Navbar, Sidebar
│ └── ...
├── src/assets/i18n/ # de.json, en.json, fr.json, it.json
└── src/budget-app-theme.css # Tailwind v4 Custom Theme (Violet Primary)
```
## Datenmodelle
| Modell | Beschreibung |
|---|---|
| `Profile` | Erweitertes User-Profil (Avatar, Kanton, 2FA, Tokens, Prefs) |
| `Account` | Konten (asset, expense, revenue) |
| `Transaction` | Doppelte Buchführung (source + destination Account) |
| `Budget` | Budgetkategorien (7 Kategorien) |
| `Expense` | Ausgaben mit Fälligkeitsdatum |
| `Deadline` | Termine (Steuern, Versicherung, Rechnung, etc.) |
| `UserSession` | Aktive Sessions mit Gerätename, IP, JWT-JTI |
| `BackupCode` | 2FA-Backup-Codes (SHA-256-Hash) |
| `FinancialYear` | Jahresplanung (User oder Haushalt) |
| `YearlyIncome` | Einnahmen pro Jahr |
| `YearlyBudgetItem` | Fixkosten pro Jahr |
| `Household` | Gemeinsamer Haushalt |
| `HouseholdMembership` | Haushalt-Mitgliedschaft mit Rolle und Status |
## API-Endpunkte (Übersicht)
### Auth
| Methode | Endpunkt | Beschreibung |
|---|---|---|
| POST | `/api/auth/register/` | Registrierung (sendet Bestätigungsmail) |
| POST | `/api/auth/verify-email/` | E-Mail bestätigen |
| POST | `/api/auth/token/` | Login |
| POST | `/api/auth/token/refresh/` | JWT erneuern |
| POST | `/api/auth/logout/` | Logout + Blacklist |
| POST | `/api/auth/password/` | Passwort ändern |
| POST | `/api/auth/password-reset/` | Reset anfordern |
| POST | `/api/auth/password-reset/confirm/` | Neues Passwort setzen |
| POST | `/api/auth/2fa/login/` | TOTP-Verifikation |
| POST | `/api/auth/2fa/setup/` | 2FA einrichten |
| POST | `/api/auth/2fa/enable/` | 2FA aktivieren |
| POST | `/api/auth/2fa/disable/` | 2FA deaktivieren |
| POST | `/api/auth/2fa/recover/` | Recovery-Code anfordern |
| POST | `/api/auth/2fa/recover/confirm/` | Recovery bestätigen |
| GET | `/api/auth/sessions/` | Session-Liste |
| DELETE | `/api/auth/sessions/<key>/` | Session widerrufen |
| DELETE | `/api/auth/sessions/revoke-all/` | Alle anderen Sessions widerrufen |
### Daten
| Methode | Endpunkt | Beschreibung |
|---|---|---|
| GET/PUT | `/api/profile/` | Profil lesen/aktualisieren |
| GET/POST/PUT/DELETE | `/api/accounts/` | Konten |
| GET/POST/PUT/DELETE | `/api/transactions/` | Transaktionen |
| GET/POST/PUT/DELETE | `/api/budgets/` | Budgets |
| GET/POST/PUT/DELETE | `/api/expenses/` | Ausgaben |
| GET/POST/PUT/DELETE | `/api/deadlines/` | Termine |
| GET | `/api/export/` | ZIP-Export (6 PDFs) |
| GET | `/api/search/` | Globale Suche |
| GET | `/api/notifications/` | Benachrichtigungen |
| PATCH | `/api/notifications/prefs/` | Benachrichtigungs-Prefs |
### Jahresplanung
| Methode | Endpunkt | Beschreibung |
|---|---|---|
| GET/POST | `/api/financial-years/` | Jahre auflisten / erstellen |
| GET/PATCH/DELETE | `/api/financial-years/<year>/` | Jahr-Detail |
| POST | `/api/financial-years/<year>/copy-from/<source>/` | Jahr kopieren |
| GET/POST | `/api/financial-years/<year>/incomes/` | Einnahmen |
| GET/POST | `/api/financial-years/<year>/budget-items/` | Fixkosten |
| GET/POST | `/api/households/` | Haushalte |
| POST | `/api/households/<pk>/invite/` | Mitglied einladen |
| POST | `/api/households/<pk>/accept/` | Einladung annehmen |
| POST | `/api/households/<pk>/leave/` | Haushalt verlassen |
## Sicherheits-Architektur
- **JWT**: Access-Token 60min, Refresh-Token 7 Tage, Rotation + Blacklist
- **2FA**: TOTP (pyotp), HMAC-signierter Temp-Token (5min), Replay-Schutz, 8 Backup-Codes (SHA-256)
- **Passwort-Reset**: Token als SHA-256-Hash in DB, 15min TTL, anti-enumeration Response
- **E-Mail-Verifikation**: Token als SHA-256-Hash, 24h TTL
- **Rate-Limiting**: 5/min Auth, 200/min User, 20/min Anon
- **Sessions**: Alle Sessions werden bei Passwortänderung/-reset invalidiert
- **Produktion**: HTTPS-Redirect, HSTS (1 Jahr), Secure Cookies, Content-Type-Nosniff
- **CAPTCHA**: Cloudflare Turnstile auf Login + Register
# Architektur-Übersicht
## Stack
| Schicht | Technologie |
|---|---|
| Frontend | Angular 21, Standalone Components, Signals |
| Styling | Tailwind CSS v4, Flowbite Design System |
| Charts | ApexCharts 3.46 |
| i18n | ngx-translate (DE, FR, IT, EN) |
| Backend | Django REST Framework, Python 3.12 |
| Auth | SimpleJWT (Access 60min, Refresh 7d, Rotation + Blacklist) |
| Datenbank | PostgreSQL |
| E-Mail | Brevo SMTP (`smtp-relay.brevo.com:587`) |
| Server | Hetzner Ubuntu 24.04, Gunicorn + Nginx, Certbot (HTTPS) |
| Font | Roboto via `@fontsource/roboto` (selbst-gehostet, DSGVO-konform) |
## Verzeichnisstruktur
```
armarium-suite/
├── backend/
│ ├── core/ # Django-Projektkonfiguration (settings, urls)
│ ├── finance/ # Haupt-App (Models, Views, Serializers)
│ │ ├── migrations/
│ │ ├── models.py
│ │ ├── views.py
│ │ ├── serializers.py
│ │ ├── email.py # send_email() Helper
│ │ └── backends.py # EmailAuthBackend
│ ├── templates/emails/ # HTML + Plaintext E-Mail-Templates
│ ├── requirements.txt
│ └── .env # Nicht im Repo
└── frontend/
├── src/app/
│ ├── auth/ # Login, Register, ForgotPassword, ResetPassword, VerifyEmail
│ ├── dashboard/
│ ├── services/ # ApiService, AuthService, FinancialYearService, ...
│ ├── layout/ # Shell, Navbar, Sidebar
│ └── ...
├── src/assets/i18n/ # de.json, en.json, fr.json, it.json
└── src/budget-app-theme.css # Tailwind v4 Custom Theme (Violet Primary)
```
## Datenmodelle
| Modell | Beschreibung |
|---|---|
| `Profile` | Erweitertes User-Profil (Avatar, Kanton, 2FA, Tokens, Prefs) |
| `Account` | Konten (asset, expense, revenue) |
| `Transaction` | Doppelte Buchführung (source + destination Account) |
| `Budget` | Budgetkategorien (7 Kategorien) |
| `Expense` | Ausgaben mit Fälligkeitsdatum |
| `Deadline` | Termine (Steuern, Versicherung, Rechnung, etc.) |
| `UserSession` | Aktive Sessions mit Gerätename, IP, JWT-JTI |
| `BackupCode` | 2FA-Backup-Codes (SHA-256-Hash) |
| `FinancialYear` | Jahresplanung (User oder Haushalt) |
| `YearlyIncome` | Einnahmen pro Jahr |
| `YearlyBudgetItem` | Fixkosten pro Jahr |
| `Household` | Gemeinsamer Haushalt |
| `HouseholdMembership` | Haushalt-Mitgliedschaft mit Rolle und Status |
## API-Endpunkte (Übersicht)
### Auth
| Methode | Endpunkt | Beschreibung |
|---|---|---|
| POST | `/api/auth/register/` | Registrierung (sendet Bestätigungsmail) |
| POST | `/api/auth/verify-email/` | E-Mail bestätigen |
| POST | `/api/auth/token/` | Login |
| POST | `/api/auth/token/refresh/` | JWT erneuern |
| POST | `/api/auth/logout/` | Logout + Blacklist |
| POST | `/api/auth/password/` | Passwort ändern |
| POST | `/api/auth/password-reset/` | Reset anfordern |
| POST | `/api/auth/password-reset/confirm/` | Neues Passwort setzen |
| POST | `/api/auth/2fa/login/` | TOTP-Verifikation |
| POST | `/api/auth/2fa/setup/` | 2FA einrichten |
| POST | `/api/auth/2fa/enable/` | 2FA aktivieren |
| POST | `/api/auth/2fa/disable/` | 2FA deaktivieren |
| POST | `/api/auth/2fa/recover/` | Recovery-Code anfordern |
| POST | `/api/auth/2fa/recover/confirm/` | Recovery bestätigen |
| GET | `/api/auth/sessions/` | Session-Liste |
| DELETE | `/api/auth/sessions/<key>/` | Session widerrufen |
| DELETE | `/api/auth/sessions/revoke-all/` | Alle anderen Sessions widerrufen |
### Daten
| Methode | Endpunkt | Beschreibung |
|---|---|---|
| GET/PUT | `/api/profile/` | Profil lesen/aktualisieren |
| GET/POST/PUT/DELETE | `/api/accounts/` | Konten |
| GET/POST/PUT/DELETE | `/api/transactions/` | Transaktionen |
| GET/POST/PUT/DELETE | `/api/budgets/` | Budgets |
| GET/POST/PUT/DELETE | `/api/expenses/` | Ausgaben |
| GET/POST/PUT/DELETE | `/api/deadlines/` | Termine |
| GET | `/api/export/` | ZIP-Export (6 PDFs) |
| GET | `/api/search/` | Globale Suche |
| GET | `/api/notifications/` | Benachrichtigungen |
| PATCH | `/api/notifications/prefs/` | Benachrichtigungs-Prefs |
### Jahresplanung
| Methode | Endpunkt | Beschreibung |
|---|---|---|
| GET/POST | `/api/financial-years/` | Jahre auflisten / erstellen |
| GET/PATCH/DELETE | `/api/financial-years/<year>/` | Jahr-Detail |
| POST | `/api/financial-years/<year>/copy-from/<source>/` | Jahr kopieren |
| GET/POST | `/api/financial-years/<year>/incomes/` | Einnahmen |
| GET/POST | `/api/financial-years/<year>/budget-items/` | Fixkosten |
| GET/POST | `/api/households/` | Haushalte |
| POST | `/api/households/<pk>/invite/` | Mitglied einladen |
| POST | `/api/households/<pk>/accept/` | Einladung annehmen |
| POST | `/api/households/<pk>/leave/` | Haushalt verlassen |
## Sicherheits-Architektur
- **JWT**: Access-Token 60min, Refresh-Token 7 Tage, Rotation + Blacklist
- **2FA**: TOTP (pyotp), HMAC-signierter Temp-Token (5min), Replay-Schutz, 8 Backup-Codes (SHA-256)
- **Passwort-Reset**: Token als SHA-256-Hash in DB, 15min TTL, anti-enumeration Response
- **E-Mail-Verifikation**: Token als SHA-256-Hash, 24h TTL
- **Rate-Limiting**: 5/min Auth, 200/min User, 20/min Anon
- **Sessions**: Alle Sessions werden bei Passwortänderung/-reset invalidiert
- **Produktion**: HTTPS-Redirect, HSTS (1 Jahr), Secure Cookies, Content-Type-Nosniff
- **CAPTCHA**: Cloudflare Turnstile auf Login + Register