Commit Graph

7 Commits

Author SHA1 Message Date
louispaulb
6fc8a2d37f refactor: externalize ERP service token via VITE_ERP_TOKEN env var
Token is no longer hardcoded in source — injected at build time.
Build with: VITE_ERP_TOKEN="key:secret" npx quasar build
Prevents accidental token invalidation and keeps secrets out of git.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:39:41 -04:00
louispaulb
1263786b90 fix: update service token + fix API proxy routing
- Regenerated Admin API token (old one was invalidated by generate_keys)
- Traefik: separate routers for app (with Authentik) and /api/ (no auth)
- Nginx proxy: use container IP (cross-compose DNS doesn't resolve names)
- /outpost.goauthentik.io/ route for Authentik callbacks

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:39:11 -04:00
louispaulb
7ef22873f0 fix: handle Authentik session expiry in SPA
- authFetch uses redirect:'manual' to detect 302 from Authentik
- If session expired (302/401/opaqueredirect), reload page to trigger
  Traefik forwardAuth → Authentik re-login flow
- Logout redirects to Authentik invalidation flow
- App.vue calls checkSession on mount to populate user identity

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:34:39 -04:00
louispaulb
f1faffeab9 feat: switch Dispatch auth to Authentik forwardAuth
- Remove login form from App.vue (Authentik handles auth at Traefik level)
- Simplify auth store: no more checkSession/generate_keys complexity
- All ERPNext API calls use a service token (reliable, no CORS issues)
- User identity provided by Authentik X-authentik-email header
- Logout redirects to Authentik end-session URL
- Removed: login(), generate_keys, cookie fallback, token localStorage

Infrastructure:
- Created Authentik Proxy Provider for dispatch.gigafibre.ca
- Added to embedded outpost
- Applied authentik@file middleware to dispatch Traefik router
- Also removed unused Gitea (git.gigafibre.ca) containers + volumes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 13:33:09 -04:00
louispaulb
af42c6082e feat: auth gate, GPS hybrid tracking, tech CRUD modal, ERPNext API proxy
Authentication:
- Add App.vue login gate (v-if auth.loading / v-else-if !auth.user / router-view)
- Fix auth.checkSession with try/finally to always reset loading
- Fix generate_keys method name for Frappe v16 (generate_keys, not generate_keys_for_api_user)
- Auto-generate API token on cookie-based auth (Authentik SSO support)
- Remove duplicate checkSession from DispatchV2Page (was causing infinite mount/unmount loop)

GPS Tracking — Hybrid REST + WebSocket:
- Initial REST fetch per-device in parallel (Traccar API only supports one deviceId per request)
- WebSocket real-time updates via wss://dispatch.gigafibre.ca/traccar/api/socket
- Auto-fallback to 30s polling if WebSocket fails, with exponential backoff reconnect
- Module-level guards (__gpsStarted, __gpsPolling) to prevent loops on component remount
- Only update tech.gpsCoords when value actually changes (prevents unnecessary reactive triggers)

Tech Management (GPS Modal):
- Add/delete technicians directly from GPS modal → persists to ERPNext
- Inline edit: double-click name to rename, phone field, status select
- Auto-generate technician_id (TECH-N+1)
- Unlink jobs before delete to avoid ERPNext LinkExistsError
- Added phone/email custom fields to Dispatch Technician doctype

Infrastructure:
- Nginx proxy: /api/ → ERPNext (same-origin, eliminates all CORS issues)
- Nginx proxy: /traccar/ WebSocket support (Upgrade headers, 86400s timeout)
- No-cache headers on index.html and sw.js for instant PWA updates
- BASE_URL switched to empty string in production (same-origin via proxy)

Bug fixes:
- ERPNext Number Card PostgreSQL fix (ORDER BY on aggregate queries)
- Traccar fetchPositions: parallel per-device calls (API ignores multiple deviceId params)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:02:04 -04:00
louispaulb
f1badea201 fix: add watcher for GPS position updates on map markers
Technician GPS positions from Traccar were being fetched and stored
correctly every 30s but drawMapMarkers() was never triggered on
gpsCoords change, so markers stayed at their initial position.

Added a deep watcher on store.technicians[].gpsCoords in useMap.js
that calls drawMapMarkers() whenever any technician's GPS position
is updated by pollGps().

Also includes traccar.js API module and dispatch store GPS polling
(pollGps / startGpsPolling / stopGpsPolling).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 20:17:13 -04:00
louispaulb
1b0fc89304 Initial commit — OSS/BSS Field Dispatch app
Current state: custom CSS + vanilla Vue components
Architecture: modular with composables, provide/inject pattern
Ready for progressive migration to Quasar native components

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 14:11:40 -04:00