File auth-module.js of Package PersistenceOS

/**
 * PersistenceOS Authentication Module
 * Handles user authentication, session management, and security
 * 
 * Depends on: core-utils.js
 */

// =============================================================================
// AUTHENTICATION STATE
// =============================================================================

const authState = {
    isAuthenticated: false,
    currentUser: null,
    token: null,
    loginAttempts: 0,
    maxLoginAttempts: 5,
    lockoutTime: 300000 // 5 minutes
};

// =============================================================================
// AUTHENTICATION FUNCTIONS
// =============================================================================

/**
 * Initialize authentication system
 */
function initializeAuth() {
    console.log('🔐 Initializing authentication system...');
    
    // Check for existing authentication
    const token = localStorage.getItem('access_token');
    const userData = PersistenceCore.getStorageItem('user_data');
    const authenticated = localStorage.getItem('authenticated') === 'true';
    
    if (token && userData && authenticated) {
        authState.isAuthenticated = true;
        authState.currentUser = userData;
        authState.token = token;
        console.log('✅ User already authenticated:', userData.username);
    } else {
        console.log('â„šī¸ No valid authentication found');
        clearAuthState();
    }
    
    return authState.isAuthenticated;
}

/**
 * Perform user login
 * @param {string} username - Username
 * @param {string} password - Password
 * @returns {Promise<boolean>} - Success status
 */
async function login(username, password) {
    console.log(`🔐 Attempting login for user: ${username}`);
    
    // Check for lockout
    if (isAccountLocked()) {
        const remainingTime = getRemainingLockoutTime();
        PersistenceCore.showNotification(
            `Account locked. Try again in ${Math.ceil(remainingTime / 60000)} minutes.`,
            'error'
        );
        return false;
    }
    
    try {
        const response = await fetch('/api/auth/login', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ username, password })
        });
        
        if (response.ok) {
            const data = await response.json();
            
            // Store authentication data
            localStorage.setItem('access_token', data.access_token);
            localStorage.setItem('authenticated', 'true');
            localStorage.setItem('username', username);
            PersistenceCore.setStorageItem('user_data', {
                username: username,
                loginTime: new Date().toISOString(),
                permissions: data.permissions || ['read', 'write']
            });
            
            // Update auth state
            authState.isAuthenticated = true;
            authState.currentUser = { username, permissions: data.permissions || ['read', 'write'] };
            authState.token = data.access_token;
            authState.loginAttempts = 0;
            
            // Clear lockout data
            localStorage.removeItem('lockout_time');
            localStorage.removeItem('login_attempts');
            
            console.log('✅ Login successful');
            PersistenceCore.showNotification('Login successful!', 'success');
            return true;
            
        } else {
            // Handle login failure
            authState.loginAttempts++;
            localStorage.setItem('login_attempts', authState.loginAttempts.toString());
            
            if (authState.loginAttempts >= authState.maxLoginAttempts) {
                const lockoutTime = Date.now() + authState.lockoutTime;
                localStorage.setItem('lockout_time', lockoutTime.toString());
                PersistenceCore.showNotification(
                    `Too many failed attempts. Account locked for ${authState.lockoutTime / 60000} minutes.`,
                    'error'
                );
            } else {
                const remainingAttempts = authState.maxLoginAttempts - authState.loginAttempts;
                PersistenceCore.showNotification(
                    `Invalid credentials. ${remainingAttempts} attempts remaining.`,
                    'error'
                );
            }
            
            console.log('❌ Login failed');
            return false;
        }
        
    } catch (error) {
        console.error('❌ Login error:', error);
        PersistenceCore.showNotification('Login failed: Network error', 'error');
        return false;
    }
}

/**
 * Perform user logout
 */
function logout() {
    console.log('🔐 Logging out user...');
    
    // Clear authentication data
    clearAuthState();
    
    // Notify user
    PersistenceCore.showNotification('Logged out successfully', 'info');
    
    // Redirect to login page
    setTimeout(() => {
        window.location.href = '/login.html';
    }, 1000);
}

/**
 * Clear authentication state
 */
function clearAuthState() {
    // Clear localStorage
    localStorage.removeItem('access_token');
    localStorage.removeItem('user_data');
    localStorage.removeItem('authenticated');
    localStorage.removeItem('username');
    localStorage.removeItem('fallback_auth');
    
    // Clear auth state
    authState.isAuthenticated = false;
    authState.currentUser = null;
    authState.token = null;
}

/**
 * Check if account is locked due to failed login attempts
 * @returns {boolean}
 */
function isAccountLocked() {
    const lockoutTime = localStorage.getItem('lockout_time');
    if (!lockoutTime) return false;
    
    const lockoutExpiry = parseInt(lockoutTime);
    return Date.now() < lockoutExpiry;
}

/**
 * Get remaining lockout time in milliseconds
 * @returns {number}
 */
function getRemainingLockoutTime() {
    const lockoutTime = localStorage.getItem('lockout_time');
    if (!lockoutTime) return 0;
    
    const lockoutExpiry = parseInt(lockoutTime);
    return Math.max(0, lockoutExpiry - Date.now());
}

/**
 * Check if user has specific permission
 * @param {string} permission - Permission to check
 * @returns {boolean}
 */
function hasPermission(permission) {
    if (!authState.isAuthenticated || !authState.currentUser) {
        return false;
    }
    
    const permissions = authState.currentUser.permissions || [];
    return permissions.includes(permission) || permissions.includes('admin');
}

/**
 * Require authentication for function execution
 * @param {Function} func - Function to execute if authenticated
 * @param {string} requiredPermission - Optional required permission
 * @returns {Function}
 */
function requireAuth(func, requiredPermission = null) {
    return function(...args) {
        if (!authState.isAuthenticated) {
            PersistenceCore.showNotification('Authentication required', 'warning');
            logout();
            return;
        }
        
        if (requiredPermission && !hasPermission(requiredPermission)) {
            PersistenceCore.showNotification('Insufficient permissions', 'error');
            return;
        }
        
        return func.apply(this, args);
    };
}

/**
 * Refresh authentication token
 * @returns {Promise<boolean>}
 */
async function refreshToken() {
    if (!authState.token) return false;
    
    try {
        const response = await fetch('/api/auth/refresh', {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${authState.token}`,
                'Content-Type': 'application/json'
            }
        });
        
        if (response.ok) {
            const data = await response.json();
            localStorage.setItem('access_token', data.access_token);
            authState.token = data.access_token;
            console.log('✅ Token refreshed successfully');
            return true;
        } else {
            console.log('❌ Token refresh failed');
            logout();
            return false;
        }
    } catch (error) {
        console.error('❌ Token refresh error:', error);
        return false;
    }
}

/**
 * Setup automatic token refresh
 */
function setupTokenRefresh() {
    // Refresh token every 30 minutes
    setInterval(async () => {
        if (authState.isAuthenticated) {
            await refreshToken();
        }
    }, 30 * 60 * 1000);
}

// =============================================================================
// INITIALIZATION
// =============================================================================

// Initialize authentication on module load
document.addEventListener('DOMContentLoaded', () => {
    initializeAuth();
    setupTokenRefresh();

    // Dispatch authentication state change event
    window.dispatchEvent(new CustomEvent('auth-state-changed', {
        detail: {
            isAuthenticated: authState.isAuthenticated,
            user: authState.currentUser
        }
    }));
});

// =============================================================================
// EXPORT FOR MODULE SYSTEM
// =============================================================================

window.PersistenceAuth = {
    state: authState,
    initializeAuth,
    login,
    logout,
    clearAuthState,
    isAccountLocked,
    getRemainingLockoutTime,
    hasPermission,
    requireAuth,
    refreshToken,
    setupTokenRefresh
};

console.log('✅ PersistenceOS Authentication Module loaded');
openSUSE Build Service is sponsored by