feat: Zammad, Telegram und den Spiegel anbinden
Zammad liest ueber die Suche und schreibt nichts zurueck. Telegram holt per getUpdates statt per Webhook — der Planer soll auch hinter einem Anschluss ohne feste Adresse laufen. Der Spiegel schickt Belegungen ohne Titel und nur die ausdruecklich markierten Aufgaben. Wer dem Telegram-Bot schreibt, ohne im Adressbuch zu stehen, bekommt keine Antwort. Die einzige Ausnahme ist ein gueltiger Kopplungscode: Er ist der Beweis, dass jemand mit Zugang zur Anwendung diesen Chat will. Ohne ihn muesste man die Chatkennung von Hand eintragen — und um sie zu erfahren, muesste der Bot Unbekannten antworten. Jede Sendung des Spiegels traegt eine Signatur ueber den Rumpf und gilt fuenf Minuten. Der Empfaenger antwortet auf jeden Fehlschlag gleich: falsches Geheimnis, verstellte Uhr oder Unsinn im Inhalt sind von aussen nicht zu unterscheiden. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e4d3547457
commit
6dad3331e2
@@ -0,0 +1,45 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
import { auditSchreiben } from '@/server/audit'
|
||||
import { sendungAufnehmen, sendungPruefen } from '@/server/integration/spiegel'
|
||||
import { jetzt } from '@/server/zeitgeber'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
/**
|
||||
* Der Eingang des Spiegels — nur in der Instanz `daheim`.
|
||||
*
|
||||
* Hier meldet sich kein Mensch an: Die Gegenstelle weist sich über eine
|
||||
* Signatur aus, die sie mit dem gemeinsamen Geheimnis über den Rumpf bildet.
|
||||
*
|
||||
* Jede Zurückweisung sieht gleich aus. Ob das Geheimnis falsch war, die Uhr
|
||||
* verstellt oder der Inhalt Unsinn — von außen ist das nicht zu unterscheiden,
|
||||
* und genau so soll es sein.
|
||||
*/
|
||||
|
||||
export async function POST(anfrage: Request) {
|
||||
// Der Rumpf muss als Text gelesen werden: Die Signatur gilt für genau diese
|
||||
// Zeichen, nicht für das, was ein JSON-Parser daraus und wieder zurück macht.
|
||||
const koerper = await anfrage.text()
|
||||
const signatur = anfrage.headers.get('X-Planer-Signatur')
|
||||
|
||||
const geprueft = sendungPruefen(koerper, signatur, jetzt())
|
||||
if (!geprueft.ok) {
|
||||
return NextResponse.json({ fehler: 'Abgelehnt.' }, { status: 401 })
|
||||
}
|
||||
|
||||
const bericht = await sendungAufnehmen(geprueft.sendung, {
|
||||
id: null,
|
||||
email: 'spiegel@intern',
|
||||
})
|
||||
|
||||
await auditSchreiben({
|
||||
akteur: { id: null, email: 'spiegel@intern' },
|
||||
aktion: 'spiegel.empfangen',
|
||||
objektTyp: 'Spiegelbelegung',
|
||||
objektId: null,
|
||||
// Nur Zahlen: Was gespiegelt wurde, steht in den Datensätzen selbst.
|
||||
details: bericht,
|
||||
})
|
||||
|
||||
return NextResponse.json({ ok: true, ...bericht })
|
||||
}
|
||||
Reference in New Issue
Block a user