// static/admin/js/login.js // Log levels: 0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug const LOG_LEVEL = 4; // Set to 4 for full debugging, 1 for errors only const log = { error: (...args) => LOG_LEVEL >= 1 && console.error('❌ [ERROR]', ...args), warn: (...args) => LOG_LEVEL >= 2 && console.warn('⚠️ [WARN]', ...args), info: (...args) => LOG_LEVEL >= 3 && console.info('ℹ️ [INFO]', ...args), debug: (...args) => LOG_LEVEL >= 4 && console.log('🔍 [DEBUG]', ...args) }; function adminLogin() { return { dark: false, credentials: { username: '', password: '' }, loading: false, error: null, success: null, errors: {}, init() { log.info('Login page initializing...'); log.debug('Current pathname:', window.location.pathname); log.debug('Current URL:', window.location.href); // Just set theme - NO auth checking, NO token clearing! this.dark = localStorage.getItem('theme') === 'dark'; log.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) { log.warn('Found existing token on login page'); log.debug('Token preview:', token.substring(0, 20) + '...'); log.info('Not clearing token - user may have navigated here manually'); } else { log.debug('No existing token found'); } log.info('Login page initialization complete'); }, clearTokens() { log.debug('Clearing all auth tokens...'); const tokensBefore = { admin_token: !!localStorage.getItem('admin_token'), admin_user: !!localStorage.getItem('admin_user'), token: !!localStorage.getItem('token') }; log.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') }; log.debug('Tokens after clear:', tokensAfter); }, clearErrors() { log.debug('Clearing form errors'); this.error = null; this.success = null; this.errors = {}; }, validateForm() { log.debug('Validating login form...'); this.clearErrors(); let isValid = true; if (!this.credentials.username.trim()) { this.errors.username = 'Username is required'; log.warn('Validation failed: Username is required'); isValid = false; } if (!this.credentials.password) { this.errors.password = 'Password is required'; log.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'; log.warn('Validation failed: Password too short'); isValid = false; } log.info('Form validation result:', isValid ? 'VALID' : 'INVALID'); return isValid; }, async handleLogin() { log.info('=== LOGIN ATTEMPT STARTED ==='); if (!this.validateForm()) { log.warn('Form validation failed, aborting login'); return; } this.loading = true; this.clearErrors(); log.debug('Login state set to loading'); try { log.info('Calling login API endpoint...'); log.debug('Username:', this.credentials.username); log.debug('API endpoint: /api/v1/admin/auth/login'); const startTime = Date.now(); const response = await apiClient.post('/admin/auth/login', { username: this.credentials.username.trim(), password: this.credentials.password }); const duration = Date.now() - startTime; log.info(`Login API response received in ${duration}ms`); log.debug('Response structure:', { hasToken: !!response.access_token, hasUser: !!response.user, userRole: response.user?.role, userName: response.user?.username }); // Validate response if (!response.access_token) { log.error('Invalid response: No access token'); throw new Error('Invalid response from server - no token'); } if (response.user && response.user.role !== 'admin') { log.error('Authorization failed: User is not admin', { actualRole: response.user.role }); throw new Error('Access denied. Admin privileges required.'); } log.info('Login successful, storing authentication data...'); // Store authentication data localStorage.setItem('admin_token', response.access_token); localStorage.setItem('token', response.access_token); log.debug('Token stored, length:', response.access_token.length); if (response.user) { localStorage.setItem('admin_user', JSON.stringify(response.user)); log.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'); log.info('Storage verification:', { tokenStored: !!storedToken, userStored: !!storedUser, tokenLength: storedToken?.length }); // Show success message this.success = 'Login successful! Redirecting...'; log.info('Success message displayed to user'); log.info('Redirecting to dashboard immediately...'); log.info('=== EXECUTING REDIRECT ==='); log.debug('Target URL: /admin/dashboard'); log.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) { log.error('Login failed:', error); log.error('Error details:', { message: error.message, name: error.name, stack: error.stack }); this.error = error.message || 'Invalid username or password. Please try again.'; log.info('Error message displayed to user:', this.error); // Only clear tokens on login FAILURE this.clearTokens(); log.info('Tokens cleared after error'); } finally { this.loading = false; log.debug('Login state set to not loading'); log.info('=== LOGIN ATTEMPT FINISHED ==='); } }, toggleDarkMode() { log.debug('Toggling dark mode...'); this.dark = !this.dark; localStorage.setItem('theme', this.dark ? 'dark' : 'light'); log.info('Dark mode:', this.dark ? 'ON' : 'OFF'); } } }