first commit
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
# Dev-Setup & Live-Verifikation
|
||||
|
||||
## Voraussetzungen
|
||||
- Node ≥ 20, pnpm 10
|
||||
- Eine laufende MariaDB/MySQL (lokal reicht)
|
||||
|
||||
## 1. Dependencies
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
## 2. .env konfigurieren
|
||||
`.env` im Repo-Root (aus `.env.example` kopieren) und die DB-Zugangsdaten setzen.
|
||||
**Wichtig:** eine DEDIZIERTE Test-DB nutzen, NICHT die echte QBox-DB:
|
||||
|
||||
```dotenv
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_USER=root
|
||||
DB_PASSWORD=DEIN_MARIADB_PASSWORT
|
||||
DB_NAME=d4rk_mdt_dev # isolierte Test-DB — wird automatisch angelegt
|
||||
|
||||
VITE_DEV_AUTH_BYPASS=true # Browser-Login im Dev umgehen (Mock-Officer)
|
||||
```
|
||||
|
||||
## 3. Test-DB anlegen + seeden
|
||||
```bash
|
||||
pnpm db:setup:dev
|
||||
```
|
||||
Das Script (idempotent, non-destruktiv):
|
||||
1. legt die DB `d4rk_mdt_dev` an (falls nicht vorhanden),
|
||||
2. erstellt QBox-Stand-in-Tabellen `players` / `player_vehicles`,
|
||||
3. spielt die `mdt_*`-Migrationen ein,
|
||||
4. seedet 3 Test-Bürger, 3 Fahrzeuge, 3 Strafen.
|
||||
|
||||
Erwartete Ausgabe endet mit: `[setup-dev] Seed abgeschlossen ✅`
|
||||
|
||||
## 4. Starten
|
||||
```bash
|
||||
pnpm dev # api :3000 + web :5173 (Turborepo, parallel)
|
||||
```
|
||||
Browser: http://localhost:5190
|
||||
|
||||
## 5. Verifizieren (Testdaten)
|
||||
- **Personen** → Suche `Max` oder `Erika` → Detail öffnen (Job, Lizenzen, Notizen speichern, Fahndung togglen)
|
||||
- **Fahrzeuge** → Kennzeichen `COP 007` oder `MAX 001` → „Als gestohlen markieren"
|
||||
|
||||
## Gegen die echte QBox-DB (später, produktiv)
|
||||
`DB_NAME` auf die echte QBox-DB zeigen und **nur** die Migrationen einspielen
|
||||
(erzeugt ausschließlich `mdt_*`-Tabellen, fasst QBox-Tabellen nie an):
|
||||
```bash
|
||||
pnpm db:migrate
|
||||
```
|
||||
`pnpm db:setup:dev` dort NICHT ausführen (das legt QBox-Stand-in-Tabellen + Testdaten an).
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user