Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
| import { getLoginUrl } from "@/const"; | |
| import { trpc } from "@/lib/trpc"; | |
| import { TRPCClientError } from "@trpc/client"; | |
| import { useCallback, useEffect, useMemo } from "react"; | |
| const ACCESS_KEY_STORAGE = "access_key_verified"; | |
| // Mock user for access key authentication (no cookies needed) | |
| // ID must match DEMO_USER_ID in importTestSamples.ts | |
| const ACCESS_KEY_USER = { | |
| id: 1, | |
| name: "Demo User", | |
| email: "demo@aimusic.attribution", | |
| }; | |
| type UseAuthOptions = { | |
| redirectOnUnauthenticated?: boolean; | |
| redirectPath?: string; | |
| }; | |
| export function useAuth(options?: UseAuthOptions) { | |
| const { redirectOnUnauthenticated = false, redirectPath = getLoginUrl() } = | |
| options ?? {}; | |
| const utils = trpc.useUtils(); | |
| // Check if access key is verified (works in Safari iframe, no cookies needed) | |
| const accessKeyVerified = typeof window !== "undefined" && | |
| sessionStorage.getItem(ACCESS_KEY_STORAGE) === "true"; | |
| const meQuery = trpc.auth.me.useQuery(undefined, { | |
| retry: false, | |
| refetchOnWindowFocus: false, | |
| // Skip query if access key is verified - we don't need cookie auth | |
| enabled: !accessKeyVerified, | |
| }); | |
| const logoutMutation = trpc.auth.logout.useMutation({ | |
| onSuccess: () => { | |
| utils.auth.me.setData(undefined, null); | |
| }, | |
| }); | |
| const logout = useCallback(async () => { | |
| try { | |
| await logoutMutation.mutateAsync(); | |
| } catch (error: unknown) { | |
| if ( | |
| error instanceof TRPCClientError && | |
| error.data?.code === "UNAUTHORIZED" | |
| ) { | |
| return; | |
| } | |
| throw error; | |
| } finally { | |
| // Also clear access key on logout | |
| sessionStorage.removeItem(ACCESS_KEY_STORAGE); | |
| utils.auth.me.setData(undefined, null); | |
| await utils.auth.me.invalidate(); | |
| } | |
| }, [logoutMutation, utils]); | |
| const state = useMemo(() => { | |
| // If access key is verified, use mock user (no cookies needed - Safari iframe fix) | |
| const effectiveUser = accessKeyVerified ? ACCESS_KEY_USER : meQuery.data; | |
| localStorage.setItem( | |
| "manus-runtime-user-info", | |
| JSON.stringify(effectiveUser) | |
| ); | |
| return { | |
| user: effectiveUser ?? null, | |
| loading: !accessKeyVerified && (meQuery.isLoading || logoutMutation.isPending), | |
| error: meQuery.error ?? logoutMutation.error ?? null, | |
| isAuthenticated: Boolean(effectiveUser), | |
| }; | |
| }, [ | |
| accessKeyVerified, | |
| meQuery.data, | |
| meQuery.error, | |
| meQuery.isLoading, | |
| logoutMutation.error, | |
| logoutMutation.isPending, | |
| ]); | |
| useEffect(() => { | |
| if (!redirectOnUnauthenticated) return; | |
| if (meQuery.isLoading || logoutMutation.isPending) return; | |
| if (state.user) return; | |
| if (typeof window === "undefined") return; | |
| if (window.location.pathname === redirectPath) return; | |
| window.location.href = redirectPath | |
| }, [ | |
| redirectOnUnauthenticated, | |
| redirectPath, | |
| logoutMutation.isPending, | |
| meQuery.isLoading, | |
| state.user, | |
| ]); | |
| return { | |
| ...state, | |
| refresh: () => meQuery.refetch(), | |
| logout, | |
| }; | |
| } | |