'use client'; import { useEffect, useState, createContext, useContext } from 'react'; import { getAccessTokenFromStorage, authApi, setAccessToken, setRefreshToken, clearAuthTokens, type MeResponse } from './api'; import { productId } from './product-config'; import { useRouter, usePathname } from 'next/navigation'; interface User { id: string; email: string; role: string; plan: string; displayName: string; products?: Array<{ productId: string; plan: string; role: string; }>; } interface AuthContextType { user: User | null; loading: boolean; login: (email: string, password: string, productId: string) => Promise; logout: () => void; isAdmin: boolean; } const AuthContext = createContext(undefined); export function useAuth() { const context = useContext(AuthContext); if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider'); } return context; } export function AuthProvider({ children }: { children: React.ReactNode }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [isAdmin, setIsAdmin] = useState(false); const router = useRouter(); const pathname = usePathname(); const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); // Skip auth check for login page if (pathname === '/login') { setLoading(false); return; } checkAuth(); }, [pathname]); useEffect(() => { // Skip redirect for login page if (pathname === '/login') { return; } if (!loading && mounted && !user) { router.push('/login'); } }, [loading, mounted, user, router, pathname]); // If on login page, render children without auth context if (pathname === '/login') { return <>{children}; } async function checkAuth() { try { const token = getAccessTokenFromStorage(); if (!token) { console.log('No token found in storage'); setLoading(false); return; } console.log('Checking auth with token...'); // Add timeout to prevent hanging const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('Auth check timeout')), 10000) ); const userData = await Promise.race([ authApi.me(token), timeoutPromise ]) as MeResponse; console.log('User data received:', userData); setUser(userData); // Simplified admin check - just check global admin role const globalRole = userData.role; const hasAdminAccess = globalRole === 'admin'; setIsAdmin(hasAdminAccess); console.log('Admin access:', hasAdminAccess); } catch (error) { console.error('Auth check failed:', error); clearAuthTokens(); } finally { setLoading(false); } } async function login(email: string, password: string, productId: string) { try { console.log('Attempting login for:', email, 'with productId:', productId); const response = await authApi.login({ email, password, productId }); console.log('Login response received:', response); setAccessToken(response.accessToken); setRefreshToken(response.refreshToken); setUser(response.user); // Check if user has admin access (global admin role) const hasAdminAccess = response.user.role === 'admin'; setIsAdmin(hasAdminAccess); console.log('Login successful, admin access:', hasAdminAccess); } catch (error) { console.error('Login failed:', error); throw error; } } function logout() { clearAuthTokens(); setUser(null); setIsAdmin(false); router.push('/'); } // Prevent hydration mismatch by not rendering until mounted if (!mounted) { return
Loading...
; } if (loading) { return
Loading...
; } if (!user) { return
Redirecting to login...
; } if (user && !isAdmin) { return (

Access Denied

You need admin privileges to access the DevOps dashboard.

Your role: {user.role}

); } return ( {children} ); }