Prepare Kalendartool for MPM and disable invites
This commit is contained in:
50
README.md
50
README.md
@@ -1,13 +1,13 @@
|
||||
# Kalendartool
|
||||
|
||||
Einfaches Kalender- und Reservierungstool nach `plan.md`: Ein Admin legt Kalender an und lädt Benutzer per Invite-Link ein. Jeder User sieht **ausschließlich seinen einen Kalender** und kann dort Reservierungen erstellen.
|
||||
Einfaches Kalender- und Reservierungstool: Ein Admin legt Kalender an und ordnet vorhandene Benutzer direkt zu. Jeder User sieht **ausschließlich seinen einen Kalender** und kann dort Reservierungen erstellen.
|
||||
|
||||
## Kernfunktionen (MVP)
|
||||
|
||||
- **Auth**: Registrierung, Login, Logout, Passwort vergessen – bcrypt-Hashing, signierte HttpOnly-Session-Cookies, Rate-Limiting beim Login
|
||||
- **Rollen**: `ADMIN` (0..n Kalender) und `USER` (genau 1 Kalender) – serverseitig erzwungen
|
||||
- **Kalender**: Titel, Beschreibung, Zeitzone, aktiv/inaktiv
|
||||
- **Invite-System**: nicht erratbare Tokens (32 Bytes), nur SHA-256-Hash in der DB, Ablaufdatum, Übersicht Aktiv/Abgelaufen/Verwendet
|
||||
- **Mitglieder**: Administratoren ordnen vorhandene Benutzer direkt einem Kalender zu
|
||||
- **Reservierungen**: Startzeit + Dauer (15-Minuten-Schritte), Titel, Notiz
|
||||
- **Doppelbuchungsschutz**: atomare Prüfung in serialisierbarer Transaktion (HTTP 409 bei Kollision)
|
||||
- **Ansichten**: Tag / Woche / Monat
|
||||
@@ -17,16 +17,40 @@ Einfaches Kalender- und Reservierungstool nach `plan.md`: Ein Admin legt Kalende
|
||||
|
||||
Next.js 14 (App Router, TypeScript) · PostgreSQL · Prisma · Tailwind CSS · Docker · Vitest
|
||||
|
||||
## Schnellstart mit Docker (empfohlen)
|
||||
## MPM Marketplace
|
||||
|
||||
Das Repository ist als MPM-Modul vorbereitet. `module.json` beschreibt das
|
||||
Modul und seine Konfigurationsfelder; `compose.yml` enthält App, PostgreSQL
|
||||
und tägliche Backups. Die Modul-App veröffentlicht keinen Host-Port. MPM
|
||||
erreicht sie intern über Port `41030` und die Health-Route `/health`.
|
||||
|
||||
Die Anmeldung und Rollen kommen im MPM-Betrieb signiert vom MPM-Gateway.
|
||||
Die lokale Cookie-Anmeldung bleibt für den eigenständigen Betrieb erhalten.
|
||||
Kalender und Reservierungen liegen in PostgreSQL. Die benannten Volumes
|
||||
`pgdata` und `pgbackups` bleiben beim Entfernen des Moduls erhalten.
|
||||
|
||||
Bei der ersten MPM-Konfiguration werden zwei getrennte, zufällige Passwörter
|
||||
für PostgreSQL-Administration und App-Zugriff benötigt. Die Anmeldung läuft
|
||||
über MPM; lokale Konten und Einladungslinks sind im MPM-Betrieb deaktiviert.
|
||||
|
||||
Benutzer und Modulzugriff werden in MPM verwaltet. Öffne das Modul zunächst
|
||||
einmal mit dem neuen Benutzer, damit sein lokales Profil angelegt wird; ein
|
||||
Kalenderadministrator kann ihn danach direkt einem Kalender zuordnen. Die
|
||||
Datenbank-Initialisierung wird nur bei einem leeren Volume ausgeführt. Ein
|
||||
späteres Ändern der Datenbankpasswörter im MPM-Konfigurationsdialog ändert die
|
||||
Zugangsdaten eines bestehenden PostgreSQL-Volumes nicht automatisch.
|
||||
|
||||
## Schnellstart mit Docker (eigenständiger Betrieb)
|
||||
|
||||
```bash
|
||||
# 1. Session-Secret erzeugen und .env anlegen
|
||||
cp .env.example .env
|
||||
# SESSION_SECRET in .env setzen (mindestens 32 Zeichen):
|
||||
# CALENDAR_ADMIN_PASSWORD, CALENDAR_DB_PASSWORD und SESSION_SECRET in .env
|
||||
# durch zufällige Werte ersetzen. SESSION_SECRET braucht mindestens 32 Zeichen:
|
||||
node -e "console.log('SESSION_SECRET=' + require('crypto').randomBytes(48).toString('base64url'))"
|
||||
|
||||
# 2. Stack starten (PostgreSQL + App)
|
||||
docker compose up --build
|
||||
docker compose -f docker-compose.yml up --build
|
||||
```
|
||||
|
||||
Die App läuft dann auf http://localhost:3000. Migrationen werden beim Containerstart automatisch angewendet (`prisma migrate deploy`).
|
||||
@@ -35,7 +59,7 @@ Die App läuft dann auf http://localhost:3000. Migrationen werden beim Container
|
||||
|
||||
```bash
|
||||
npm install
|
||||
cp .env.example .env # DATABASE_URL und SESSION_SECRET anpassen
|
||||
cp .env.example .env # Passwörter und SESSION_SECRET anpassen
|
||||
npx prisma db push # Schema in die Datenbank schreiben
|
||||
npm run dev
|
||||
```
|
||||
@@ -46,30 +70,27 @@ Voraussetzung: laufendes PostgreSQL (z. B. nur der `db`-Service aus `docker-comp
|
||||
|
||||
1. Erste Registrierung unter `/register` → der **erste Benutzer wird automatisch ADMIN**
|
||||
2. Im Dashboard einen Kalender anlegen
|
||||
3. Unter „Benutzer einladen" einen Invite-Link erstellen und verschicken
|
||||
4. Eingeladene Personen registrieren sich über den Link und sehen sofort nur diesen einen Kalender
|
||||
3. Im Kalender unter „Mitglieder" vorhandene Benutzer zuordnen
|
||||
|
||||
## Projektstruktur
|
||||
|
||||
```
|
||||
app/ Next.js App Router (Seiten + API-Routen)
|
||||
api/auth/ register, login, logout, forgot-password
|
||||
api/calendars/ CRUD + Reservierungen + Invites
|
||||
api/calendars/ CRUD + Reservierungen + Mitglieder
|
||||
api/reservations/ Bearbeiten/Löschen (atomar)
|
||||
dashboard/ User: 1 Kalender · Admin: alle Kalender
|
||||
calendar/[id]/ Ansicht Tag/Woche/Monat
|
||||
invite/[token]/ Invite-Annahme
|
||||
admin/ Kalenderverwaltung
|
||||
components/ UI-, Kalender-, Reservierungs-, Admin-Komponenten
|
||||
lib/
|
||||
auth/ Session (JWT-Cookies), Passwort-Hashing
|
||||
permissions/ zentrale Berechtigungsschicht
|
||||
reservations/ Konfliktlogik + atomarer Service
|
||||
invites/ Token-Erzeugung/Hashing
|
||||
api/ Response-Helfer, Kontext-Lader
|
||||
validation.ts Zod-Schemas
|
||||
prisma/schema.prisma Datenmodell
|
||||
tests/ Unit-Tests (Kollisionen, Invites, Rechte)
|
||||
tests/ Unit-Tests (Kollisionen, Validierung, Rechte)
|
||||
```
|
||||
|
||||
## Tests
|
||||
@@ -78,7 +99,7 @@ tests/ Unit-Tests (Kollisionen, Invites, Rechte)
|
||||
npm test
|
||||
```
|
||||
|
||||
Getestet werden insbesondere die **Kollisionslogik** (Überlappungsvarianten aus plan.md Abschnitt 6), Invite-Token-Hashing/-Ablauf, Eingabevalidierung und die komplette Berechtigungsmatrix.
|
||||
Getestet werden insbesondere die **Kollisionslogik** (Überlappungsvarianten aus plan.md Abschnitt 6), Eingabevalidierung und die komplette Berechtigungsmatrix.
|
||||
|
||||
## Sicherheitskonzept (Kurzfassung)
|
||||
|
||||
@@ -86,7 +107,6 @@ Getestet werden insbesondere die **Kollisionslogik** (Überlappungsvarianten aus
|
||||
| --- | --- |
|
||||
| Doppelbuchungen | `SERIALIZABLE`-Transaktion in `lib/reservations/service.ts` |
|
||||
| Berechtigungen | zentrale Funktionen in `lib/permissions/permissions.ts`, geprüft in **jeder** API-Route |
|
||||
| Invite-Tokens | 32 Byte Zufall, nur SHA-256-Hash in der DB |
|
||||
| Passwörter | bcrypt (12 Runden), nie im Klartext |
|
||||
| Sessions | HS256-signierte JWTs in HttpOnly/SameSite-Cookies |
|
||||
| Login-Missbrauch | Rate-Limiting (5 Versuche / 15 min) |
|
||||
@@ -95,4 +115,4 @@ Getestet werden insbesondere die **Kollisionslogik** (Überlappungsvarianten aus
|
||||
|
||||
## Bewusste MVP-Grenzen (plan.md Abschnitt 18)
|
||||
|
||||
Buchungszeitfenster-Regeln, E-Mail-Versand, ICS-Export, wiederkehrende Reservierungen und Statistiken sind bewusst **nicht** Teil von Version 1 – die Struktur (Service-Schicht, Regeln in `lib/`) ist darauf vorbereitet.
|
||||
Buchungszeitfenster-Regeln, E-Mail-Versand, ICS-Export, wiederkehrende Reservierungen und Statistiken sind bewusst **nicht** Teil von Version 1 – die Struktur (Service-Schicht, Regeln in `lib/`) ist darauf vorbereitet.
|
||||
|
||||
Reference in New Issue
Block a user