import type { User } from '~/utils/types'; export const useAuth = () => { const user = ref(null); const isAuthenticated = computed(() => !!user.value); const loading = ref(false); const error = ref(null); // Tier-based computed properties const userTier = computed(() => user.value?.tier || 'user'); const isUser = computed(() => user.value?.tier === 'user'); const isBoard = computed(() => user.value?.tier === 'board'); const isAdmin = computed(() => user.value?.tier === 'admin'); const firstName = computed(() => { if (user.value?.firstName) return user.value.firstName; if (user.value?.name) return user.value.name.split(' ')[0]; return 'User'; }); // Helper methods const hasTier = (requiredTier: 'user' | 'board' | 'admin') => { return user.value?.tier === requiredTier; }; const hasGroup = (groupName: string) => { return user.value?.groups?.includes(groupName) || false; }; // Legacy compatibility const hasRole = (role: string) => { return hasGroup(role); }; // Direct login method const login = async (credentials: { username: string; password: string; rememberMe?: boolean }) => { loading.value = true; error.value = null; try { console.log('🔄 Starting login request...'); const response = await $fetch<{ success: boolean; redirectTo?: string; user?: User; }>('/api/auth/direct-login', { method: 'POST', body: credentials, timeout: 30000 // 30 second timeout }); console.log('✅ Login response received:', response); if (response.success) { // Add a small delay to ensure cookie is set before checking session console.log('⏳ Waiting for cookie to be set...'); await new Promise(resolve => setTimeout(resolve, 200)); // After successful login, get the user data from the session console.log('🔄 Getting user data from session...'); // Try multiple times in case of timing issues let sessionSuccess = false; let attempts = 0; const maxAttempts = 3; while (!sessionSuccess && attempts < maxAttempts) { attempts++; console.log(`🔄 Session check attempt ${attempts}/${maxAttempts}`); sessionSuccess = await checkAuth(); if (!sessionSuccess && attempts < maxAttempts) { console.log('⏳ Session not ready, waiting 500ms...'); await new Promise(resolve => setTimeout(resolve, 500)); } } if (sessionSuccess) { console.log('👤 User data retrieved from session:', user.value); // Return redirect URL for the component to handle console.log('✅ Login successful, returning redirect URL:', response.redirectTo || '/dashboard'); return { success: true, redirectTo: response.redirectTo || '/dashboard' }; } else { console.warn('❌ Failed to get user data from session after login'); // Still return success with redirect since login was successful on server return { success: true, redirectTo: '/dashboard' }; } } console.warn('❌ Login response indicates failure:', response); return { success: false, error: 'Login failed' }; } catch (err: any) { console.error('❌ Login error caught:', err); // Handle different types of errors let errorMessage = 'Login failed'; if (err.status === 502) { errorMessage = 'Server temporarily unavailable. Please try again.'; } else if (err.status === 401) { errorMessage = 'Invalid username or password'; } else if (err.status === 429) { errorMessage = 'Too many login attempts. Please try again later.'; } else if (err.data?.message) { errorMessage = err.data.message; } else if (err.message) { errorMessage = err.message; } error.value = errorMessage; return { success: false, error: errorMessage }; } finally { loading.value = false; } }; // OAuth login method (fallback) const loginOAuth = () => { return navigateTo('/api/auth/login'); }; // Password reset method const requestPasswordReset = async (email: string) => { loading.value = true; error.value = null; try { const response = await $fetch<{ success: boolean; message: string; }>('/api/auth/forgot-password', { method: 'POST', body: { email } }); return { success: true, message: response.message }; } catch (err: any) { error.value = err.data?.message || 'Password reset failed'; return { success: false, error: error.value }; } finally { loading.value = false; } }; // Check authentication status - simple and reliable const checkAuth = async () => { try { console.log('🔄 Performing session check...'); const response = await $fetch<{ authenticated: boolean; user: User | null; }>('/api/auth/session'); if (response.authenticated && response.user) { user.value = response.user; return true; } else { user.value = null; return false; } } catch (err) { console.error('Auth check error:', err); user.value = null; return false; } }; // Logout method const logout = async () => { try { await $fetch('/api/auth/logout', { method: 'POST' }); user.value = null; await navigateTo('/login'); } catch (err) { console.error('Logout error:', err); user.value = null; await navigateTo('/login'); } }; return { // State user: readonly(user), isAuthenticated, loading: readonly(loading), error: readonly(error), // Tier-based properties userTier, isUser, isBoard, isAdmin, firstName, // Helper methods hasTier, hasGroup, hasRole, // Legacy compatibility // Actions login, loginOAuth, logout, requestPasswordReset, checkAuth, }; };