import { BASE_URL } from 'src/config/erpnext' /** * Auth shim for the customer portal. * * Before 2026-04-22 this wrapped a staff Authentik session. Customers no * longer authenticate via Authentik — they arrive with a magic-link JWT * and the customer store is hydrated directly from it. See stores/customer.js. * * We still read an ERP service token so ERPNext's REST resources (Sales * Invoice, Issue, …) accept our server-side calls. That token is a fixed * API key, not a session — it's injected at build time via VITE_ERP_TOKEN * or at runtime via window.__ERP_TOKEN__. */ 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' if (opts.method && opts.method !== 'GET') { opts.credentials = 'omit' } return fetch(url, opts).then(res => { // 401 from ERPNext means the service token is broken — fail loud in console, // but don't nuke the user's tab. Their magic-link session is independent. if (res.status === 401) { console.warn('[portal] ERPNext returned 401 — check VITE_ERP_TOKEN') } return res }) } 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' } /** * Customer logout — clear the store and bounce to /login. No Authentik * involvement. The magic-link JWT, once minted, is stateless on the server * and expires on its own; clearing the client store is sufficient. */ export async function logout () { try { const { useCustomerStore } = await import('src/stores/customer') useCustomerStore().clear() } catch { /* ignore — fall through to hard redirect */ } window.location.hash = '#/login' // Force a reload so every module drops any cached customer data. window.location.reload() }