// ── ERPNext API auth — service token + Authentik session guard ────────────── // ERPNext API calls use a service token. User auth is via Authentik forwardAuth // at the Traefik level. If the Authentik session expires mid-use, API calls // get redirected (302) — we detect this and reload to trigger re-auth. // ───────────────────────────────────────────────────────────────────────────── import { BASE_URL } from 'src/config/erpnext' // Service token injected at build time via VITE_ERP_TOKEN env var // Fallback: read from window.__ERP_TOKEN__ (set by server-side injection) const SERVICE_TOKEN = import.meta.env.VITE_ERP_TOKEN || window.__ERP_TOKEN__ || '' export function authFetch (url, opts = {}) { opts.headers = { ...opts.headers, Authorization: 'token ' + SERVICE_TOKEN } opts.redirect = 'manual' // Don't follow redirects — detect Authentik 302 return fetch(url, opts).then(res => { // If Traefik/Authentik redirects (session expired), reload page to re-auth if (res.type === 'opaqueredirect' || res.status === 302 || res.status === 401) { window.location.reload() return new Response('{}', { status: 401 }) } return res }) } export function getCSRF () { return null } export function invalidateCSRF () {} export async function login () { window.location.reload() } export async function logout () { window.location.href = 'https://auth.targo.ca/if/flow/default-invalidation-flow/' } export async function getLoggedUser () { try { const res = await fetch(BASE_URL + '/api/method/frappe.auth.get_logged_user', { headers: { Authorization: 'token ' + SERVICE_TOKEN }, }) if (res.ok) { const data = await res.json() return data.message || 'authenticated' } } catch {} return 'authenticated' }