// static/admin/js/login.js // ✅ Use centralized logger - ONE LINE! // Create custom logger for login page const loginLog = window.LogConfig.createLogger('LOGIN'); function adminLogin() { return { dark: false, credentials: { username: '', password: '' }, loading: false, error: null, success: null, errors: {}, init() { loginLog.info('=== LOGIN PAGE INITIALIZING ==='); loginLog.debug('Current pathname:', window.location.pathname); loginLog.debug('Current URL:', window.location.href); // Just set theme - NO auth checking, NO token clearing! this.dark = localStorage.getItem('theme') === 'dark'; loginLog.debug('Dark mode:', this.dark); // DON'T clear tokens on init! // If user lands here with a valid token, they might be navigating manually // or got redirected. Let them try to login or navigate away. const token = localStorage.getItem('admin_token'); if (token) { loginLog.warn('Found existing token on login page'); loginLog.debug('Token preview:', token.substring(0, 20) + '...'); loginLog.info('Not clearing token - user may have navigated here manually'); } else { loginLog.debug('No existing token found'); } loginLog.info('=== LOGIN PAGE INITIALIZATION COMPLETE ==='); }, clearTokens() { loginLog.debug('Clearing all auth tokens...'); const tokensBefore = { admin_token: !!localStorage.getItem('admin_token'), admin_user: !!localStorage.getItem('admin_user'), token: !!localStorage.getItem('token') }; loginLog.debug('Tokens before clear:', tokensBefore); localStorage.removeItem('admin_token'); localStorage.removeItem('admin_user'); localStorage.removeItem('token'); const tokensAfter = { admin_token: !!localStorage.getItem('admin_token'), admin_user: !!localStorage.getItem('admin_user'), token: !!localStorage.getItem('token') }; loginLog.debug('Tokens after clear:', tokensAfter); }, clearErrors() { loginLog.debug('Clearing form errors'); this.error = null; this.success = null; this.errors = {}; }, validateForm() { loginLog.debug('Validating login form...'); this.clearErrors(); let isValid = true; if (!this.credentials.username.trim()) { this.errors.username = 'Username is required'; loginLog.warn('Validation failed: Username is required'); isValid = false; } if (!this.credentials.password) { this.errors.password = 'Password is required'; loginLog.warn('Validation failed: Password is required'); isValid = false; } else if (this.credentials.password.length < 6) { this.errors.password = 'Password must be at least 6 characters'; loginLog.warn('Validation failed: Password too short'); isValid = false; } loginLog.info('Form validation result:', isValid ? 'VALID' : 'INVALID'); return isValid; }, async handleLogin() { loginLog.info('=== LOGIN ATTEMPT STARTED ==='); if (!this.validateForm()) { loginLog.warn('Form validation failed, aborting login'); return; } this.loading = true; this.clearErrors(); loginLog.debug('Login state set to loading'); try { loginLog.info('Calling login API endpoint...'); loginLog.debug('Username:', this.credentials.username); const url = '/admin/auth/login'; const payload = { username: this.credentials.username.trim(), password: this.credentials.password }; window.LogConfig.logApiCall('POST', url, { username: payload.username }, 'request'); const startTime = performance.now(); const response = await apiClient.post(url, payload); const duration = performance.now() - startTime; window.LogConfig.logApiCall('POST', url, { hasToken: !!response.access_token, user: response.user?.username }, 'response'); window.LogConfig.logPerformance('Login', duration); loginLog.info(`Login API response received in ${duration}ms`); loginLog.debug('Response structure:', { hasToken: !!response.access_token, hasUser: !!response.user, userRole: response.user?.role, userName: response.user?.username }); // Validate response if (!response.access_token) { loginLog.error('Invalid response: No access token'); throw new Error('Invalid response from server - no token'); } if (response.user && response.user.role !== 'admin') { loginLog.error('Authorization failed: User is not admin', { actualRole: response.user.role }); throw new Error('Access denied. Admin privileges required.'); } loginLog.info('Login successful, storing authentication data...'); // Store authentication data localStorage.setItem('admin_token', response.access_token); localStorage.setItem('token', response.access_token); loginLog.debug('Token stored, length:', response.access_token.length); if (response.user) { localStorage.setItem('admin_user', JSON.stringify(response.user)); loginLog.debug('User data stored:', { username: response.user.username, role: response.user.role, id: response.user.id }); } // Verify storage const storedToken = localStorage.getItem('admin_token'); const storedUser = localStorage.getItem('admin_user'); loginLog.info('Storage verification:', { tokenStored: !!storedToken, userStored: !!storedUser, tokenLength: storedToken?.length }); // Show success message this.success = 'Login successful! Redirecting...'; loginLog.info('Success message displayed to user'); loginLog.info('Redirecting to dashboard immediately...'); loginLog.info('=== EXECUTING REDIRECT ==='); loginLog.debug('Target URL: /admin/dashboard'); loginLog.debug('Redirect method: window.location.href'); // Use href instead of replace to allow back button // But redirect IMMEDIATELY - don't wait! window.location.href = '/admin/dashboard'; } catch (error) { window.LogConfig.logError(error, 'Login'); this.error = error.message || 'Invalid username or password. Please try again.'; loginLog.info('Error message displayed to user:', this.error); // Only clear tokens on login FAILURE this.clearTokens(); loginLog.info('Tokens cleared after error'); } finally { this.loading = false; loginLog.debug('Login state set to not loading'); loginLog.info('=== LOGIN ATTEMPT FINISHED ==='); } }, toggleDarkMode() { loginLog.debug('Toggling dark mode...'); this.dark = !this.dark; localStorage.setItem('theme', this.dark ? 'dark' : 'light'); loginLog.info('Dark mode:', this.dark ? 'ON' : 'OFF'); } } } loginLog.info('Login module loaded');