import { defineStore } from 'pinia' import { ref, computed } from 'vue' import { useRouter } from 'vue-router' export const useAuthStore = defineStore('auth', () => { const router = useRouter() // State const token = ref(localStorage.getItem('token') || '') const isAdmin = ref(localStorage.getItem('is_admin') === 'true') const userEmail = ref(localStorage.getItem('user_email') || '') const userRole = ref(localStorage.getItem('user_role') || '') const userProfile = ref(null) // Full user profile from /users/me // Getters const isLoggedIn = computed(() => !!token.value) const isTester = computed(() => userEmail.value === 'tester_pro@profibot.hu' || userRole.value === 'tester') const displayName = computed(() => { if (isTester.value) return 'TESTER PRO' if (isAdmin.value) return 'ADMIN' return 'USER' }) // Actions const login = async (email, password) => { console.log('AuthStore: Real API login attempt for', email) try { // Prepare URL-encoded form data for OAuth2 password grant // FastAPI's OAuth2PasswordRequestForm expects application/x-www-form-urlencoded const params = new URLSearchParams() params.append('username', email) params.append('password', password) // Call real backend API const response = await fetch('http://localhost:8000/api/v1/auth/login', { method: 'POST', body: params, headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json' } }) if (!response.ok) { const errorText = await response.text() console.error('AuthStore: Login API error', response.status, errorText) throw new Error(`Login failed: ${response.status} ${response.statusText}`) } const data = await response.json() console.log('AuthStore: Login API response', data) // Extract token and user info const accessToken = data.access_token const refreshToken = data.refresh_token const tokenType = data.token_type const isActive = data.is_active // We need to decode the JWT token to get user role and info // For now, we'll make a separate API call to get user info // Or we can parse the JWT token (simple base64 decode) let userRole = 'user' let isAdmin = false try { // Decode JWT token to get payload const tokenParts = accessToken.split('.') if (tokenParts.length === 3) { const payload = JSON.parse(atob(tokenParts[1])) userRole = payload.role || 'user' isAdmin = userRole === 'admin' || userRole === 'superadmin' console.log('AuthStore: Decoded JWT payload', payload) } } catch (decodeError) { console.warn('AuthStore: Could not decode JWT token', decodeError) // Fallback: Make API call to get user info // For now, we'll use a default role } // Save to localStorage localStorage.setItem('token', accessToken) localStorage.setItem('refresh_token', refreshToken) localStorage.setItem('is_admin', isAdmin.toString()) localStorage.setItem('user_email', email) localStorage.setItem('user_role', userRole) // Update store state token.value = accessToken isAdmin.value = isAdmin userEmail.value = email userRole.value = userRole console.log('AuthStore: State updated, redirecting to /profile-select') // Redirect to profile-select (as per router logic) try { await router.push('/profile-select') console.log('AuthStore: Redirect successful') } catch (error) { console.error('AuthStore: Router redirect failed:', error) throw error } return { success: true, token: accessToken, isAdmin, role: userRole } } catch (error) { console.error('AuthStore: Login failed', error) // Fallback to mock login for development if API is not available if (error.message.includes('Failed to fetch') || error.message.includes('NetworkError')) { console.warn('AuthStore: API unavailable, falling back to mock login for development') // Determine user role based on email let mockIsAdmin = false let mockRole = 'user' if (email === 'superadmin@profibot.hu') { mockIsAdmin = true mockRole = 'admin' } else if (email === 'tester_pro@profibot.hu') { mockIsAdmin = true // Tester has admin privileges for testing mockRole = 'tester' } // Set mock token const mockToken = 'mock_jwt_token_' + Date.now() // Save to localStorage localStorage.setItem('token', mockToken) localStorage.setItem('is_admin', mockIsAdmin.toString()) localStorage.setItem('user_email', email) localStorage.setItem('user_role', mockRole) // Update store state token.value = mockToken isAdmin.value = mockIsAdmin userEmail.value = email userRole.value = mockRole // Redirect await router.push('/profile-select') return { success: true, token: mockToken, isAdmin: mockIsAdmin, role: mockRole } } throw error } } const logout = () => { // Clear localStorage localStorage.removeItem('token') localStorage.removeItem('is_admin') localStorage.removeItem('user_email') localStorage.removeItem('user_role') localStorage.removeItem('ui_mode') // Also clear UI mode on logout // Reset store state token.value = '' isAdmin.value = false userEmail.value = '' userRole.value = '' userProfile.value = null // Redirect to login router.push('/login') } const fetchUserProfile = async () => { if (!token.value) { throw new Error('Not authenticated') } try { const response = await fetch('http://localhost:8000/api/v1/users/me', { method: 'GET', headers: { 'Authorization': `Bearer ${token.value}`, 'Accept': 'application/json' } }) if (!response.ok) { throw new Error(`Failed to fetch user profile: ${response.status} ${response.statusText}`) } const data = await response.json() console.log('AuthStore: Fetched user profile', data) // Update user profile state userProfile.value = data // Also update email and role from profile if available if (data.email && !userEmail.value) { userEmail.value = data.email localStorage.setItem('user_email', data.email) } if (data.role && !userRole.value) { userRole.value = data.role localStorage.setItem('user_role', data.role) isAdmin.value = data.role === 'admin' || data.role === 'superadmin' localStorage.setItem('is_admin', isAdmin.value.toString()) } return data } catch (err) { console.error('AuthStore: Error fetching user profile', err) throw err } } const checkAuth = () => { // Sync with localStorage on page load const storedToken = localStorage.getItem('token') || '' const storedEmail = localStorage.getItem('user_email') || '' const storedRole = localStorage.getItem('user_role') || '' // Try to decode JWT token to get role if not stored let decodedRole = storedRole let decodedIsAdmin = storedRole === 'admin' || storedRole === 'superadmin' if (storedToken && !storedRole) { try { // Decode JWT token to get payload const tokenParts = storedToken.split('.') if (tokenParts.length === 3) { const payload = JSON.parse(atob(tokenParts[1])) decodedRole = payload.role || 'user' decodedIsAdmin = decodedRole === 'admin' || decodedRole === 'superadmin' console.log('AuthStore: Decoded JWT on checkAuth', payload) // Update localStorage with decoded role localStorage.setItem('user_role', decodedRole) localStorage.setItem('is_admin', decodedIsAdmin.toString()) } } catch (decodeError) { console.warn('AuthStore: Could not decode JWT token on checkAuth', decodeError) } } else if (storedToken && storedRole) { // Use stored role decodedIsAdmin = storedRole === 'admin' || storedRole === 'superadmin' } token.value = storedToken isAdmin.value = decodedIsAdmin userEmail.value = storedEmail userRole.value = decodedRole || 'user' } // Initialize on store creation checkAuth() return { // State token, isAdmin, userEmail, userRole, userProfile, // Getters isLoggedIn, isTester, displayName, // Actions login, logout, checkAuth, fetchUserProfile } })