94 lines
2.7 KiB
Markdown
94 lines
2.7 KiB
Markdown
|
|
# 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`
|
||
|
|
- Gotenberg v8 (oder Carbone, via `RENDERER=carbone`)
|
||
|
|
- PostgreSQL-Instanz für Audit-Log
|
||
|
|
|
||
|
|
## Schnellstart (Entwicklung)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
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
|
||
|
|
|
||
|
|
```json
|
||
|
|
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/me` validiert
|
||
|
|
- 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 |
|