initial commit
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# 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 |
|
||||
Reference in New Issue
Block a user