-
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user