jbilcke-hf HF staff commited on
Commit
16891a6
1 Parent(s): 0fcac01

work on HF login

Browse files
src/app/interface/hf-login/index.tsx CHANGED
@@ -2,21 +2,15 @@
2
 
3
  import { useCurrentUser } from "@/app/state/userCurrentUser"
4
  import { Button } from "@/components/ui/button"
5
- import { useHuggingFaceLogin } from "@/lib/useHuggingFaceLogin"
6
 
7
  export function HuggingFaceLogin() {
8
 
9
- const user = useCurrentUser()
10
- const hf = useHuggingFaceLogin()
11
 
12
  // feature is not finished yet
13
  if (!user?.userName || user?.userName !== "jbilcke-hf") { return }
14
 
15
- console.log("user:", user)
16
- console.log("hf.isLoggedIn:", hf.isLoggedIn)
17
- console.log("hf.oauthResult:", hf.oauthResult)
18
-
19
  return (
20
- <div><Button onClick={hf.login}>test</Button></div>
21
  )
22
  }
 
2
 
3
  import { useCurrentUser } from "@/app/state/userCurrentUser"
4
  import { Button } from "@/components/ui/button"
 
5
 
6
  export function HuggingFaceLogin() {
7
 
8
+ const { user, login } = useCurrentUser()
 
9
 
10
  // feature is not finished yet
11
  if (!user?.userName || user?.userName !== "jbilcke-hf") { return }
12
 
 
 
 
 
13
  return (
14
+ <div><Button onClick={login}>Sign in with Hugging Face</Button></div>
15
  )
16
  }
src/app/main.tsx CHANGED
@@ -16,8 +16,6 @@ import { PublicMusicVideosView } from "./views/public-music-videos-view"
16
  import { getCollectionKey } from "@/lib/getCollectionKey"
17
  import { PublicVideoEmbedView } from "./views/public-video-embed-view"
18
 
19
- import { HuggingFaceLogin } from "./interface/hf-login"
20
-
21
  // this is where we transition from the server-side space
22
  // and the client-side space
23
  // basically, all the views are generated in client-side space
@@ -140,7 +138,6 @@ export function Main({
140
  const view = useStore(s => s.view)
141
  return (
142
  <TubeLayout>
143
- <HuggingFaceLogin />
144
  {view === "home" && <HomeView />}
145
  {view === "public_video_embed" && <PublicVideoEmbedView />}
146
  {view === "public_video" && <PublicVideoView />}
 
16
  import { getCollectionKey } from "@/lib/getCollectionKey"
17
  import { PublicVideoEmbedView } from "./views/public-video-embed-view"
18
 
 
 
19
  // this is where we transition from the server-side space
20
  // and the client-side space
21
  // basically, all the views are generated in client-side space
 
138
  const view = useStore(s => s.view)
139
  return (
140
  <TubeLayout>
 
141
  {view === "home" && <HomeView />}
142
  {view === "public_video_embed" && <PublicVideoEmbedView />}
143
  {view === "public_video" && <PublicVideoView />}
src/app/state/defaultSettings.ts CHANGED
@@ -2,4 +2,5 @@ import { Settings } from "@/types/general"
2
 
3
  export const defaultSettings: Settings = {
4
  huggingfaceApiKey: "",
 
5
  }
 
2
 
3
  export const defaultSettings: Settings = {
4
  huggingfaceApiKey: "",
5
+ huggingfaceTemporaryApiKey: "",
6
  }
src/app/state/localStorageKeys.ts CHANGED
@@ -3,4 +3,5 @@ import { Settings } from "@/types/general"
3
  export const localStorageKeys: Record<keyof Settings, string> = {
4
  // important: prefix with AI_TUBE to avoid collisions when running the app on localhost
5
  huggingfaceApiKey: "AI_TUBE_CONF_AUTH_HF_API_TOKEN",
 
6
  }
 
3
  export const localStorageKeys: Record<keyof Settings, string> = {
4
  // important: prefix with AI_TUBE to avoid collisions when running the app on localhost
5
  huggingfaceApiKey: "AI_TUBE_CONF_AUTH_HF_API_TOKEN",
6
+ huggingfaceTemporaryApiKey: "AI_TUBE_CONF_AUTH_TEMPORARY_HF_API_TOKEN"
7
  }
src/app/state/userCurrentUser.ts CHANGED
@@ -1,48 +1,213 @@
1
- import { useEffect, useTransition } from "react"
 
 
 
2
 
3
  import { UserInfo } from "@/types/general"
4
 
5
  import { useStore } from "./useStore"
6
- import { useLocalStorage } from "usehooks-ts"
7
  import { localStorageKeys } from "./localStorageKeys"
8
  import { defaultSettings } from "./defaultSettings"
9
  import { getCurrentUser } from "../server/actions/users"
10
 
11
- export function useCurrentUser(): UserInfo | undefined {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  const [_pending, startTransition] = useTransition()
13
 
14
- const currentUser = useStore(s => s.currentUser)
15
  const setCurrentUser = useStore(s => s.setCurrentUser)
 
 
 
16
 
17
- const [huggingfaceApiKey] = useLocalStorage<string>(
 
 
18
  localStorageKeys.huggingfaceApiKey,
19
  defaultSettings.huggingfaceApiKey
20
  )
21
- useEffect(() => {
22
- startTransition(async () => {
23
 
24
- // no key
25
- if (!huggingfaceApiKey) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  setCurrentUser(undefined)
27
- return
28
  }
 
29
 
30
- // already logged-in
31
- if (currentUser?.id) {
32
- return
33
- }
34
  try {
35
 
36
  const user = await getCurrentUser(huggingfaceApiKey)
37
 
38
  setCurrentUser(user)
 
 
39
  } catch (err) {
40
- console.error("failed to log in:", err)
41
  setCurrentUser(undefined)
42
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  })
44
-
45
- }, [huggingfaceApiKey, currentUser?.id])
46
 
47
- return currentUser
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
 
1
+ import { useEffect, useState, useTransition } from "react"
2
+ import { OAuthResult, oauthHandleRedirectIfPresent, oauthLoginUrl } from "@huggingface/hub"
3
+
4
+ import { useLocalStorage } from "usehooks-ts"
5
 
6
  import { UserInfo } from "@/types/general"
7
 
8
  import { useStore } from "./useStore"
9
+
10
  import { localStorageKeys } from "./localStorageKeys"
11
  import { defaultSettings } from "./defaultSettings"
12
  import { getCurrentUser } from "../server/actions/users"
13
 
14
+ export function useCurrentUser({
15
+ isLoginRequired = false
16
+ }: {
17
+ // set this to true, and the page will automatically redirect to the
18
+ // HF login page if the session is expired
19
+ isLoginRequired?: boolean
20
+ } = {}): {
21
+ user?: UserInfo
22
+ login: () => void
23
+ checkSession: (isLoginRequired: boolean) => Promise<UserInfo | undefined>
24
+ apiKey: string
25
+ oauthResult?: OAuthResult
26
+
27
+ // the long standing API is a temporary solution for "PRO" users of AI Tube
28
+ // (users who use Clap files using external tools,
29
+ // or want ot use their own HF account to generate videos)
30
+ longStandingApiKey: string
31
+ setLongStandingApiKey: (apiKey: string, loginOnFailure: boolean) => void
32
+ } {
33
  const [_pending, startTransition] = useTransition()
34
 
35
+ const user = useStore(s => s.currentUser)
36
  const setCurrentUser = useStore(s => s.setCurrentUser)
37
+ const [oauthResult, setOauthResult] = useState<OAuthResult>()
38
+
39
+ const userId = `${user?.id || ""}`
40
 
41
+ // this is the legacy, long-standing API key
42
+ // which is still required for long generation of Clap files
43
+ const [huggingfaceApiKey, setHuggingfaceApiKey] = useLocalStorage<string>(
44
  localStorageKeys.huggingfaceApiKey,
45
  defaultSettings.huggingfaceApiKey
46
  )
 
 
47
 
48
+ // this is the new recommended API to use, with short expiration rates
49
+ // in the future this API key will be enough for all our use cases
50
+ const [huggingfaceTemporaryApiKey, setHuggingfaceTemporaryApiKey] = useLocalStorage<string>(
51
+ localStorageKeys.huggingfaceTemporaryApiKey,
52
+ defaultSettings.huggingfaceTemporaryApiKey
53
+ )
54
+
55
+ // force the API call
56
+ const checkSession = async (isLoginRequired: boolean = false): Promise<UserInfo | undefined> => {
57
+
58
+ console.log("useCurrentUser.checkSession()")
59
+ // new way: try to use the safer temporary key whenever possible
60
+ if (huggingfaceTemporaryApiKey) {
61
+ try {
62
+
63
+ const user = await getCurrentUser(huggingfaceTemporaryApiKey)
64
+
65
+ setCurrentUser(user)
66
+
67
+ return user // we stop there, no need to try the legacy key
68
+
69
+ } catch (err) {
70
+ console.error("failed to log in using the temporary key:", err)
71
  setCurrentUser(undefined)
 
72
  }
73
+ }
74
 
75
+ // deprecated: the old static key which is harder to renew
76
+ if (huggingfaceApiKey) {
 
 
77
  try {
78
 
79
  const user = await getCurrentUser(huggingfaceApiKey)
80
 
81
  setCurrentUser(user)
82
+
83
+ return user
84
  } catch (err) {
85
+ console.error("failed to log in using the static key:", err)
86
  setCurrentUser(undefined)
87
  }
88
+ }
89
+
90
+ // when we reach this stage, we know that none of the API tokens were valid
91
+ // we are given the choice to request a login or not
92
+ // (depending on if it's a secret page or not)
93
+
94
+ if (isLoginRequired) {
95
+ await login()
96
+ }
97
+
98
+ return undefined
99
+ }
100
+
101
+ // can be called many times, but won't do the API call if not necessary
102
+ const main = async (isLoginRequired: boolean) => {
103
+
104
+ console.log("useCurrentUser()")
105
+
106
+ try {
107
+ const res = await oauthHandleRedirectIfPresent()
108
+ if (res) {
109
+ console.log("useCurrentUser(): we just received an oauth login!")
110
+ setOauthResult(res)
111
+ setHuggingfaceTemporaryApiKey(res.accessToken)
112
+ await checkSession(isLoginRequired)
113
+ return
114
+ }
115
+ } catch (err) {
116
+ }
117
+
118
+ // already logged-in, no need to spend an API call
119
+ // although it is worth noting that the API token might be expired at this stage
120
+ if (userId) {
121
+ return
122
+ }
123
+
124
+ console.log("useCurrentUser(): yes, we need to call synchronizeSession()")
125
+ await checkSession(isLoginRequired)
126
+ }
127
+
128
+ useEffect(() => {
129
+ startTransition(async () => { await main(isLoginRequired) })
130
+ }, [isLoginRequired, huggingfaceApiKey, huggingfaceTemporaryApiKey, userId])
131
+
132
+
133
+ const login = async () => {
134
+ const oauthUrl = await oauthLoginUrl({
135
+ /**
136
+ * OAuth client ID.
137
+ *
138
+ * For static Spaces, you can omit this and it will be loaded from the Space config, as long as `hf_oauth: true` is present in the README.md's metadata.
139
+ * For other Spaces, it is available to the backend in the OAUTH_CLIENT_ID environment variable, as long as `hf_oauth: true` is present in the README.md's metadata.
140
+ *
141
+ * You can also create a Developer Application at https://huggingface.co/settings/connected-applications and use its client ID.
142
+ */
143
+ clientId: process.env.NEXT_PUBLIC_AI_TUBE_OAUTH_CLIENT_ID,
144
+
145
+ // hubUrl?: string;
146
+
147
+ /**
148
+ * OAuth scope, a list of space separate scopes.
149
+ *
150
+ * For static Spaces, you can omit this and it will be loaded from the Space config, as long as `hf_oauth: true` is present in the README.md's metadata.
151
+ * For other Spaces, it is available to the backend in the OAUTH_SCOPES environment variable, as long as `hf_oauth: true` is present in the README.md's metadata.
152
+ *
153
+ * Defaults to "openid profile".
154
+ *
155
+ * You can also create a Developer Application at https://huggingface.co/settings/connected-applications and use its scopes.
156
+ *
157
+ * See https://huggingface.co/docs/hub/oauth for a list of available scopes.
158
+ */
159
+ scopes: "openid profile",
160
+
161
+ /**
162
+ * Redirect URI, defaults to the current URL.
163
+ *
164
+ * For Spaces, any URL within the Space is allowed.
165
+ *
166
+ * For Developer Applications, you can add any URL you want to the list of allowed redirect URIs at https://huggingface.co/settings/connected-applications.
167
+ */
168
+ redirectUrl: "https://jbilcke-hf-ai-tube.hf.space",
169
+
170
+ /**
171
+ * State to pass to the OAuth provider, which will be returned in the call to `oauthLogin` after the redirect.
172
+ */
173
+ // state: ""
174
  })
 
 
175
 
176
+ window.location.href = oauthUrl
177
+ }
178
+
179
+ const setLongStandingApiKey = (apiKey: string, loginOnFailure: boolean) => {
180
+ (async () => {
181
+ try {
182
+ const user = await getCurrentUser(apiKey)
183
+ setHuggingfaceApiKey(apiKey)
184
+ setCurrentUser(user)
185
+ } catch (err) {
186
+ console.error("failed to log in using the long standing key:", err)
187
+ setHuggingfaceApiKey("")
188
+ setCurrentUser(undefined)
189
+ if (loginOnFailure) {
190
+ login()
191
+ }
192
+ }
193
+ })()
194
+ }
195
+
196
+ // this may correspond to either a short or a long standing api key
197
+ // in the future it may always be a short api key with auto renewal
198
+ const apiKey = user?.hfApiToken || ""
199
+
200
+
201
+ // for now, we still need to keep track of a logn api, but this is purely optional
202
+ const longStandingApiKey = huggingfaceApiKey
203
+
204
+ return {
205
+ user,
206
+ login,
207
+ checkSession,
208
+ oauthResult,
209
+ apiKey,
210
+ longStandingApiKey,
211
+ setLongStandingApiKey,
212
+ }
213
  }
src/app/views/public-video-view/index.tsx CHANGED
@@ -43,14 +43,14 @@ export function PublicVideoView() {
43
  // EDIT: you know what, let's do this the dirty way for now
44
  // const [desiredCurrentTime, setDesiredCurrentTime] = useState()
45
 
46
- const currentUser = useCurrentUser()
47
 
48
  const [userThumbnail, setUserThumbnail] = useState("")
49
 
50
  useEffect(() => {
51
- setUserThumbnail(currentUser?.thumbnail || "")
52
 
53
- }, [currentUser?.thumbnail])
54
 
55
  const handleBadUserThumbnail = () => {
56
  if (userThumbnail) {
@@ -388,7 +388,7 @@ export function PublicVideoView() {
388
  </div>
389
 
390
  {/* COMMENT INPUT BLOCK - HORIZONTAL */}
391
- {currentUser && <div className="flex flex-row w-full">
392
 
393
  {/* AVATAR */}
394
  <div
@@ -403,7 +403,7 @@ export function PublicVideoView() {
403
  />
404
  </div>
405
  : <DefaultAvatar
406
- username={currentUser?.userName}
407
  bgColor="#fde047"
408
  textColor="#1c1917"
409
  width={36}
 
43
  // EDIT: you know what, let's do this the dirty way for now
44
  // const [desiredCurrentTime, setDesiredCurrentTime] = useState()
45
 
46
+ const { user } = useCurrentUser()
47
 
48
  const [userThumbnail, setUserThumbnail] = useState("")
49
 
50
  useEffect(() => {
51
+ setUserThumbnail(user?.thumbnail || "")
52
 
53
+ }, [user?.thumbnail])
54
 
55
  const handleBadUserThumbnail = () => {
56
  if (userThumbnail) {
 
388
  </div>
389
 
390
  {/* COMMENT INPUT BLOCK - HORIZONTAL */}
391
+ {user && <div className="flex flex-row w-full">
392
 
393
  {/* AVATAR */}
394
  <div
 
403
  />
404
  </div>
405
  : <DefaultAvatar
406
+ username={user?.userName}
407
  bgColor="#fde047"
408
  textColor="#1c1917"
409
  width={36}
src/app/views/user-account-view/index.tsx CHANGED
@@ -1,23 +1,20 @@
1
  "use client"
2
 
3
  import { useEffect, useState, useTransition } from "react"
4
- import { useLocalStorage } from "usehooks-ts"
5
 
6
  import { useStore } from "@/app/state/useStore"
7
  import { cn } from "@/lib/utils"
8
  import { ChannelList } from "@/app/interface/channel-list"
9
- import { localStorageKeys } from "@/app/state/localStorageKeys"
10
- import { defaultSettings } from "@/app/state/defaultSettings"
11
- import { Input } from "@/components/ui/input"
12
 
13
  import { getPrivateChannels } from "@/app/server/actions/ai-tube-hf/getPrivateChannels"
 
 
 
14
 
15
  export function UserAccountView() {
16
  const [_isPending, startTransition] = useTransition()
17
- const [huggingfaceApiKey, setHuggingfaceApiKey] = useLocalStorage<string>(
18
- localStorageKeys.huggingfaceApiKey,
19
- defaultSettings.huggingfaceApiKey
20
- )
21
  const setView = useStore(s => s.setView)
22
  const userChannel = useStore(s => s.userChannel)
23
  const setUserChannel = useStore(s => s.setUserChannel)
@@ -28,10 +25,10 @@ export function UserAccountView() {
28
 
29
  useEffect(() => {
30
  startTransition(async () => {
31
- if (!isLoaded && huggingfaceApiKey) {
32
  try {
33
  const newUserChannels = await getPrivateChannels({
34
- apiKey: huggingfaceApiKey,
35
  renewCache: true,
36
  })
37
  setUserChannels(newUserChannels)
@@ -43,36 +40,32 @@ export function UserAccountView() {
43
  }
44
  }
45
  })
46
- }, [isLoaded, huggingfaceApiKey, userChannels.map(c => c.id).join(","), setUserChannels, setLoaded])
47
-
48
  return (
49
  <div className={cn(`flex flex-col space-y-4`)}>
50
- <h2 className="text-3xl font-bold">Want your own channels? Setup your account!</h2>
51
-
52
- <div className="flex flex-col space-y-4 max-w-2xl">
53
- <div className="flex flex-row space-x-2 items-center">
54
- <label className="flex w-64">Hugging Face token:</label>
55
- <Input
56
- placeholder="Hugging Face token (with WRITE access)"
57
- type="password"
58
- className="font-mono"
59
- onChange={(x) => {
60
- setHuggingfaceApiKey(x.target.value)
61
- }}
62
- value={huggingfaceApiKey}
63
- />
64
- </div>
65
- <p className="text-neutral-100/70">
66
- Note: your Hugging Face token must be a <span className="font-bold font-mono text-yellow-300">WRITE</span> access token.
67
- </p>
68
- {huggingfaceApiKey
69
- ? <p className="">Nice, looks like you are ready to go!</p>
70
- : <p>Please setup your account (see above) to get started</p>}
71
- </div>
72
 
73
- {huggingfaceApiKey ?
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
  <div className="flex flex-col space-y-4">
75
- <h2 className="text-3xl font-bold">Your custom channels:</h2>
 
 
76
  {userChannels?.length ? <ChannelList
77
  layout="grid"
78
  channels={[
@@ -88,9 +81,8 @@ export function UserAccountView() {
88
  setView("user_channel")
89
  }}
90
  />
91
- : isLoaded ? <p>You don&apos;t seem to have any channel yet. See @flngr on X to learn more about how to do this!</p> : <p>Loading channels..</p>}
92
- </div> : null}
93
-
94
  </div>
95
  )
96
  }
 
1
  "use client"
2
 
3
  import { useEffect, useState, useTransition } from "react"
 
4
 
5
  import { useStore } from "@/app/state/useStore"
6
  import { cn } from "@/lib/utils"
7
  import { ChannelList } from "@/app/interface/channel-list"
 
 
 
8
 
9
  import { getPrivateChannels } from "@/app/server/actions/ai-tube-hf/getPrivateChannels"
10
+ import { useCurrentUser } from "@/app/state/userCurrentUser"
11
+ import { Button } from "@/components/ui/button"
12
+ import { Input } from "@/components/ui/input"
13
 
14
  export function UserAccountView() {
15
  const [_isPending, startTransition] = useTransition()
16
+
17
+ const { user, login, apiKey, longStandingApiKey, setLongStandingApiKey } = useCurrentUser({ isLoginRequired: true })
 
 
18
  const setView = useStore(s => s.setView)
19
  const userChannel = useStore(s => s.userChannel)
20
  const setUserChannel = useStore(s => s.setUserChannel)
 
25
 
26
  useEffect(() => {
27
  startTransition(async () => {
28
+ if (!isLoaded && apiKey) {
29
  try {
30
  const newUserChannels = await getPrivateChannels({
31
+ apiKey,
32
  renewCache: true,
33
  })
34
  setUserChannels(newUserChannels)
 
40
  }
41
  }
42
  })
43
+ }, [isLoaded, apiKey, userChannels.map(c => c.id).join(","), setUserChannels, setLoaded])
44
+
45
  return (
46
  <div className={cn(`flex flex-col space-y-4`)}>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
+ {
49
+ // this is a beta feature, only necessary for users who use Clap files
50
+ user?.userName.startsWith("jbilcke")
51
+ ? <div className="flex flex-row space-x-2 items-center">
52
+ <label className="flex w-64">Save videos to my HF account</label>
53
+ <Input
54
+ placeholder="Hugging Face token (with WRITE access)"
55
+ type="password"
56
+ className="font-mono"
57
+ onChange={(x) => {
58
+ setLongStandingApiKey(x.target.value, false)
59
+ }}
60
+ value={longStandingApiKey}
61
+ />
62
+ </div> : null}
63
+
64
+ {apiKey ?
65
  <div className="flex flex-col space-y-4">
66
+ <h2 className="text-3xl font-bold">@{user?.userName} channels</h2>
67
+ <p>Don&apos;t see your channel? try to <Button onClick={login}>synchronize</Button> again.</p>
68
+
69
  {userChannels?.length ? <ChannelList
70
  layout="grid"
71
  channels={[
 
81
  setView("user_channel")
82
  }}
83
  />
84
+ : isLoaded ? null : <p>Loading channels owned by @{user?.userName}..</p>}
85
+ </div> : <p>To create a channel, comment or like a video please <Button onClick={login}>Login with Hugging Face</Button>.</p>}
 
86
  </div>
87
  )
88
  }
src/lib/useHuggingFaceLogin.ts DELETED
@@ -1,75 +0,0 @@
1
- import { useEffect, useState } from "react"
2
-
3
- import { oauthHandleRedirectIfPresent, oauthLoginUrl } from "@huggingface/hub"
4
-
5
- export function useHuggingFaceLogin(onLogin?: (data: any) => void) {
6
- const [isLoggedIn, setLoggedIn] = useState(false)
7
- const [oauthResult, setOauthResult] = useState<any>({})
8
-
9
- useEffect(() => {
10
- const fn = async () => {
11
- const res = await oauthHandleRedirectIfPresent()
12
- if (res) {
13
- setOauthResult(res)
14
- setLoggedIn(true)
15
- onLogin?.(res)
16
- }
17
- }
18
- fn()
19
- }, [])
20
-
21
- const login = async () => {
22
- const oauthUrl = await oauthLoginUrl({
23
- /**
24
- * OAuth client ID.
25
- *
26
- * For static Spaces, you can omit this and it will be loaded from the Space config, as long as `hf_oauth: true` is present in the README.md's metadata.
27
- * For other Spaces, it is available to the backend in the OAUTH_CLIENT_ID environment variable, as long as `hf_oauth: true` is present in the README.md's metadata.
28
- *
29
- * You can also create a Developer Application at https://huggingface.co/settings/connected-applications and use its client ID.
30
- */
31
- clientId: process.env.NEXT_PUBLIC_AI_TUBE_OAUTH_CLIENT_ID,
32
-
33
- // hubUrl?: string;
34
-
35
- /**
36
- * OAuth scope, a list of space separate scopes.
37
- *
38
- * For static Spaces, you can omit this and it will be loaded from the Space config, as long as `hf_oauth: true` is present in the README.md's metadata.
39
- * For other Spaces, it is available to the backend in the OAUTH_SCOPES environment variable, as long as `hf_oauth: true` is present in the README.md's metadata.
40
- *
41
- * Defaults to "openid profile".
42
- *
43
- * You can also create a Developer Application at https://huggingface.co/settings/connected-applications and use its scopes.
44
- *
45
- * See https://huggingface.co/docs/hub/oauth for a list of available scopes.
46
- */
47
- scopes: "openid profile",
48
-
49
- /**
50
- * Redirect URI, defaults to the current URL.
51
- *
52
- * For Spaces, any URL within the Space is allowed.
53
- *
54
- * For Developer Applications, you can add any URL you want to the list of allowed redirect URIs at https://huggingface.co/settings/connected-applications.
55
- */
56
- redirectUrl: "https://jbilcke-hf-ai-tube.hf.space",
57
-
58
- /**
59
- * State to pass to the OAuth provider, which will be returned in the call to `oauthLogin` after the redirect.
60
- */
61
- // state: ""
62
- })
63
-
64
- console.log("oauthUrl:", oauthUrl)
65
- window.location.href = oauthUrl
66
- }
67
-
68
- console.log(JSON.stringify(oauthResult, null, 2))
69
-
70
- return {
71
- isLoggedIn,
72
- login,
73
- oauthResult,
74
- }
75
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/types/general.ts CHANGED
@@ -635,6 +635,7 @@ export type InterfaceView =
635
 
636
  export type Settings = {
637
  huggingfaceApiKey: string
 
638
  }
639
 
640
  export type ParsedDatasetReadme = {
 
635
 
636
  export type Settings = {
637
  huggingfaceApiKey: string
638
+ huggingfaceTemporaryApiKey: string
639
  }
640
 
641
  export type ParsedDatasetReadme = {