Files
orion/static/admin/js/login.js

214 lines
8.2 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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');
}
}
}