Jede eingehende Bewerbung landet weiterhin wie bisher in der D1-Datenbank, wird zusätzlich aber (falls eine Webhook-URL hinterlegt ist) als formatierte Discord-Nachricht in den passenden Kanal gepostet - pro Bewerbungsbereich (Modi/Scout/Creator/Kooperation) eine eigene Webhook-URL, exakt wie auf der Website getrennt. Läuft über normale Discord-Webhooks, kompatibel mit Ticketanizer, falls dessen Kanäle eigene Ziel-URLs im selben Format anbieten. - Neu: cloudflare-worker/src/lib/discord.js (Embed-Aufbau, Feld-Labels pro Formular, Farbe je Bewerbungsart) - applications.js: submitApplication ruft den Versand nach dem Speichern auf, über ctx.waitUntil() damit die Antwort an den Nutzer nicht wartet - worker.js: ctx wird jetzt an fetch() durchgereicht - Discord ist rein informativ - fehlt die Webhook-URL oder ist Discord kurz nicht erreichbar, wird die Bewerbung trotzdem ganz normal gespeichert - README.md: Einrichtungsanleitung (wrangler secret put DISCORD_WEBHOOK_*)
179 lines
8.4 KiB
Markdown
179 lines
8.4 KiB
Markdown
# DOGFATHER UNIVERSE — Interner Bereich (Cloudflare Worker + D1)
|
|
|
|
Setzt das Anforderungsdokument **„Geschützter Zugang, Rollen und Benutzerverwaltung"**
|
|
(`Geschuetzter_Zugang_Rollen_Benutzerverwaltung.pdf`) vollständig um: Session-basierte Anmeldung,
|
|
verschlüsselte (aber für Dogi jederzeit einsehbare) Zugangscodes, frei konfigurierbare Rollen mit
|
|
granularen Rechten, individuelle Ausnahmen pro Person, Aktivitätsprotokoll, Login-Lockout.
|
|
|
|
Kosten: läuft im kostenlosen Cloudflare-Tier (Workers Free, D1 Free, KV Free reichen locker).
|
|
|
|
## ✅ Bereits deployed
|
|
|
|
- **Interner Worker:** https://dogfather-universe-postfach.dogfather1608.workers.dev (Health-Check: `/health`)
|
|
- **D1-Datenbank:** `dogfather-universe-db`
|
|
- Website (`postfach.html`, `zugaenge.html`, `assets/js/*.js`) zeigt bereits auf diese URL.
|
|
|
|
Die Schritte unten sind nur nötig, falls der Worker mal neu aufgesetzt werden muss.
|
|
|
|
## Architektur
|
|
|
|
```
|
|
src/worker.js Router — verteilt Requests an die Handler unten
|
|
src/lib/crypto.js SHA-256-Hashing, AES-256-GCM-Verschlüsselung, ID/Token-Erzeugung
|
|
src/lib/auth.js Login-Prüfung, Sessions, Rate-Limiting/Lockout
|
|
src/lib/permissions.js Vollständiger Permission-Katalog aus dem Anforderungsdokument
|
|
src/lib/audit.js Aktivitätsprotokoll schreiben (nie mit Codes!)
|
|
src/lib/http.js CORS/JSON-Helfer
|
|
src/routes/auth.js Login/Logout
|
|
src/routes/users.js Zugänge und Teammitglieder (inkl. Code-Funktionen, NUR Owner)
|
|
src/routes/roles.js Rollen erstellen/umbenennen/löschen
|
|
src/routes/applications.js Bewerbungen: Status, Zuweisung, Notizen, Antwortentwürfe
|
|
src/routes/audit.js Aktivitätsprotokoll auslesen
|
|
migrations/0001_init.sql D1-Schema (users, roles, sessions, audit_log, applications, ...)
|
|
```
|
|
|
|
## Das Kernprinzip (aus dem Anforderungsdokument)
|
|
|
|
> Nur der Hauptadministrator sieht jederzeit alle vollständigen Zugangscodes und nur der
|
|
> Hauptadministrator darf sie erstellen, ändern, kopieren, zurücksetzen oder sperren.
|
|
|
|
Technisch umgesetzt:
|
|
|
|
- **Owner-Code** = das `POSTFACH_CODE`-Secret. Kein Datenbankeintrag, kann nicht gelöscht/verändert
|
|
werden außer von Dogi selbst per `wrangler secret put`.
|
|
- **Team-Codes** werden **zweifach** gespeichert:
|
|
- `code_hash` (SHA-256, nicht umkehrbar) — für den schnellen Login-Vergleich.
|
|
- `code_enc` (AES-256-GCM, umkehrbar) — nur damit kann der Owner sich den Klartext-Code später
|
|
wieder anzeigen lassen. Der Schlüssel dafür liegt ausschließlich im `ENCRYPTION_KEY`-Secret.
|
|
- **Code anzeigen** verlangt zusätzlich eine Re-Authentifizierung (Owner-Code erneut eingeben),
|
|
bevor der Klartext entschlüsselt und zurückgegeben wird.
|
|
- Folgende Aktionen sind **fest an `isOwner === true` gebunden** und erscheinen nirgends als
|
|
wählbare Berechtigung: Code anzeigen/kopieren/erstellen/ändern/zurücksetzen, den eigenen
|
|
Owner-Zugang bearbeiten, die Owner-Rolle löschen/einschränken, jemanden zum Owner machen.
|
|
|
|
## Voraussetzungen
|
|
|
|
- Ein (kostenloser) Cloudflare-Account
|
|
- Node.js installiert (für `npx wrangler`)
|
|
|
|
## Deploy von Grund auf (falls je nötig)
|
|
|
|
Alles im Ordner `cloudflare-worker/` ausführen:
|
|
|
|
```bash
|
|
cd cloudflare-worker
|
|
|
|
# 1. Bei Cloudflare einloggen
|
|
npx wrangler login
|
|
|
|
# 2. D1-Datenbank anlegen
|
|
npx wrangler d1 create dogfather-universe-db
|
|
# -> "database_id" aus der Ausgabe in wrangler.toml eintragen
|
|
|
|
# 3. Schema anlegen
|
|
npx wrangler d1 execute dogfather-universe-db --remote --file=migrations/0001_init.sql
|
|
|
|
# 4. KV-Namespace anlegen (nur noch für den Live-Status-Schalter genutzt)
|
|
npx wrangler kv namespace create BEWERBUNGEN
|
|
# -> "id" aus der Ausgabe in wrangler.toml eintragen
|
|
|
|
# 5. Owner-Code festlegen (dein persönlicher Hauptadministrator-Zugang)
|
|
npx wrangler secret put POSTFACH_CODE
|
|
|
|
# 6. Verschlüsselungs-Schlüssel für Team-Codes festlegen (32 zufällige Bytes, base64)
|
|
# z.B. erzeugen mit: node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
|
|
npx wrangler secret put ENCRYPTION_KEY
|
|
|
|
# 7. (Optional) Bewerbungen zusätzlich automatisch in Discord posten —
|
|
# siehe Abschnitt "Bewerbungen auf Discord (Ticketanizer)" unten.
|
|
# Ohne diesen Schritt läuft alles wie gehabt, es fehlt nur die
|
|
# Discord-Benachrichtigung.
|
|
|
|
# 8. Deployen
|
|
npx wrangler deploy
|
|
```
|
|
|
|
## Bewerbungen auf Discord (Ticketanizer)
|
|
|
|
Jede eingehende Bewerbung wird zusätzlich zur Speicherung in der Datenbank als
|
|
schön formatierte Nachricht (Embed) in den passenden Discord-Kanal gepostet —
|
|
pro Bewerbungsbereich ein eigener Kanal/Webhook, exakt wie auf der Website
|
|
getrennt (Modi, Scout, Creator, Kooperation).
|
|
|
|
**Das läuft komplett über normale Discord-Webhooks — kein Bot, kein
|
|
zusätzlicher Code auf Discord-Seite nötig.** Falls Ticketanizer selbst in
|
|
seinen Board-/Kanal-Einstellungen bereits eine eigene Ziel-Webhook-URL
|
|
anzeigt, kann diese genauso eingetragen werden wie eine normale
|
|
Discord-Webhook-URL — beide funktionieren identisch (Discord-Webhook-Format).
|
|
|
|
### Einrichtung (pro Kanal ca. 1 Minute)
|
|
|
|
1. Im Discord-Kanal (z.B. dem Modi-Bewerbungskanal): Kanal bearbeiten →
|
|
**Integrationen** → **Webhooks** → **Neuer Webhook**.
|
|
2. Der Webhook kann beliebig heißen (z.B. "Homepage-Bewerbungen"). **Webhook-URL
|
|
kopieren.**
|
|
3. Als Secret im Worker hinterlegen (einmal pro Bewerbungsbereich, nur die
|
|
URLs eintragen, die schon vorhanden sind — fehlende werden einfach
|
|
übersprungen, es gibt dafür keine Fehlermeldung):
|
|
|
|
```bash
|
|
npx wrangler secret put DISCORD_WEBHOOK_MODI
|
|
npx wrangler secret put DISCORD_WEBHOOK_SCOUT
|
|
npx wrangler secret put DISCORD_WEBHOOK_CREATOR
|
|
npx wrangler secret put DISCORD_WEBHOOK_KOOPERATION
|
|
```
|
|
|
|
Jeweils die kopierte Webhook-URL einfügen, wenn danach gefragt wird.
|
|
|
|
4. Danach einmal `npx wrangler deploy`, damit der Worker die neuen Secrets
|
|
kennt (Secrets selbst brauchen keinen Deploy, aber schadet nicht).
|
|
|
|
### Wichtig
|
|
|
|
- **Discord ist rein informativ, kein Ausfallpunkt.** Fehlt eine Webhook-URL
|
|
oder ist Discord kurz nicht erreichbar, wird die Bewerbung trotzdem ganz
|
|
normal in der Datenbank gespeichert — nur die Zusatz-Nachricht in Discord
|
|
entfällt dann.
|
|
- Secrets stehen **nie** im Code oder in `wrangler.toml` (die ist eingecheckt),
|
|
sondern ausschließlich verschlüsselt bei Cloudflare — genau wie
|
|
`POSTFACH_CODE` und `ENCRYPTION_KEY`.
|
|
- Ändern/Ersetzen einer URL: den jeweiligen `wrangler secret put ...`-Befehl
|
|
erneut ausführen, überschreibt den alten Wert.
|
|
|
|
## Wer den Owner-Code kennen darf
|
|
|
|
Nur du. Er ist dein Hauptadministrator-Zugang — sieht ausnahmslos alles, kann Zugänge/Rollen/Codes
|
|
verwalten. Ändern: `wrangler secret put POSTFACH_CODE` erneut ausführen.
|
|
|
|
## Zugänge und Teammitglieder verwalten
|
|
|
|
Auf `zugaenge.html` (verlinkt von `postfach.html`, wenn du als Owner eingeloggt bist):
|
|
|
|
- **Neue Zugänge erstellen** — Name, Benutzername, E-Mail, Rolle, Gültigkeit, Notiz. Code manuell
|
|
festlegen oder automatisch sicher generieren lassen. Wird **einmalig** im Klartext angezeigt —
|
|
danach nur noch über „Code anzeigen" (mit Re-Auth) abrufbar.
|
|
- **Rollen frei erstellen** — jedes einzelne Recht per Checkbox an-/abschaltbar (Bewerbungsbereiche,
|
|
Bearbeitung, Antworten, Notizen, Teamverwaltung, Einstellungen). Die Code-Funktionen tauchen dort
|
|
bewusst nirgends auf.
|
|
- **Individuelle Ausnahmen pro Person** — zusätzlich zur Rolle einzelne Rechte gezielt erlauben
|
|
oder entziehen.
|
|
- **Delegierbare Teilfunktion:** Personen mit dem Recht „Neue Benutzer vorbereiten" können einen
|
|
Entwurf anlegen (Name, Benutzername, Rolle) — der Zugang bleibt inaktiv, bis du ihn im Bereich
|
|
„Zugänge" mit „Freigeben & Code erstellen" final aktivierst.
|
|
- **Pro Person:** Code anzeigen/kopieren/neu erstellen (nur Owner), Sperren/Entsperren, alle
|
|
Sitzungen beenden (nur Owner), Rolle ändern, Rechte verwalten, vollständig löschen (nur Owner).
|
|
|
|
## Sicherheitsmaßnahmen
|
|
|
|
- Nach 5 falschen Codes pro Client 15 Minuten Sperre (`login_attempts`-Tabelle).
|
|
- Sessions: 30 Minuten Inaktivitäts-Timeout, 12 Stunden absolute Höchstdauer.
|
|
- Zugangscodes erscheinen **niemals** im Aktivitätsprotokoll, im Quelltext oder in Fehlermeldungen.
|
|
- CORS ist aktuell offen (`*`) — sobald die finale Domain feststeht, in `src/lib/http.js` →
|
|
`corsHeaders()` auf die echte Domain einschränken.
|
|
|
|
## Wartung
|
|
|
|
- Bewerbungen/Zugänge/Rollen: alles über `zugaenge.html` bzw. `postfach.html` als Owner.
|
|
- Direktzugriff auf die Datenbank bei Bedarf:
|
|
`npx wrangler d1 execute dogfather-universe-db --remote --command="SELECT ..."`
|