5c6a21e2c3
The desktop shell is one generic .deb/.AppImage distributed via mca/public_releases, not built per-booth, but the backend origin was baked in at build time (VITE_API_BASE, hardcoded to http://127.0.0.1:3000) — the same installer could never point at a different appliance without a rebuild. Adds ConnectScreen (shown before Login in Tauri when no backend is saved), backed by tauri-plugin-store persisting the operator-entered URL across restarts. CSP's connect-src tightens to 'self' only — all backend traffic already routes through tauri-plugin-http/websocket, which run Rust-side and are outside connect-src's reach anyway — and the real access boundary moves to capabilities/default.json's http:default scope, wildcarded so an operator-chosen host is actually reachable. Adds a "Change server" control in Setup (desktop-only) to repoint an already-configured install. While tracing the desktop auth path for this: tauri-plugin-http's fetch() runs through Rust's reqwest, which keeps its own cookie jar separate from the webview, so document.cookie on tauri://localhost never sees the parking_csrf cookie the server sets (open upstream bug, tauri-apps/tauri#13045/#11518). This means the desktop app has likely been silently sending no CSRF header on every mutation since the shell was first built — pre-existing, independent of this change. Fixed by having sessionView() (routes/auth.ts) also echo the CSRF value in the login/me JSON body; the desktop client stashes it in memory and echoes that instead of reading document.cookie. assertCsrf() itself is untouched. Verified end-to-end against a real LAN-bound dev server: login returns a csrfToken matching the cookie, a mutation using the body-sourced token in X-CSRF-Token succeeds (200), and the same mutation without it still correctly 403s.
48 lines
1.3 KiB
JSON
48 lines
1.3 KiB
JSON
{
|
|
"name": "@parking/web",
|
|
"version": "0.0.0",
|
|
"private": true,
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "vite",
|
|
"build": "tsc -b && vite build",
|
|
"preview": "vite preview",
|
|
"typecheck": "tsc --noEmit",
|
|
"lint": "tsc --noEmit",
|
|
"test": "vitest run"
|
|
},
|
|
"dependencies": {
|
|
"@parking/shared": "workspace:*",
|
|
"@radix-ui/react-dialog": "^1.1.17",
|
|
"@radix-ui/react-dropdown-menu": "^2.1.18",
|
|
"@radix-ui/react-tabs": "^1.1.15",
|
|
"@tanstack/react-query": "^5.101.0",
|
|
"@tanstack/react-router": "^1.170.16",
|
|
"@tauri-apps/api": "^2.11.1",
|
|
"@tauri-apps/plugin-http": "^2.5.2",
|
|
"@tauri-apps/plugin-process": "^2.3.1",
|
|
"@tauri-apps/plugin-store": "^2.4.0",
|
|
"@tauri-apps/plugin-updater": "^2.10.1",
|
|
"@tauri-apps/plugin-websocket": "^2.3.0",
|
|
"i18next": "^26.3.1",
|
|
"react": "19.2.7",
|
|
"react-dom": "19.2.7",
|
|
"react-i18next": "^17.0.8",
|
|
"recharts": "^3.2.1",
|
|
"zustand": "^5.0.14"
|
|
},
|
|
"devDependencies": {
|
|
"@tailwindcss/vite": "^4.3.1",
|
|
"@tanstack/react-router-devtools": "^1.167.0",
|
|
"@types/react": "19.2.17",
|
|
"@types/react-dom": "19.2.3",
|
|
"@testing-library/react": "^16.1.0",
|
|
"@vitejs/plugin-react": "6.0.2",
|
|
"jsdom": "^25.0.1",
|
|
"tailwindcss": "^4.3.1",
|
|
"typescript": "6.0.3",
|
|
"vite": "8.0.16",
|
|
"vitest": "^4.1.9"
|
|
}
|
|
}
|