import * as React from 'react' import { SessionProvider, useSession, signIn, signOut } from 'next-auth/react' import { Session } from 'next-auth' import { AuthUser, UserRole } from './types' import { hasPermission, hasRole } from './permissions' interface AuthContextType { user: AuthUser | null isAuthenticated: boolean isLoading: boolean signIn: typeof signIn signOut: typeof signOut hasPermission: (permission: string) => boolean hasRole: (role: UserRole) => boolean updateSession: () => Promise } const AuthContext = React.createContext(undefined) interface AuthProviderProps { children: React.ReactNode session?: Session | null } function AuthProviderContent({ children }: { children: React.ReactNode }) { const { data: session, status, update } = useSession() const isLoading = status === 'loading' const isAuthenticated = status === 'authenticated' const user: AuthUser | null = session?.user ? { id: session.user.id, email: session.user.email!, name: session.user.name, image: session.user.image, role: session.user.role || UserRole.USER, emailVerified: session.user.emailVerified, } : null const checkPermission = React.useCallback( (permission: string): boolean => { if (!user) return false return hasPermission(user.role, permission) }, [user] ) const checkRole = React.useCallback( (requiredRole: UserRole): boolean => { if (!user) return false return hasRole(user.role, requiredRole) }, [user] ) const updateSession = React.useCallback(async () => { await update() }, [update]) const value: AuthContextType = { user, isAuthenticated, isLoading, signIn, signOut, hasPermission: checkPermission, hasRole: checkRole, updateSession, } return {children} } export function AuthProvider({ children, session }: AuthProviderProps) { return ( {children} ) } export function useAuth(): AuthContextType { const context = React.useContext(AuthContext) if (context === undefined) { throw new Error('useAuth must be used within an AuthProvider') } return context } // Higher-order component for components that require auth export function withAuth

( Component: React.ComponentType

, options?: { requiredRole?: UserRole; fallback?: React.ReactNode } ) { return function AuthenticatedComponent(props: P) { const { isAuthenticated, isLoading, user } = useAuth() if (isLoading) { return options?.fallback ||

Loading...
} if (!isAuthenticated) { if (typeof window !== 'undefined') { signIn() } return options?.fallback ||
Redirecting to sign in...
} if (options?.requiredRole && user) { if (!hasRole(user.role, options.requiredRole)) { return
Access denied. Insufficient permissions.
} } return } } export { AuthContext }