This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

semble / src / webapp / hooks / useAuth.tsx
3.1 kB 102 lines
1'use client'; 2 3import { createContext, useContext, ReactNode, useEffect } from 'react'; 4import { useQuery, useQueryClient } from '@tanstack/react-query'; 5import { useRouter } from 'next/navigation'; 6import type { GetProfileResponse } from '@/api-client/ApiClient'; 7import { ClientCookieAuthService } from '@/services/auth/CookieAuthService.client'; 8import { verifySessionOnClient } from '@/lib/auth/dal'; 9import { usePathname } from 'next/navigation'; 10import posthog from 'posthog-js'; 11import { isInternalUser, isEarlyTester } from '@/lib/userLists'; 12import { shouldCaptureAnalytics } from '@/features/analytics/utils'; 13 14const ENABLE_AUTH_LOGGING = true; 15 16interface AuthContextType { 17 user: GetProfileResponse | null; 18 isAuthenticated: boolean; 19 isLoading: boolean; 20 refreshAuth: () => Promise<void>; 21 logout: () => Promise<void>; 22} 23 24const AuthContext = createContext<AuthContextType | undefined>(undefined); 25 26export const AuthProvider = ({ children }: { children: ReactNode }) => { 27 const router = useRouter(); 28 const queryClient = useQueryClient(); 29 const pathname = usePathname(); // to prevent redirecting to login on landing page 30 31 const refreshAuth = async () => { 32 await query.refetch(); 33 }; 34 35 const logout = async () => { 36 if (ENABLE_AUTH_LOGGING) { 37 console.log('[useAuth] Initiating logout process'); 38 } 39 40 // Reset PostHog user identity 41 if (shouldCaptureAnalytics()) { 42 posthog.reset(); 43 if (ENABLE_AUTH_LOGGING) { 44 console.log('[useAuth] PostHog user identity reset'); 45 } 46 } 47 48 await ClientCookieAuthService.clearTokens(); 49 queryClient.clear(); 50 router.push('/login'); 51 }; 52 53 const query = useQuery<GetProfileResponse | null>({ 54 queryKey: ['authenticated user'], 55 queryFn: async () => { 56 const session = await verifySessionOnClient(); 57 return session; 58 }, 59 staleTime: 5 * 60 * 1000, // cache for 5 minutes 60 refetchOnWindowFocus: false, 61 retry: false, 62 }); 63 64 useEffect(() => { 65 // Handle other auth errors 66 if (query.isError && !query.isLoading && pathname !== '/') logout(); 67 }, [query.data, query.isError, query.isLoading, pathname, router, logout]); 68 69 // Set super properties for anonymous tracking (no PII) 70 useEffect(() => { 71 const user = query.data; 72 73 // Set super properties when analytics is enabled and user is available 74 // These properties are included in all events automatically 75 if (shouldCaptureAnalytics() && user) { 76 posthog.register({ 77 is_internal: isInternalUser(user.handle), 78 is_early_tester: isEarlyTester(user.handle), 79 }); 80 } 81 }, [query.data]); 82 83 const contextValue: AuthContextType = { 84 user: query.data ?? null, 85 isAuthenticated: !!query.data, 86 isLoading: query.isLoading, 87 refreshAuth, 88 logout, 89 }; 90 91 return ( 92 <AuthContext.Provider value={contextValue}>{children}</AuthContext.Provider> 93 ); 94}; 95 96export const useAuth = (): AuthContextType => { 97 const context = useContext(AuthContext); 98 if (!context) { 99 throw new Error('useAuth must be used within an AuthProvider'); 100 } 101 return context; 102};