Next.js 15 App Router mit öffentlicher Übersicht und geschütztem Admin-Bereich zur Pflege von Datenschutzerklärungen nach Art. 12ff. DSGVO. - Oberfläche auf Basis von shadcn/ui, Inter lokal eingebunden - Prisma/SQLite, Auth.js mit Credentials-Provider und Rollen - Massenimport der Merkblätter des Amtes Leezen aus PDF - Docker-Image (standalone) und Gitea-Workflow zur Veröffentlichung Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3.9 KiB
Syncova Policies
Verwaltung und Veröffentlichung von Datenschutzerklärungen nach DSGVO (Art. 12ff.). Öffentliche Übersicht für Betroffene, geschützter Admin-Bereich zur Pflege.
Next.js 15 (App Router) · React 19 · Tailwind CSS 4 · shadcn/ui · Prisma + SQLite · Auth.js
Schnellstart (lokal)
npm install
cp .env.example .env # NEXTAUTH_SECRET eintragen (siehe unten)
npx prisma migrate deploy
npm run seed-admin # legt den ersten Admin an und zeigt das Passwort einmalig
npm run dev
Die Anwendung läuft anschließend auf http://localhost:3000, der Admin-Bereich
unter /admin.
Umgebungsvariablen
| Variable | Pflicht | Bedeutung |
|---|---|---|
NEXTAUTH_SECRET |
ja | Signiert die Session-Token. Erzeugen mit node -e "console.log(require('crypto').randomBytes(32).toString('base64'))" |
NEXTAUTH_URL |
ja | Öffentliche URL der Anwendung, z. B. https://datenschutz.example.de |
DATABASE_URL |
ja | SQLite-Pfad. Lokal file:./dev.db, im Container file:/app/data/syncova.db |
ADMIN_EMAIL |
nein | Vorgabe für seed-admin / reset-admin |
ADMIN_NAME |
nein | Anzeigename des Admin-Kontos |
ADMIN_PASSWORD |
nein | Leer lassen für ein generiertes Zufallspasswort |
.envist absichtlich nicht versioniert – sie enthält das Session-Secret. Ebenso wenig die SQLite-Datei, die Benutzerkonten und Passwort-Hashes enthält.
Betrieb per Docker
docker run -d --name syncova-policies \
-p 3000:3000 \
-e NEXTAUTH_SECRET="$(node -e "console.log(require('crypto').randomBytes(32).toString('base64'))")" \
-e NEXTAUTH_URL="https://datenschutz.example.de" \
-v syncova-data:/app/data \
git.jfritzsche.de/jf/syncova-policies:latest
Oder mit Compose:
export NEXTAUTH_SECRET="…"
export NEXTAUTH_URL="https://datenschutz.example.de"
docker compose up -d
Beim Start wendet der Container ausstehende Migrationen selbst an
(prisma migrate deploy). Die Datenbank liegt im Volume unter /app/data –
ohne dieses Volume gehen alle Daten beim Neustart verloren.
Ersten Admin-Zugang anlegen:
docker exec -it syncova-policies node scripts/seed-admin.js
Passwort zurücksetzen:
docker exec -it syncova-policies node scripts/reset-admin.js --email admin@example.de
Datenpflege
Datenschutzerklärungen werden normalerweise im Admin-Bereich gepflegt. Für Massenimporte gibt es zwei Wege:
| Befehl | Zweck |
|---|---|
npm run import-policy -- data/policies/<datei>.json |
Einzelne Erklärung aus JSON importieren (--update überschreibt) |
npm run analyze-pdfs |
PDFs in data/import/ analysieren, ohne zu schreiben |
npm run import-pdfs |
Alle PDFs aus data/import/ importieren (--dry-run, --public) |
Der PDF-Import ist auf die Merkblatt-Vorlage des Amtes Leezen zugeschnitten
(scripts/lib/pdf-policy.js). Er vergleicht den Textbaustein-Teil jedes
Dokuments gegen ein Referenzdokument und meldet jede Abweichung, statt sie
stillschweigend zu übernehmen. Importierte Datensätze werden am Titel erkannt
und aktualisiert, nicht dupliziert.
Veröffentlichung des Images
.gitea/workflows/publish-image.yml baut bei jedem Push auf main sowie bei
v*-Tags ein Image und lädt es in die Gitea-Registry.
Voraussetzung: im Repository unter Settings → Actions → Secrets ein Secret
REGISTRY_TOKEN mit einem Token hinterlegen, das write:package darf.
Projektstruktur
app/ Routen (öffentlich, /admin, /auth, /api)
components/ UI-Komponenten; components/ui = shadcn/ui
hooks/ SWR-Datenzugriff, Theme
lib/ Prisma/Auth-Helfer, Markdown, Formatierung
prisma/ Schema und Migrationen
scripts/ Admin- und Importskripte
data/import/ Quell-PDFs für den Massenimport
data/policies/ Aufbereitete Datensätze als JSON