/** * Authentication API client for the dashboard. * * Provides functions to interact with auth endpoints including login, * logout, and fetching current user information. */ export interface User { id: number; username: string; role: 'user' | 'editor' | 'admin' | 'superadmin'; is_active: boolean; } export interface LoginRequest { username: string; password: string; } export interface LoginResponse { message: string; user: { id: number; username: string; role: string; }; } export interface AuthCheckResponse { authenticated: boolean; role?: string; } /** * Change password for the currently authenticated user. */ export async function changePassword(currentPassword: string, newPassword: string): Promise<{ message: string }> { const res = await fetch('/api/auth/change-password', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, credentials: 'include', body: JSON.stringify({ current_password: currentPassword, new_password: newPassword }), }); const data = await res.json(); if (!res.ok) { throw new Error(data.error || 'Failed to change password'); } return data as { message: string }; } /** * Authenticate a user with username and password. * * @param username - The user's username * @param password - The user's password * @returns Promise * @throws Error if login fails */ export async function login(username: string, password: string): Promise { const res = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', // Important for session cookies body: JSON.stringify({ username, password }), }); const data = await res.json(); if (!res.ok || data.error) { throw new Error(data.error || 'Login failed'); } return data; } /** * Log out the current user. * * @returns Promise * @throws Error if logout fails */ export async function logout(): Promise { const res = await fetch('/api/auth/logout', { method: 'POST', credentials: 'include', }); const data = await res.json(); if (!res.ok || data.error) { throw new Error(data.error || 'Logout failed'); } } /** * Fetch the current authenticated user's information. * * @returns Promise * @throws Error if not authenticated or request fails */ export async function fetchCurrentUser(): Promise { const res = await fetch('/api/auth/me', { method: 'GET', credentials: 'include', }); const data = await res.json(); if (!res.ok || data.error) { throw new Error(data.error || 'Failed to fetch current user'); } return data as User; } /** * Quick check if user is authenticated (lighter than fetchCurrentUser). * * @returns Promise */ export async function checkAuth(): Promise { const res = await fetch('/api/auth/check', { method: 'GET', credentials: 'include', }); const data = await res.json(); if (!res.ok) { throw new Error('Failed to check authentication status'); } return data; } /** * Helper function to check if a user has a specific role. * * @param user - The user object * @param role - The role to check for * @returns boolean */ export function hasRole(user: User | null, role: string): boolean { if (!user) return false; return user.role === role; } /** * Helper function to check if a user has any of the specified roles. * * @param user - The user object * @param roles - Array of roles to check for * @returns boolean */ export function hasAnyRole(user: User | null, roles: string[]): boolean { if (!user) return false; return roles.includes(user.role); } /** * Helper function to check if user is superadmin. */ export function isSuperadmin(user: User | null): boolean { return hasRole(user, 'superadmin'); } /** * Helper function to check if user is admin or higher. */ export function isAdminOrHigher(user: User | null): boolean { return hasAnyRole(user, ['admin', 'superadmin']); } /** * Helper function to check if user is editor or higher. */ export function isEditorOrHigher(user: User | null): boolean { return hasAnyRole(user, ['editor', 'admin', 'superadmin']); }