/** * Simplified Authentication Helper * * This provides a streamlined authentication solution that works with * the simplified server-side authentication approach. */ class SimpleAuth { /** * Initialize the authentication helper */ constructor() { this.token = localStorage.getItem('token'); this.user = JSON.parse(localStorage.getItem('user') || 'null'); } /** * Parse a JWT token to extract its payload * @param {string} token - The JWT token to parse * @returns {object|null} The decoded payload or null if invalid */ parseJwt(token) { try { const base64Url = token.split('.')[1]; const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); return JSON.parse(jsonPayload); } catch (e) { console.error('Error parsing JWT token:', e); return null; } } /** * Login a user * @param {object} credentials - The user credentials (username, password) * @returns {Promise} The login result */ async login(credentials) { try { const response = await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credentials) }); const data = await response.json(); if (!response.ok) { throw new Error(data.error || 'Login failed'); } // Store token and user data this.token = data.token; localStorage.setItem('token', data.token); // Parse user data from token const payload = this.parseJwt(data.token); this.user = { id: payload.uid, username: payload.username, accessLevel: payload.accessLevel }; localStorage.setItem('user', JSON.stringify(this.user)); return { success: true, user: this.user }; } catch (error) { console.error('Login error:', error); return { success: false, error: error.message }; } } /** * Logout the current user */ logout() { this.token = null; this.user = null; localStorage.removeItem('token'); localStorage.removeItem('user'); // Redirect to home page window.location.href = '/'; } /** * Check if the user is authenticated * @returns {boolean} True if authenticated, false otherwise */ isAuthenticated() { return !!this.token && !!this.user; } /** * Check if the user is an admin * @returns {boolean} True if admin, false otherwise */ isAdmin() { return this.isAuthenticated() && this.user.accessLevel === 1; } /** * Get the current user * @returns {object|null} The current user or null if not authenticated */ getUser() { return this.user; } /** * Get the authentication token * @returns {string|null} The token or null if not authenticated */ getToken() { return this.token; } /** * Make an authenticated API request * @param {string} url - The URL to fetch * @param {object} options - Fetch options * @returns {Promise} The fetch response */ async fetchAuth(url, options = {}) { if (!this.token) { throw new Error('Not authenticated'); } const headers = { ...options.headers, 'Authorization': `Bearer ${this.token}` }; return fetch(url, { ...options, headers }); } } // Create a global instance const auth = new SimpleAuth();