Initial commit on Test branch

This commit is contained in:
openclaw committed 2026-10-16 16:33:34 +02:00
1 parent b23e92360b
commit c89833b3b5
1 file changed
+1 -160
+1 -160
View File
@@ -1,160 +1 @@
# Familienplaner
Digitaler Familienplaner als Progressive Web App: Einkaufsliste, Essenplan, Aufgaben & Ämtchen, Familienkalender
(inkl. Abo für iPhone/Outlook) und Chat – für Smartphone, Tablet und Desktop.
> **Status:** Phasen 1–6 sind umgesetzt: Login, Rollenmatrix, Benutzerverwaltung, Familieneinstellungen, Audit-Log,
> Einkaufslisten (Echtzeit, offline nutzbar), Essenplan (Wochenraster, Wünsche der Kinder, Zutaten auf die Einkaufsliste),
> Aufgaben & Ämtchen (Wiederholungen, Eltern-Bestätigung, Punkte, Kinderansicht, offline erfassbar, Push-Erinnerungen vorbereitet),
> Familienkalender (mehrere Kalender mit Rechten, Serien mit Ausnahmen, Agenda/Tag/Woche/Monat, Abo für iPhone/Outlook, ICS-Import),
> PWA-Grundgerüst, Aspire- und Docker-Betrieb.
> Die Fachfunktionen folgen phasenweise, siehe [`docs/ROADMAP.md`](docs/ROADMAP.md).
* Architektur: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
* Entscheidungen: [`docs/adr/`](docs/adr/)
## Voraussetzungen (Entwicklung)
* .NET SDK 10 (getestet mit 10.0.300)
* Docker Desktop bzw. Docker Engine (für SQL Server)
* optional: Aspire CLI (`aspire run`)
## Entwicklung
```bash
dotnet tool restore
aspire run # oder: dotnet run --project src/FamilyPlanner.AppHost
```
Das Aspire-Dashboard öffnet sich automatisch (Login-Link steht in der Konsole). Die App läuft unter
<https://localhost:7264>. Beim ersten Start wird der SQL-Server-Container mit persistentem Volume angelegt,
der MigrationService migriert die Datenbank und legt den Initial-Admin an:
| Benutzer | Passwort | Hinweis |
|---|---|---|
| `admin` | `Admin123!ChangeMe` | nur lokal (`src/FamilyPlanner.AppHost/appsettings.Development.json`), muss beim ersten Login geändert werden |
Das Passwort lässt sich per User Secrets überschreiben:
`dotnet user-secrets set "Parameters:seed-admin-password" "..." --project src/FamilyPlanner.AppHost`.
### Push-Erinnerungen (optional)
Erinnerungen an Aufgaben kommen per Web Push ([ADR-0014](docs/adr/0014-aufgaben-und-aemtchen.md)). Dafür braucht der Server ein
VAPID-Schlüsselpaar – ohne Schlüssel ist die Funktion ausgeschaltet. Schlüssel erzeugen und lokal als Aspire-Parameter hinterlegen:
```bash
dotnet run tools/generate-vapid-keys.cs # gibt Schlüssel + passende user-secrets-Befehle aus (nicht einchecken!)
cd src/FamilyPlanner.AppHost
dotnet user-secrets set "Parameters:vapid-public-key" "<öffentlicher Schlüssel>"
dotnet user-secrets set "Parameters:vapid-private-key" "<privater Schlüssel>"
```
Danach kann jedes Familienmitglied im Benutzermenü unter **Benachrichtigungen** Erinnerungen für sein Gerät aktivieren
(iPhone/iPad: erst „Zum Home-Bildschirm“ hinzufügen, dann in der installierten App aktivieren).
### Tests
```bash
dotnet build FamilyPlanner.slnx
dotnet test --solution FamilyPlanner.slnx # Integrationstests benötigen Docker
```
## Produktivbetrieb (Docker Compose)
```bash
cd deploy
cp .env.example .env # Passwörter und Domain anpassen
docker compose up -d --build # ohne Reverse Proxy, Web auf 127.0.0.1:8080
# oder mit automatischem HTTPS (Caddy + Let's Encrypt, Ports 80/443):
docker compose --profile proxy up -d --build
```
Die App benötigt **HTTPS** (sichere Cookies). Ohne Caddy funktioniert der Login nur über `http://localhost` oder hinter
einem eigenen Reverse Proxy mit TLS.
### Konfiguration (`deploy/.env`)
| Variable | Bedeutung |
|---|---|
| `SQL_SA_PASSWORD` | Passwort des SQL-Server-Administrators (komplex, min. 8 Zeichen) |
| `MSSQL_PID` | SQL-Server-Edition (`Express` = kostenlos) |
| `ADMIN_USERNAME`, `ADMIN_PASSWORD`, `ADMIN_EMAIL` | Initial-Admin, nur beim allerersten Start; Passwortwechsel wird erzwungen |
| `FAMILY_NAME` | Familienname (Vorbelegung der Familieneinstellungen beim ersten Start) |
| `WEB_BIND`, `WEB_PORT` | Host-Bindung des Web-Containers ohne Caddy |
| `DOMAIN` | Domain für Caddy/Let's Encrypt (Profil `proxy`) |
| `REGISTRY`, `TAG` | optionales Image-Präfix und Tag |
| `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `VAPID_SUBJECT` | optional: Web-Push-Erinnerungen (Schlüssel mit `dotnet run tools/generate-vapid-keys.cs`); leer = aus |
Weitere Einstellungen (alle Dienste) folgen der ASP.NET-Core-Konvention `Abschnitt__Schlüssel`, z. B.
`RateLimiting__LoginPermitLimit=10` (Api) oder `Features__PinLogin=true` (Api, schaltet den vorbereiteten PIN-Login für Kinder frei).
Benutzer, Familieneinstellungen (Familienname, Zeitzone, Essenplan, Mahlzeiten, Aufgaben-Kategorien, Punktesystem, Gast-Rechte)
und das Protokoll administrativer Aktionen verwaltet der Administrator in der App unter **Verwaltung**.
### Update
```bash
cd deploy
git pull
docker compose up -d --build # Migrationen laufen automatisch über den migrations-Container
```
### Backup & Restore
```bash
cd deploy
./scripts/backup.sh # schreibt backups/familyplanner-<datum>.bak
./scripts/restore.sh backups/familyplanner-20261009-120000.bak
```
Backups liegen zusätzlich im Docker-Volume `sql-backup` (14 Tage). Für eine regelmäßige Sicherung z. B. per Cron:
`0 3 * * * cd /opt/familyplanner/deploy && ./scripts/backup.sh`.
## Kalender-Abos (iPhone/Outlook)
In der App unter **Kalender › Filter-Menü › Kalender abonnieren** einen Abo-Link erstellen: alle Termine, nur die eigenen
(Personen-Tag) oder ein einzelner Kalender, optional mit Aufgaben. Der Link wird nur einmal angezeigt (mit QR-Code) und
funktioniert wie ein Passwort; er lässt sich jederzeit neu erzeugen oder widerrufen. Administratoren sehen und widerrufen alle Abos
unter **Verwaltung › Kalender**.
* **iPhone/iPad:** „In Kalender-App öffnen“ antippen oder den QR-Code scannen. Alternativ *Einstellungen › Apps › Kalender ›
Kalender-Accounts › Account hinzufügen › Andere › Kalenderabo hinzufügen* und den https-Link einfügen.
* **Outlook (Web/neues Outlook):** *Kalender › Kalender hinzufügen › Aus dem Internet abonnieren* und den https-Link einfügen.
Outlook aktualisiert Abos nur alle paar Stunden.
* **Google Kalender:** *Weitere Kalender „+“ › Per URL*.
Voraussetzungen: Die App muss für die Geräte per **HTTPS** mit gültigem Zertifikat erreichbar sein (z. B. Caddy-Profil `proxy`).
Abos sind nur lesend; für Änderungen vom Handy aus gibt es die Zwei-Wege-Synchronisation (siehe nächster Abschnitt).
Der Feed-Endpunkt ist auf 60 Abrufe pro Minute und IP begrenzt (`RateLimiting__FeedPermitLimit`).
## Haus (Smart Home, Shelly)
Unter **Haus** bedient die Familie freigegebene Geräte (Licht, Steckdosen, Rollos; Sensoren zeigen Werte), nach Raum gruppiert oder auf einem
Grundriss mit Geräte-Symbolen. Administratoren legen unter **Hausverwaltung** Geräte (Shelly Gen1 und Gen2+/Plus/Pro/Gen3), Räume, Pläne und
Freigaben an (je Gerät für Rollen und/oder einzelne Personen: *nur ansehen* oder *schalten*) und sehen das Aktionsprotokoll.
* Der **Server** (Api-Container) spricht die Geräte direkt im Heimnetz an – er muss sie erreichen können. Eingetragen werden IP-Adressen oder
lokale Namen (`192.168.1.50`, `shelly-flur.local`); Adressen außerhalb des Heimnetzes sind aus Sicherheitsgründen gesperrt. Im Docker-Betrieb genügt
meist das Standard-Netzwerk; sonst Routing/Firewall des Hosts prüfen oder `network_mode: host` (siehe Kommentar in `deploy/docker-compose.yml`, [ADR-0023](docs/adr/0023-haus-smarthome.md)).
* Ist ein Gerät durch ein Passwort geschützt (bei Gen2+ Benutzer `admin`), wird es verschlüsselt gespeichert und nie wieder angezeigt.
* Ohne echtes Gerät lässt sich nichts schalten; Entwicklung und Tests benutzen einen Fake-Shelly-Server.
## Kalender mit dem Handy verbinden (CalDAV, Zwei-Wege)
Unter **Einstellungen › Kalender verbinden** (auch im Kalender-Menü: *Mit Handy verbinden*) erscheinen Server-Adresse
(`https://<Domain>/caldav/`) und Benutzername. Dort ein **App-Passwort** pro Gerät erstellen (wird nur einmal angezeigt, jederzeit
widerrufbar) und in der Kalender-App eintragen – **nie das normale Passwort**. Die Familienkalender erscheinen dann in
**iPhone/iPad/Mac** (*Account hinzufügen › Andere › CalDAV-Account*), **Thunderbird** (*Neuer Kalender › Im Netzwerk › CalDAV*) und
**Android** (App *DAVx5*); Termine, die dort angelegt oder geändert werden, landen im Familienplaner und umgekehrt. Es gelten dieselben
Rechte wie in der App (Kinder ändern nur eigene Termine, Gäste lesen nur).
* **HTTPS ist Pflicht** (`CALDAV_REQUIRE_HTTPS=true`, Standard): Kalender-Apps senden das App-Passwort bei jeder Abfrage per HTTP Basic.
Nur in einem reinen Heimnetz ohne Zertifikat kann es auf `false` gestellt werden (Klartext im LAN).
* Bei falschen Zugangsdaten sperrt der Server weitere Versuche kurz (429); iOS stellt beim ersten Abgleich viele Anfragen
(`RateLimiting__CalDavPermitLimit`, Standard 600 pro Minute und IP).
* **Outlook** kann kein CalDAV: dort bleibt nur das lesende ICS-Abo (Zwei-Wege-Abgleich mit Outlook wäre nur über Microsoft Graph möglich,
siehe Backlog). Nicht gespeichert werden Erinnerungen, Teilnehmer und Anhänge; Wiederholungen außerhalb der unterstützten Regeln
(z. B. stündlich) und Aufgaben werden vom Server abgelehnt. Details und Grenzen: [ADR-0017](docs/adr/0017-caldav-und-graph-spaeter.md).
**ICS-Import** (Schulferien, Müllabfuhr …): *Kalender › Filter-Menü › .ics importieren* bzw. *Verwaltung › Kalender*. Bereits importierte
Termine (gleiche UID) werden übersprungen; nicht unterstützte Wiederholungsregeln werden im Ergebnis genannt.
# Rbm.FamStack