Files
2026-09-16 06:32:26 +02:00

127 lines
8.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Notify Gateway
Go-Gateway mit ntfy-, Gotify-, Webhook-, IMAP- und Discord-Eingängen. Regeln verteilen Nachrichten über eine persistente Outbox an Divera247, Discord, HTTP-Webhooks, SMTP, ntfy und Gotify.
**Stand:** `0.1.0-alpha.5` – mit SQLite-Outbox, Wiederholungen, Deduplizierung und Zustellhistorie. Standardmäßig ist `divera.dry_run=true`; zusätzliche Ausgänge starten mit `live=false`.
## Ausgänge einrichten
1. Unter **Ausgänge** einen Ausgang anlegen: Name, eindeutige ID, Provider und dessen Verbindungsdaten.
2. Unter **Zuordnungen** als Ziel **Discord**, **HTTP-Webhook**, **SMTP**, **ntfy** oder **Gotify** und den Ausgang wählen. Quelle, Filter und Titel-/Text-Templates konfigurieren.
3. Mit **Regel prüfen** das Payload ansehen, anschließend speichern. Eingehende Testmeldungen erzeugen im Dry-Run ein Ergebnis ohne Netzwerkversand.
4. Für echten Versand **Live-Versand aktivieren** am jeweiligen Ausgang einschalten und speichern. Dieser Schalter ist unabhängig von `divera.dry_run`.
Mehrere passende Regeln erzeugen unabhängige Zustellaufträge. HTTP-Eingänge antworten nach Speicherung mit **202 Accepted** und einer Referenz. Mit `Idempotency-Key` lassen sich Wiederholungen derselben Nachricht deduplizieren. Temporäre Versandfehler werden bis zu achtmal versucht; erfolgreiche Ziele werden dabei nicht erneut versendet. Status und manuelle Wiederholung stehen unter **Zustellhistorie** bereit.
Discord sendet Titel und Meldung, getrennt durch einen Zeilenumbruch, als Text. Leere Texte und Inhalte über 2000 UTF-16-Codeeinheiten werden abgelehnt, Mentions sind deaktiviert. Der Adapter verwendet `wait=true` für eine bestätigte API-Antwort. Siehe [Discord-Webhooks](https://docs.discord.com/developers/resources/webhook#execute-webhook).
HTTP-Webhooks erhalten per POST JSON mit `source`, `channel`, `title`, `message`, `address`, `priority`, `tags` und `received_at`. Raw-Eingangsdaten und Divera247-Extras werden nicht automatisch weitergegeben. Weiterleitungen werden blockiert. Die neuen Ausgänge liefern keine Remote-Antworttexte oder Ziel-URLs an den Eingang zurück.
Beispiele stehen in `config.example.json`. Bestehende Konfigurationen bleiben verwendbar; beim Start entsteht zusätzlich `outbox.db` daneben. Einrichtung von SMTP/IMAP und Discord, Zustellgarantien, Metriken und Backups: [OPERATIONS.md](OPERATIONS.md). Ausbauplan: [PROVIDER_PLAN.md](PROVIDER_PLAN.md).
## Bereits enthalten
- Go 1.23+, SQLite ohne CGO, IMAP/MIME und bcrypt als versionierte Go-Abhängigkeiten.
- Persistente, atomar geschriebene JSON-Konfiguration (`0600`).
- Admin-WebUI mit Session-Login, formularbasierter Konfiguration, Passwortwechsel, Divera247-Verbindungstest und Stammdaten-Auswahl.
- Eingangs-Authentifizierung per Bearer-Token, ntfy-kompatiblem Basic-Auth-Passwort bzw. Gotify-`token`/`X-Gotify-Key`.
- ntfy-Publish als Text, JSON und GET-Trigger (`trigger`, `send`, `publish`).
- Gotify-kompatibler `POST /message?token=...` sowie `/in/gotify/message`.
- Generischer `POST/PUT /in/webhook/{channel}` für JSON, Formular- oder Text-Payloads.
- Regel-Engine mit Quelle, Kanal-, Titel- und Meldungs-Regex sowie Mindestpriorität; Regeln werden in der WebUI grafisch bearbeitet und können per Payload-Vorschau getestet werden.
- Mapping auf Divera247 Alarm, Mitteilung (News) oder Termin (Event), inkl. Stichwort, Meldung, Ort, Empfänger-Typ, Einheit(en), Gruppen, Personen, Fahrzeuge und Versandwege. Einheitsübergreifende Zuordnungen können pro Einheit die Empfängerart Alle/Gruppen/Personen setzen.
- Freies `extra`-Objekt je Mapping, um zusätzliche Divera247-Felder ohne Codeänderung zu übergeben.
- Divera247-v2-Client für CRUD, Archivieren, Lesen, Rückmeldungen, Reichweite, Downloads, Anhänge, Alarm schließen, Event-ICS und Pull-Daten. Zusätzlich steht ein generischer Request-Pfad für noch nicht typisierte API-Funktionen bereit.
- Dockerfile, Compose-Beispiel und Unit-Tests.
## Start
```bash
export GATEWAY_ADMIN_PASSWORD='ein-langes-einmaliges-passwort'
go run ./cmd/gateway -config ./data/config.json
```
Danach: `http://localhost:8080/ui/`. Wenn beim ersten Start kein `GATEWAY_ADMIN_PASSWORD` gesetzt ist, erzeugt das Gateway einmalig ein Admin-Passwort und schreibt es ins Start-Log.
Die automatisch erzeugte Konfiguration startet mit `divera.dry_run=true`. Erst nach Eintragen des Divera247-Accesskeys und einem erfolgreichen Test sollte Dry-Run deaktiviert werden.
## WebUI
Die WebUI unter `http://localhost:8080/ui/` ist in Bereiche für **Divera247**, **Eingänge**, **Zuordnungen** sowie **Server & Sicherheit** gegliedert. Die Konfiguration erfolgt über Formulare; ein direkter JSON-Editor ist für den normalen Betrieb nicht mehr nötig.
Unter **Divera247** können Accesskey, UCR, Timeout und Dry-Run gepflegt werden. Die Stammdaten werden primär über die stabile v2-Schnittstelle `pull/all` geladen. Für PRO-/Mehrfacheinheiten wertet das Gateway `data.ucr` aus und lädt jede erreichbare User-Cluster-Relation separat; Benutzer werden aus `data.cluster.consumer` übernommen, wobei der numerische Collection-Key als **UCR-ID** für gezielte Alarmempfänger erhalten bleibt. Der v3-Endpunkt `user-cluster-relations` dient nur noch als Fallback, falls v2 keine Personen liefert. Die Stammdaten stehen anschließend in Zuordnungsregeln als Such- und Auswahlfelder zur Verfügung. Die Regelvorschau zeigt das resultierende Divera247-Payload, ohne es zu versenden.
## Beispiel: ntfy -> Divera247 Alarm
In der WebUI oder in `config.json` ein Mapping aktivieren und z. B. einen Token für Topic `alarm` setzen. Anschließend:
```bash
curl -X POST \
-H 'Authorization: Bearer replace-me' \
-H 'Title: FEUER3' \
-H 'Priority: high' \
--data 'Unklare Rauchentwicklung' \
http://localhost:8080/ntfy/alarm
```
JSON-Publish ist unter `/ntfy` oder `/in/ntfy` möglich:
```bash
curl -X POST -H 'Authorization: Bearer replace-me' \
-H 'Content-Type: application/json' \
-d '{"topic":"alarm","title":"TH1","message":"Baum auf Straße","priority":4}' \
http://localhost:8080/ntfy
```
## Beispiel: Gotify
```bash
curl -X POST 'http://localhost:8080/message?token=replace-me' \
-H 'Content-Type: application/json' \
-d '{"title":"Meldung","message":"Test","priority":5}'
```
## Konfigurationsmodell
Die Datei `config.example.json` zeigt das vollständige derzeitige Schema. Ein Mapping kann insbesondere diese Divera247-Ziele setzen:
- `target`: `alarm`, `news`, `event`
- `title_template`, `text_template`, `address_template`
- `notification_type`: 1 Einheit/Standort, 2 alle, 3 Gruppen, 4 Benutzer (entsprechend Divera247)
- `cluster_routes` (empfohlen für einheitsübergreifend, z. B. `{"123": 2}`), alternativ `clusters`, sowie `groups`, `users`, `vehicles`
- `send_push`, `send_sms`, `send_call`, `send_mail`, `send_pager`
- `private_mode`
- `extra`: zusätzliche API-Felder (z. B. `foreign_id`, `priority`, `response_time`, Event-Zeitstempel usw.)
Templates sind Go-`text/template` und erhalten das normalisierte Eingangsobjekt (`.Source`, `.Channel`, `.Title`, `.Message`, `.Address`, `.Priority`, `.Tags`, `.Raw`, `.ReceivedAt`).
## Sicherheitshinweise zum Alpha-Stand
- Die WebUI gehört hinter TLS (Reverse Proxy oder direkt späterer TLS-Support).
- Divera247-Accesskey und Ingress-Tokens liegen derzeit in der Konfigurationsdatei; Dateirechte werden auf `0600` gesetzt. Secret-Verschlüsselung/Secret-Store ist ein geplanter Schritt.
- Neue Passwörter verwenden bcrypt; vorhandene SHA-256-Hashes werden beim Login migriert. CSRF-Schutz, CSP, Größenlimits und Login-Rate-Limit sind integriert.
- Für echte Alarmierung zuerst mit einer Divera247-Testeinheit und `dry_run=true` prüfen.
Siehe `PROJECT_PLAN.md` und `API_SUPPORT.md` für Roadmap und Abdeckungsstand.
## Entwicklung prüfen
```sh
go test ./...
go vet ./...
node scripts/check-ui.cjs
```
Die Provider-Tests verwenden lokale HTTP-Testserver und Dry-Run; echte Nachrichten
werden dabei nicht versendet. Die UI-Prüfung kontrolliert JavaScript-Syntax und
eindeutige DOM-IDs. Zusätzlich existiert ein Browser-Test mit Chrome/Edge:
```sh
go build -o .cache/gateway-smoke.exe ./cmd/gateway
node scripts/browser-smoke.cjs
```
Er startet eine separate Testinstanz mit eigenem Profil und Dry-Run und prüft
Login, Formulare, Vorschau, Speichern und Zustellhistorie.