This commit is contained in:
2026-09-16 06:32:26 +02:00
parent 4f8e0bbb04
commit 85f84bc391
+125 -1
View File
@@ -1,2 +1,126 @@
# notify-gateway
# 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.