File size: 5,075 Bytes
c10f8f8
 
 
 
 
 
ddb7f1c
c10f8f8
 
569d96f
e4d51c2
c10f8f8
 
 
 
 
ddb7f1c
c10f8f8
 
 
569d96f
56f47b1
c10f8f8
56f47b1
c10f8f8
 
 
56f47b1
 
 
 
 
 
 
 
c10f8f8
 
 
 
 
56f47b1
c10f8f8
 
 
 
 
 
 
 
 
 
 
 
 
ddb7f1c
 
 
 
 
 
 
 
 
 
 
 
e4d51c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c10f8f8
 
e4d51c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c10f8f8
 
 
 
 
 
 
 
 
f1dc792
 
 
 
 
71fcc87
 
1cb3dcc
f1dc792
c565924
71fcc87
1cb3dcc
 
71fcc87
1cb3dcc
 
 
 
 
71fcc87
1cb3dcc
f1dc792
56f47b1
 
c10f8f8
 
 
 
 
 
 
 
 
 
 
 
92d95b7
 
 
 
 
c10f8f8
 
 
 
ddb7f1c
 
c10f8f8
 
 
 
768bffa
c10f8f8
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/* 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,
  };
};