Serienbrief-Backend
Node.js/Express-Backend für das Serienbrief-System auf Basis von Directus (Adressdatenbank) und Gotenberg/Carbone (PDF-Rendering).
Voraussetzungen
- Docker Engine 27.x, Docker Compose V2
- Laufende Directus-Instanz mit:
- Collection
sb_templates(siehe Konzept-Dokument) - Service-Account-Token mit Lesezugriff auf Kontakt-Collections und
sb_templates
- Collection
- Gotenberg v8 (oder Carbone, via
RENDERER=carbone) - PostgreSQL-Instanz für Audit-Log
Schnellstart (Entwicklung)
cp .env.example .env
# .env anpassen (DIRECTUS_TOKEN, AUDIT_DB_* etc.)
npm install
npm run dev
Umgebungsvariablen
Alle Optionen: siehe .env.example
API-Endpunkte
| Methode | Pfad | Auth | Beschreibung |
|---|---|---|---|
GET |
/health |
nein | Healthcheck |
GET |
/api/sb/templates |
Bearer | Aktive Templates |
GET |
/api/sb/recipients |
Bearer | Empfängerliste |
POST |
/api/sb/render |
Bearer | PDF generieren |
GET |
/api/sb/audit |
Bearer (Admin) | Audit-Log |
POST |
/admin/reload-templates |
intern | Template-Cache leeren |
Render-Request
POST /api/sb/render
Authorization: Bearer <directus-user-token>
{
"templateId": "uuid-aus-sb_templates",
"collection": "kontakte",
"recipientIds": [42, 87, 133],
"extraFields": { "betreff": "Wichtige Information" }
}
Response: application/pdf (Datei-Download)
Template-Syntax (Carbone)
Templates sind ODT- oder DOCX-Dateien mit Carbone-Platzhaltern:
{d.empfaenger[i].vorname} {d.empfaenger[i].nachname}
{d.empfaenger[i].adresse}
{d.empfaenger[i].plz} {d.empfaenger[i].ort}
Datum: {d.meta.datum}
Betreff: {d.meta.betreff}
Sicherheit
- Service-Account-Token wird als Docker Secret geliefert (
/run/secrets/directus_token) - User-Bearer-Token wird gegen Directus
/users/mevalidiert - Generierte PDFs werden nur im RAM gehalten und direkt gestreamt (keine Persistenz)
- Audit-Log: INSERT-only (DB-User hat kein UPDATE/DELETE)
- Container läuft als non-root (UID 1001),
read_only: true,cap_drop: ALL
Renderer-Auswahl
| Variable | Wert | Beschreibung |
|---|---|---|
RENDERER |
gotenberg (default) |
Carbone merged Template + Daten → Gotenberg konvertiert nach PDF |
RENDERER |
carbone |
Carbone merged + konvertiert direkt (LibreOffice im Container nötig) |
Direktus-Collection sb_templates
| Feld | Typ | Beschreibung |
|---|---|---|
id |
UUID | Primärschlüssel |
name |
String | Anzeigename |
description |
String | Beschreibung |
version |
String | z.B. 2.1 |
file_id |
FK → directus_files | Template-Datei |
active |
Boolean | Nur aktive werden angezeigt |
allowed_fields |
String | Kommagetrennte Felder-Allowlist |