5.3 KiB
Kalendartool
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) undUSER(genau 1 Kalender) – serverseitig erzwungen - Kalender: Titel, Beschreibung, Zeitzone, aktiv/inaktiv
- 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
- Sicherheit: zentrale Berechtigungsschicht (
lib/permissions), Zod-Validierung aller Eingaben, Middleware-Schutz, keine Account-Enumeration
Tech-Stack
Next.js 14 (App Router, TypeScript) · PostgreSQL · Prisma · Tailwind CSS · Docker · Vitest
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)
# 1. Session-Secret erzeugen und .env anlegen
cp .env.example .env
# 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 -f docker-compose.yml up --build
Die App läuft dann auf http://localhost:3000. Migrationen werden beim Containerstart automatisch angewendet (prisma migrate deploy).
Schnellstart ohne Docker
npm install
cp .env.example .env # Passwörter und SESSION_SECRET anpassen
npx prisma db push # Schema in die Datenbank schreiben
npm run dev
Voraussetzung: laufendes PostgreSQL (z. B. nur der db-Service aus docker-compose.yml: docker compose up -d db).
Erste Schritte
- Erste Registrierung unter
/register→ der erste Benutzer wird automatisch ADMIN - Im Dashboard einen Kalender anlegen
- 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 + Mitglieder
api/reservations/ Bearbeiten/Löschen (atomar)
dashboard/ User: 1 Kalender · Admin: alle Kalender
calendar/[id]/ Ansicht Tag/Woche/Monat
admin/ Kalenderverwaltung
components/ UI-, Kalender-, Reservierungs-, Admin-Komponenten
lib/
auth/ Session (JWT-Cookies), Passwort-Hashing
permissions/ zentrale Berechtigungsschicht
reservations/ Konfliktlogik + atomarer Service
api/ Response-Helfer, Kontext-Lader
validation.ts Zod-Schemas
prisma/schema.prisma Datenmodell
tests/ Unit-Tests (Kollisionen, Validierung, Rechte)
Tests
npm test
Getestet werden insbesondere die Kollisionslogik (Überlappungsvarianten aus plan.md Abschnitt 6), Eingabevalidierung und die komplette Berechtigungsmatrix.
Sicherheitskonzept (Kurzfassung)
| Thema | Umsetzung |
|---|---|
| Doppelbuchungen | SERIALIZABLE-Transaktion in lib/reservations/service.ts |
| Berechtigungen | zentrale Funktionen in lib/permissions/permissions.ts, geprüft in jeder API-Route |
| Passwörter | bcrypt (12 Runden), nie im Klartext |
| Sessions | HS256-signierte JWTs in HttpOnly/SameSite-Cookies |
| Login-Missbrauch | Rate-Limiting (5 Versuche / 15 min) |
| Account-Enumeration | generische Fehler, /forgot-password antwortet immer 200 |
| Eingaben | Zod-Schemas mit Längen-/Formatgrenzen |
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.