/** * Authentication Module for Weight Tracker * Provides password protection for the application */ const Auth = (() => { // Session storage key const AUTH_KEY = 'weight_tracker_auth'; // Default password hash (can be overridden via environment variables) // This is a bcrypt hash of "password" - should be replaced in production let passwordHash = '$2a$10$EgxHKjDDFcZKtQY9hl/N4.QvEQHCXVnQXw9dzFYlUDVKOcLMGp9eq'; // Login state let isAuthenticated = false; /** * Initialize the authentication module */ const init = () => { // Check for password hash in environment variables (passed via meta tag) const envPasswordHash = document.querySelector('meta[name="password-hash"]')?.getAttribute('content'); if (envPasswordHash) { passwordHash = envPasswordHash; } // Check if already authenticated checkAuthStatus(); // If not authenticated, show login screen if (!isAuthenticated) { showLoginScreen(); } }; /** * Check if the user is authenticated */ const checkAuthStatus = () => { const authData = sessionStorage.getItem(AUTH_KEY); isAuthenticated = authData === 'true'; return isAuthenticated; }; /** * Show the login screen */ const showLoginScreen = () => { // Create login overlay const overlay = document.createElement('div'); overlay.className = 'login-overlay'; overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.backgroundColor = 'var(--background-color, #f8f9fa)'; overlay.style.zIndex = '9999'; overlay.style.display = 'flex'; overlay.style.justifyContent = 'center'; overlay.style.alignItems = 'center'; // Create login form overlay.innerHTML = `

Keep My Weight

Simple, private weight & meal tracking

Your data stays private, always. This password protects your personal health information.

`; // Add to DOM document.body.appendChild(overlay); // Handle form submission const form = document.getElementById('login-form'); form.addEventListener('submit', async (e) => { e.preventDefault(); const password = document.getElementById('password').value; const errorMessage = document.getElementById('error-message'); try { // Use bcrypt.js for password verification const bcrypt = window.dcodeIO?.bcrypt; if (!bcrypt) { throw new Error('bcrypt.js not loaded'); } // Verify password const isMatch = await new Promise((resolve) => { bcrypt.compare(password, passwordHash, (err, result) => { if (err) { console.error('Error verifying password:', err); resolve(false); } else { resolve(result); } }); }); if (isMatch) { // Set as authenticated sessionStorage.setItem(AUTH_KEY, 'true'); isAuthenticated = true; // Remove login overlay document.body.removeChild(overlay); } else { errorMessage.textContent = 'Invalid password. Please try again.'; } } catch (error) { console.error('Authentication error:', error); errorMessage.textContent = 'An error occurred during authentication. Please try again.'; } }); }; /** * Log out the user */ const logout = () => { sessionStorage.removeItem(AUTH_KEY); isAuthenticated = false; showLoginScreen(); }; // Return public API return { init, checkAuthStatus, logout }; })();