Aktueller Stand
This commit is contained in:
108
README.md
108
README.md
@@ -1,15 +1,18 @@
|
||||
# Vereinskalender
|
||||
|
||||
State-of-the-art Kalenderapp fuer Vereine mit Admin-Freigaben, persoenlichen Kalenderansichten und iCal-Export. Die App basiert auf Next.js (App Router), Prisma und NextAuth (Credentials).
|
||||
State-of-the-art Kalenderapp für Vereine mit Admin-Freigaben, persönlichen Kalenderansichten und iCal-Export. Die App basiert auf Next.js (App Router), Prisma und NextAuth (Credentials).
|
||||
|
||||
## Features
|
||||
- Admins koennen Termine sofort freigeben oder Vorschlaege bestaetigen/ablehnen.
|
||||
- Mitglieder schlagen Termine vor; Freigaben laufen ueber das Admin-Panel.
|
||||
- Admins können Termine sofort freigeben oder Vorschläge bestätigen/ablehnen.
|
||||
- Mitglieder schlagen Termine vor; Freigaben laufen über das Admin-Panel.
|
||||
- Neue Registrierungen müssen durch Admins freigeschaltet werden.
|
||||
- Mehrere Kalenderansichten (Monat, Woche, Liste) mit FullCalendar.
|
||||
- Eigene Ansichten mit iCal-Abonnement fuer externe Apps (iOS/Android).
|
||||
- Eine Standardansicht pro Benutzer mit iCal-Abonnement für externe Apps (iOS/Android).
|
||||
- Kategorien zur Strukturierung (nur Admins dürfen Kategorien anlegen).
|
||||
- Kategorien können abonniert werden, damit neue und bestehende Termine automatisch in die Ansicht fallen.
|
||||
|
||||
## Tech-Stack
|
||||
- Frontend: Next.js 14 (App Router), React 18, Tailwind CSS, FullCalendar
|
||||
- Frontend: Next.js 14 (App Router), React 18, Tailwind CSS, FullCalendar (v6.1.20 CSS lokal)
|
||||
- Backend: Next.js Route Handlers, Prisma ORM, SQLite
|
||||
- Auth: NextAuth (Credentials + Prisma Adapter)
|
||||
- Export: iCal via `ical-generator`
|
||||
@@ -30,47 +33,114 @@ npm run prisma:migrate
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Open `http://localhost:3000`.
|
||||
Öffne `http://localhost:3000`.
|
||||
|
||||
## Konfiguration
|
||||
|
||||
In `.env` (lokal) bzw. per Umgebungsvariablen (Docker/Prod):
|
||||
|
||||
```
|
||||
DATABASE_URL="file:./dev.db"
|
||||
DATABASE_URL="file:./data/dev.db"
|
||||
NEXTAUTH_SECRET="replace-with-strong-secret"
|
||||
NEXTAUTH_URL="http://localhost:3000"
|
||||
NEXTAUTH_URL="http://localhost:3101"
|
||||
ADMIN_EMAILS="admin@example.com"
|
||||
SUPERADMIN_EMAILS="superadmin@example.com"
|
||||
SMTP_HOST="smtp.example.com"
|
||||
SMTP_PORT="587"
|
||||
SMTP_USER="user@example.com"
|
||||
SMTP_PASS="password"
|
||||
SMTP_SECURE="false"
|
||||
SMTP_FROM="Vereinskalender <noreply@example.com>"
|
||||
NOMINATIM_USER_AGENT="vereinskalender/1.0 (mailto:admin@example.com)"
|
||||
```
|
||||
|
||||
## Admin-Setup
|
||||
|
||||
`ADMIN_EMAILS` (kommagetrennt) steuert, welche Accounts beim Signup als Admin markiert werden.
|
||||
Admin-Konten werden sofort freigeschaltet, normale Mitglieder bleiben auf `PENDING`.
|
||||
`SUPERADMIN_EMAILS` (kommagetrennt) steuert Superadmins, die System-Einstellungen verwalten dürfen.
|
||||
|
||||
## Wichtige Befehle
|
||||
|
||||
- `npm run dev` - lokale Entwicklung
|
||||
- `npm run build` - Production Build
|
||||
- `npm run start` - Server starten (Production)
|
||||
- `npm run prisma:migrate` - DB Migrationen fuer SQLite (Dev)
|
||||
- `npm run prisma:migrate` - DB Migrationen für SQLite (Dev)
|
||||
- `npm run prisma:deploy` - Schema push (Container-Start)
|
||||
- `npm run prisma:studio` - Prisma Studio
|
||||
- `npm run copy:fullcalendar-css` - FullCalendar CSS nach `public/vendor/fullcalendar/` kopieren
|
||||
|
||||
## APIs (kurz)
|
||||
- `POST /api/register` - Registrierung
|
||||
- `GET /api/events` - Events (Admins sehen alles, User nur eigene + freigegebene)
|
||||
- `POST /api/events` - Termin vorschlagen/anlegen
|
||||
- `PATCH /api/events/:id` - Freigeben/Ablehnen (Admin)
|
||||
- `GET /api/categories` - Kategorien anzeigen
|
||||
- `POST /api/categories` - Kategorie anlegen (Admin)
|
||||
- `GET /api/users?status=PENDING` - Offene Registrierungen (Admin)
|
||||
- `PATCH /api/users` - Benutzer freischalten/ändern (Admin)
|
||||
- `GET /api/views` - Eigene Ansichten
|
||||
- `POST /api/views` - Ansicht erstellen
|
||||
- `POST /api/views/:id/items` - Termin zur Ansicht
|
||||
- `DELETE /api/views/:id/items` - Termin entfernen
|
||||
- `GET /api/views/default` - Standardansicht laden/erstellen
|
||||
- `GET /api/ical/:token` - iCal Feed der Ansicht
|
||||
- `POST /api/views/default/rotate` - iCal-Link erneuern
|
||||
- `POST /api/views/:id/categories` - Kategorie abonnieren
|
||||
- `DELETE /api/views/:id/categories` - Kategorie-Abo entfernen
|
||||
- `PATCH /api/profile` - E-Mail/Passwort aktualisieren
|
||||
- `POST /api/password-reset/request` - Passwort-Reset Link anfordern
|
||||
- `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/places/autocomplete` - Places Autocomplete (Login)
|
||||
- `GET /api/places/details` - Places Details (Login)
|
||||
- `GET /api/places/reverse` - Reverse-Geocoding (Login)
|
||||
|
||||
## iCal-Abonnement
|
||||
|
||||
Unter "Meine Ansichten" wird fuer jede Ansicht eine iCal-URL erzeugt. Diese kann in Kalender-Apps (iOS/Android) abonniert werden.
|
||||
Unter `/settings` wird die iCal-URL angezeigt. Diese kann in Kalender-Apps (iOS/Android) abonniert werden.
|
||||
|
||||
## Standardansicht
|
||||
|
||||
- Jeder Benutzer hat eine Standardansicht (`/api/views/default`).
|
||||
- Termine können direkt im Kalender oder in der Listenansicht ein- oder ausgeblendet werden.
|
||||
- Kategorien lassen sich abonnieren, um künftige Termine automatisch einzublenden.
|
||||
|
||||
## Einstellungen
|
||||
|
||||
Unter `/settings` können Nutzer ihre E-Mail oder ihr Passwort ändern und den iCal-Link erneuern.
|
||||
|
||||
## Superadmin
|
||||
|
||||
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.
|
||||
|
||||
## Orte & Karten
|
||||
|
||||
- Der Ort wird per Google Places oder OpenStreetMap (Nominatim) vorgeschlagen und mit `placeId` sowie Koordinaten gespeichert.
|
||||
- Der Ort kann zusätzlich direkt auf der Karte ausgewählt werden (Reverse-Geocoding füllt den Namen).
|
||||
- In den Termin-Details wird abhängig vom Anbieter eine Karte (Google Maps Embed oder OpenStreetMap) angezeigt.
|
||||
|
||||
## Passwort-Reset
|
||||
|
||||
Unter `/reset` kann ein Passwort-Reset angefordert werden. Der Link ist 60 Minuten gültig.
|
||||
Wenn keine SMTP-Umgebung gesetzt ist, wird der Link im Server-Log ausgegeben.
|
||||
|
||||
## E-Mail-Verifizierung
|
||||
|
||||
- Nach der Registrierung wird eine Verifizierungs-Mail gesendet (Token ist 24h gültig).
|
||||
- Verifizierungslink erneut senden unter `/verify`.
|
||||
|
||||
## Termin-Logik
|
||||
|
||||
- Startdatum und Startzeit sind Pflichtfelder.
|
||||
- Endzeit ist optional; falls nicht gesetzt, wird für Kalenderausgaben automatisch +3 Stunden angenommen.
|
||||
|
||||
## Registrierungen
|
||||
|
||||
- Neue Mitglieder sind standardmäßig `PENDING`.
|
||||
- Admins schalten unter `/admin/users` frei.
|
||||
|
||||
## Docker
|
||||
|
||||
@@ -79,15 +149,21 @@ cp .env.example .env
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
Wichtig fuer persistente Logins:
|
||||
Wichtig für persistente Logins und Daten:
|
||||
- `NEXTAUTH_SECRET` in `.env` fix setzen (nicht bei jedem Build wechseln).
|
||||
- Die SQLite-DB liegt im `data/`-Volume des Containers und bleibt erhalten.
|
||||
- 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.
|
||||
|
||||
## Schnellere Builds (Best Practices)
|
||||
- `package-lock.json` committen und im Dockerfile `npm ci` nutzen (bereits vorbereitet).
|
||||
- BuildKit-Cache nutzen (im Dockerfile aktiv, benoetigt Docker BuildKit).
|
||||
- Fuer schnelle lokale Iteration: `docker compose -f docker-compose.dev.yml up --build`.
|
||||
- BuildKit-Cache nutzen (im Dockerfile aktiv, benötigt Docker BuildKit).
|
||||
- Für schnelle lokale Iteration: `docker compose -f docker-compose.dev.yml up --build`.
|
||||
|
||||
## FullCalendar CSS
|
||||
|
||||
FullCalendar v6 liefert keine fertigen CSS-Dateien auf npm aus. Daher liegt eine gebündelte CSS-Datei in `public/vendor/fullcalendar/fullcalendar.css`, erzeugt aus den offiziellen Stylesheets des FullCalendar-Repos (Version v6.1.20). Bei einem Upgrade die CSS-Datei via `scripts/build-fullcalendar-css.sh` neu generieren.
|
||||
|
||||
## Sicherheitshinweise
|
||||
- Keine Secrets committen; `.env` ist in `.dockerignore`.
|
||||
- Fuer Prod echte Secrets und eine externe DB nutzen.
|
||||
- Für Prod echte Secrets und eine externe DB nutzen.
|
||||
- Login-Versuche sind gedrosselt (IP + E-Mail), nach mehreren Fehlversuchen erfolgt eine temporäre Sperre.
|
||||
|
||||
Reference in New Issue
Block a user