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>
117 lines
3.9 KiB
Markdown
117 lines
3.9 KiB
Markdown
# 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)
|
||
|
||
```bash
|
||
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 |
|
||
|
||
> `.env` ist absichtlich nicht versioniert – sie enthält das Session-Secret.
|
||
> Ebenso wenig die SQLite-Datei, die Benutzerkonten und Passwort-Hashes enthält.
|
||
|
||
---
|
||
|
||
## Betrieb per Docker
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
docker exec -it syncova-policies node scripts/seed-admin.js
|
||
```
|
||
|
||
Passwort zurücksetzen:
|
||
|
||
```bash
|
||
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
|
||
```
|