← back to Bertha

react-dash/src/api.js

68 lines

const API = '/api';

// ── Unified DW Auth System ──
// Uses httpOnly cookie 'bertha_session' set by the server.
// Client cannot read/write the cookie directly — server manages it.

export async function api(path, opts = {}) {
  const res = await fetch(`${API}${path}`, {
    ...opts,
    credentials: 'same-origin', // send cookies with requests
    headers: { 'Content-Type': 'application/json', ...opts.headers },
  });
  if (res.status === 401 && !path.startsWith('/auth/')) {
    // Session expired or not authenticated — redirect to login
    window.location.href = '/login';
    return {};
  }
  return res.json();
}

export async function post(path, body) {
  return api(path, { method: 'POST', body: JSON.stringify(body) });
}

// Check if user has a valid session (server validates the httpOnly cookie)
export async function checkSession() {
  try {
    const data = await api('/auth/session');
    return data.authenticated === true;
  } catch {
    return false;
  }
}

// Login via unified auth endpoint — server sets httpOnly session cookie
export async function login(username, password) {
  const data = await post('/auth/login', { username, password });
  return data.success === true;
}

// Google OAuth login — send Google credential to server for verification
export async function googleLogin(credential) {
  const data = await post('/auth/google', { credential });
  return data;
}

// Get Google OAuth config (client ID)
export async function getGoogleConfig() {
  try {
    return await api('/auth/google-config');
  } catch { return { configured: false }; }
}

// Logout — server clears the httpOnly session cookie
export async function logout() {
  await post('/auth/logout', {});
  window.location.href = '/login';
}

// Legacy compat — isLoggedIn now checks session asynchronously
// For sync checks in Layout, we use a lightweight approach
export function isLoggedIn() {
  // We can't read httpOnly cookies from JS, so we rely on
  // the session check endpoint. For immediate nav guard,
  // Layout.jsx calls checkSession() on mount.
  return true; // Let Layout handle async check
}