first commit

This commit is contained in:
2026-07-16 09:35:32 +02:00
commit dd0746e2e6
179 changed files with 25679 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
# FiveM-Bridge — Setup
Die Bridge (`fivem-bridge/`) verbindet das Ingame-Tablet mit dem MDT-Backend/Web.
Sie ist bewusst minimal: Token holen · Web-App im NUI-iframe öffnen · Dienst/Positionen
pushen · Waypoint setzen. Die eigentliche MDT-Logik lebt im Backend/Web.
## Architektur
```
Cop drückt Taste
→ Client holt Token vom Bridge-Server (lib.callback)
→ Bridge-Server ruft Backend POST /auth/fivem (Header x-bridge-secret)
← { token, user }
→ Client öffnet NUI-Shell (nui/index.html) mit <iframe src=WebUrl>
→ Shell postMessaged { action:'auth', token, user } ins iframe
→ Web-App ist eingeloggt
Server-Thread (nur im Dienst): GetEntityCoords → POST /bridge/officer/position
Dienstwechsel: POST /bridge/officer/duty
Andere Resource: exports.d4rk_tablet:createDispatch(...) → POST /bridge/dispatch
```
## Voraussetzungen
- `qbx_core`, `ox_lib`
- MDT-**Backend** erreichbar (Node, siehe [dev-setup.md](dev-setup.md))
- MDT-**Web-App** gehostet und erreichbar (der Build mit korrekten `VITE_API_URL`/`VITE_SOCKET_URL`, und **`VITE_DEV_AUTH_BYPASS=false`**!)
## server.cfg
```cfg
# MDT-Bridge
set mdt:backendUrl "https://mdt-api.deinserver.de" # Backend-Basis-URL (server→server)
set mdt:webUrl "https://mdt.deinserver.de" # gehostete Web-App (im iframe)
set mdt:bridgeSecret "<langes-zufalls-geheimnis>" # == BRIDGE_HMAC_SECRET im Backend!
set mdt:openCommand "mdt"
ensure d4rk_tablet # bzw. der Ordnername der Bridge-Resource
```
Wichtig:
- `mdt:bridgeSecret` **muss** `BRIDGE_HMAC_SECRET` in der Backend-`.env` entsprechen.
- Backend-`CORS_ORIGINS` muss die `mdt:webUrl`-Origin enthalten (das iframe fetcht cross-origin).
## Nutzung
- Taste/Command (`mdt`) öffnet das Tablet. Nur Jobs aus `Config.JobDepartments` bekommen Zugriff.
- `ESC` schließt es (oder Logout in der Web-App → `mdt:close`).
- **Dienst**: `/mdtduty` toggelt (oder QBox-`SetDuty`-Event). Nur im Dienst wird die Position gepusht → erscheint auf der Leitstellen-Karte.
- **Dispatch aus anderer Resource**:
```lua
exports.d4rk_tablet:createDispatch({
code = '10-90', title = 'Banküberfall', department = 'police',
priority = 'high', location = 'Pacific Standard',
coords = { x = 235.0, y = 216.0, z = 106.0 },
})
```
## Sicherheit
- Bridge↔Backend: Shared-Secret-Header `x-bridge-secret` (server-zu-server). Alternativ HMAC
(`x-mdt-timestamp` + `x-mdt-signature`) — das Backend akzeptiert beides.
- Positionen werden **server-seitig** via `GetEntityCoords` ermittelt (kein Vertrauen in Client-Coords).
- Der JWT-Token wird nur per `postMessage` an das iframe übergeben (nicht in der URL).
## Verifiziert
Backend-Contract per curl getestet: `/auth/fivem` (Secret → Token+User), `/bridge/officer/duty|position`,
`/bridge/dispatch` (Secret → 200, falsches/kein Secret → 401). Der Lua-Teil braucht einen laufenden
FiveM-Server zum Live-Test.