Aktueller Stand

This commit is contained in:
2026-01-15 23:18:42 +01:00
parent 46eae2a2a9
commit dcf45bac3d
32 changed files with 2625 additions and 395 deletions

View File

@@ -16,6 +16,7 @@ State-of-the-art Kalenderapp für Vereine mit Admin-Freigaben, persönlichen Kal
- Backend: Next.js Route Handlers, Prisma ORM, SQLite
- Auth: NextAuth (Credentials + Prisma Adapter)
- Export: iCal via `ical-generator`
- Import: iCal via `node-ical`
## Projektstruktur
- `app/` - Routen, Layouts und Seiten
@@ -52,6 +53,12 @@ SMTP_PASS="password"
SMTP_SECURE="false"
SMTP_FROM="Vereinskalender <noreply@example.com>"
NOMINATIM_USER_AGENT="vereinskalender/1.0 (mailto:admin@example.com)"
RATE_LIMIT_WINDOW_MINUTES="15"
RATE_LIMIT_LOGIN="10"
RATE_LIMIT_REGISTER="5"
RATE_LIMIT_PASSWORD_RESET="3"
RATE_LIMIT_VERIFY_EMAIL="3"
RATE_LIMIT_ICAL_IMPORT="5"
```
## Admin-Setup
@@ -84,6 +91,7 @@ Admin-Konten werden sofort freigeschaltet, normale Mitglieder bleiben auf `PENDI
- `DELETE /api/views/:id/items` - Termin entfernen
- `GET /api/views/default` - Standardansicht laden/erstellen
- `GET /api/ical/:token` - iCal Feed der Ansicht
- `POST /api/ical/import` - iCal-Datei importieren (Admin/Superadmin)
- `POST /api/views/default/rotate` - iCal-Link erneuern
- `POST /api/views/:id/categories` - Kategorie abonnieren
- `DELETE /api/views/:id/categories` - Kategorie-Abo entfernen
@@ -92,16 +100,22 @@ Admin-Konten werden sofort freigeschaltet, normale Mitglieder bleiben auf `PENDI
- `POST /api/password-reset/confirm` - Passwort setzen (mit Token)
- `POST /api/verify-email/request` - Verifizierungslink senden
- `POST /api/verify-email/confirm` - E-Mail verifizieren
- `GET /api/settings/google-places` - Ortsanbieter + API Key abrufen (Login)
- `POST /api/settings/google-places` - Ortsanbieter/Key speichern (Superadmin)
- `GET /api/settings/system` - Ortsanbieter + API Key abrufen (Login)
- `POST /api/settings/system` - Ortsanbieter/Key speichern (Superadmin)
- `GET /api/places/autocomplete` - Places Autocomplete (Login)
- `GET /api/places/details` - Places Details (Login)
- `GET /api/places/reverse` - Reverse-Geocoding (Login)
- `GET /api/settings/app-name` - App-Name abrufen
- `POST /api/settings/app-name` - App-Name setzen (Superadmin)
## iCal-Abonnement
Unter `/settings` wird die iCal-URL angezeigt. Diese kann in Kalender-Apps (iOS/Android) abonniert werden.
## iCal-Import
Admins und Superadmins können `.ics` Dateien im Adminbereich hochladen. Termine werden importiert und direkt freigegeben. `GEO:lat;lng` wird unterstützt, um Karten direkt anzuzeigen.
## Standardansicht
- Jeder Benutzer hat eine Standardansicht (`/api/views/default`).
@@ -116,6 +130,10 @@ Unter `/settings` können Nutzer ihre E-Mail oder ihr Passwort ändern und den i
Superadmins sehen unter `/admin` zusätzlich die System-Einstellungen und können den Ortsanbieter (Google oder OpenStreetMap/Nominatim) konfigurieren. Außerdem kann die öffentliche Registrierung deaktiviert werden.
Der App-Name kann ebenfalls dort gepflegt werden und wird in der Navigation sowie im iCal-Export verwendet.
Für iCal wird standardmäßig ein Rückblick von 14 Tagen angewendet (plus alle zukünftigen Termine). Jeder Benutzer kann den Rückblick in den Einstellungen anpassen; der Wert wird als URL-Parameter `pastDays` genutzt.
## Orte & Karten
- Der Ort wird per Google Places oder OpenStreetMap (Nominatim) vorgeschlagen und mit `placeId` sowie Koordinaten gespeichert.
@@ -154,6 +172,20 @@ Wichtig für persistente Logins und Daten:
- Die SQLite-DB liegt im Host-Verzeichnis `/opt/docker/vereinskalender/app-data` und wird nach `/app/prisma/data` gemountet. Sie bleibt über Rebuilds erhalten.
- `docker compose down -v` löscht keine Bind-Mount-Daten, aber ein Entfernen von `/opt/docker/vereinskalender/app-data` löscht alles.
## Rate Limiting
Passwort-Reset, E-Mail-Verifizierung, Registrierung, Login und iCal-Import sind DB-basiert rate-limited. Nach dem Hinzufügen neuer Limits Prisma-Migration ausführen (`npm run prisma:migrate` bzw. `npm run prisma:deploy` im Container).
Optional zusätzlich per Nginx:
```nginx
limit_req_zone $binary_remote_addr zone=authlimit:10m rate=5r/m;
location = /api/password-reset/request { limit_req zone=authlimit burst=5 nodelay; proxy_pass http://app:3000; }
location = /api/verify-email/request { limit_req zone=authlimit burst=5 nodelay; proxy_pass http://app:3000; }
location = /api/register { limit_req zone=authlimit burst=5 nodelay; proxy_pass http://app:3000; }
```
## Schnellere Builds (Best Practices)
- `package-lock.json` committen und im Dockerfile `npm ci` nutzen (bereits vorbereitet).
- BuildKit-Cache nutzen (im Dockerfile aktiv, benötigt Docker BuildKit).