deepsite / hooks /useUser.ts
enzostvs's picture
enzostvs HF Staff
login through iframe
e4d51c2
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useCookie } from "react-use";
import { useRouter } from "next/navigation";
import { ProjectType, User } from "@/types";
import { api } from "@/lib/api";
import { toast } from "sonner";
import MY_TOKEN_KEY from "@/lib/get-cookie-name";
import { useBroadcastChannel } from "@/lib/useBroadcastChannel";
export const useUser = (initialData?: {
user: User | null;
errCode: number | null;
projects: ProjectType[];
}) => {
const client = useQueryClient();
const router = useRouter();
const [, setCurrentRoute, removeCurrentRoute] = useCookie("deepsite-currentRoute");
const [token, setToken, removeToken] = useCookie(MY_TOKEN_KEY());
const { data: { user, errCode } = { user: null, errCode: null }, isLoading, refetch: refetchMe } =
useQuery({
queryKey: ["user.me"],
queryFn: async () => {
const me = await api.get("/me");
if (me.data) {
if (me.data.projects) {
setProjects(me.data.projects);
}
return { user: me.data.user, errCode: me.data.errCode };
}
return { user: null, errCode: null };
},
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
retry: false,
enabled: true,
});
const { data: loadingAuth } = useQuery({
queryKey: ["loadingAuth"],
queryFn: async () => false,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
});
const setLoadingAuth = (value: boolean) => {
client.setQueryData(["setLoadingAuth"], value);
};
const { data: projects } = useQuery({
queryKey: ["me.projects"],
queryFn: async () => [],
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
initialData: initialData?.projects || [],
});
const setProjects = (projects: ProjectType[]) => {
client.setQueryData(["me.projects"], projects);
};
// Listen for OAuth callback from popup window
useBroadcastChannel("auth", (message: any) => {
if (message.type === "user-oauth" && message.code) {
loginFromCode(message.code);
}
});
const isInIframe = () => {
try {
return window.self !== window.top;
} catch {
return true;
}
};
const openLoginWindow = async () => {
setCurrentRoute(window.location.pathname);
// If in iframe, open OAuth in popup window
if (isInIframe()) {
try {
const response = await api.get("/auth/login-url");
const loginUrl = response.data?.loginUrl;
if (loginUrl) {
const width = 600;
const height = 700;
const left = (window.screen.width - width) / 2;
const top = (window.screen.height - height) / 2;
window.open(
loginUrl,
"HuggingFace Login",
`width=${width},height=${height},left=${left},top=${top},popup=yes`
);
return;
}
} catch (error) {
console.error("Failed to open login popup:", error);
toast.error("Failed to open login window");
}
}
// Default: navigate to auth page (for non-iframe contexts)
return router.push("/auth");
};
const loginFromCode = async (code: string) => {
setLoadingAuth(true);
if (loadingAuth) return;
await api
.post("/auth", { code })
.then(async (res: any) => {
if (res.data && res.data.access_token) {
const expiresIn = res.data.expires_in || 3600;
const expiresDate = new Date();
expiresDate.setTime(expiresDate.getTime() + expiresIn * 1000);
const isProduction = window.location.protocol === 'https:';
const cookieOptions: any = {
expires: expiresDate,
path: '/',
sameSite: isProduction ? 'none' : 'lax',
};
if (isProduction) {
cookieOptions.secure = true;
}
setToken(res.data.access_token, cookieOptions);
const cookieString = `${MY_TOKEN_KEY()}=${res.data.access_token}; path=/; max-age=${expiresIn}; samesite=${isProduction ? 'none' : 'lax'}${cookieOptions.secure ? '; secure' : ''}`;
document.cookie = cookieString;
refetchMe();
router.push("/")
toast.success("Login successful");
}
})
.catch((err: any) => {
toast.error(err?.data?.message ?? err.message ?? "An error occurred");
})
.finally(() => {
setLoadingAuth(false);
});
};
const logout = async () => {
removeToken();
removeCurrentRoute();
toast.success("Logout successful");
client.clear();
window.location.reload();
};
return {
user,
projects,
setProjects,
errCode,
loading: isLoading || loadingAuth,
openLoginWindow,
loginFromCode,
token,
logout,
};
};