diff --git a/app/webui/js/auth.js b/app/webui/js/auth.js new file mode 100644 index 0000000..f44a045 --- /dev/null +++ b/app/webui/js/auth.js @@ -0,0 +1,81 @@ +/** + * Auth helper functions (login, register, logout, refresh). + * + * These are plain functions that can be called from anywhere (Alpine-stores, + * page-level handlers). They do NOT depend on Alpine — only on api.js and + * localStorage. + * + * The Alpine store in store.js wraps these so the UI can react to state changes. + */ + +import { api, setToken, clearToken, getToken } from './api.js'; + +/** + * Login with email + password. + * Backend: POST /api/v1/auth/login → {access_token, token_type, expires_in} + * + * @param {string} email + * @param {string} password + * @returns {Promise<{access_token: string, token_type: string, expires_in: number}>} + */ +export async function login(email, password) { + const res = await api.post('/auth/login', { email, password }); + if (res && res.access_token) { + setToken(res.access_token); + } + return res; +} + +/** + * Register a new user (first-admin bootstrap or admin invites a sales-rep). + * Backend: POST /api/v1/auth/register → {user, access_token, token_type, expires_in} + * + * @param {{email: string, password: string, name: string, role?: string}} payload + */ +export async function register(payload) { + const res = await api.post('/auth/register', payload); + if (res && res.access_token) { + setToken(res.access_token); + } + return res; +} + +/** + * Logout: tell the backend (best-effort), clear local JWT, redirect to login. + * Backend: POST /api/v1/auth/logout → {message: "logged out"} + */ +export async function logout() { + if (getToken()) { + try { + await api.post('/auth/logout', {}); + } catch { + // best-effort — even if the backend is down, we still clear the local token + } + } + clearToken(); + window.location.href = '/index.html'; +} + +/** + * Refresh the JWT using the current (still-valid) token. + * Backend: POST /api/v1/auth/refresh → {access_token, token_type, expires_in} + * + * @returns {Promise<{access_token: string, token_type: string, expires_in: number}>} + */ +export async function refreshToken() { + const res = await api.post('/auth/refresh', {}); + if (res && res.access_token) { + setToken(res.access_token); + } + return res; +} + +/** + * Fetch the currently-authenticated user's profile. + * Backend: GET /api/v1/users/me → UserOut + * + * @returns {Promise} + */ +export async function fetchCurrentUser() { + return api.get('/users/me'); +}