From 83a4474c6e556ade2c95481d119c6e2cae876332 Mon Sep 17 00:00:00 2001 From: Mathijs de Bruin Date: Mon, 25 Nov 2024 19:30:52 +0000 Subject: [PATCH] WIP this is insane. --- libs/react-client/src/api/hooks/api.ts | 13 +++-- libs/react-client/src/api/hooks/auth/index.ts | 1 - libs/react-client/src/api/index.tsx | 16 +++--- libs/react-client/src/auth/user.ts | 50 ++++++++++++------- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/libs/react-client/src/api/hooks/api.ts b/libs/react-client/src/api/hooks/api.ts index 25c508afa0..5f2e6d5ad9 100644 --- a/libs/react-client/src/api/hooks/api.ts +++ b/libs/react-client/src/api/hooks/api.ts @@ -8,9 +8,10 @@ import useSWR, { SWRConfiguration } from 'swr'; const fetcher = async ( client: ChainlitAPI, endpoint: string, - token?: string + token?: string, + expect401?: boolean ) => { - const res = await client.get(endpoint, token); + const res = await client.get(endpoint, token, expect401); return res?.json(); }; @@ -40,7 +41,11 @@ const fetcher = async ( */ function useApi( path?: string | null, - { token, ...swrConfig }: SWRConfiguration & { token?: string } = {} + { + token, + expect401, + ...swrConfig + }: SWRConfiguration & { token?: string; expect401?: boolean } = {} ) { const client = useContext(ChainlitContext); let accessToken = useRecoilValue(accessTokenState); @@ -50,7 +55,7 @@ function useApi( const memoizedFetcher = useMemo( () => ([url, token]: [url: string, token: string]) => - fetcher(client, url, token), + fetcher(client, url, token, expect401), [client] ); diff --git a/libs/react-client/src/api/hooks/auth/index.ts b/libs/react-client/src/api/hooks/auth/index.ts index e18763226e..ba7ae8b12c 100644 --- a/libs/react-client/src/api/hooks/auth/index.ts +++ b/libs/react-client/src/api/hooks/auth/index.ts @@ -12,7 +12,6 @@ export const useAuth = (): IUseAuth => { const { logout } = useSessionManagement(); const { user, setUserFromAPI } = useUser(); const [accessToken] = useRecoilState(accessTokenState); - const { handleSetAccessToken } = useTokenManagement(); const isReady = !!(!isLoading && authConfig); diff --git a/libs/react-client/src/api/index.tsx b/libs/react-client/src/api/index.tsx index 7955ebfa14..989a3ca52d 100644 --- a/libs/react-client/src/api/index.tsx +++ b/libs/react-client/src/api/index.tsx @@ -1,5 +1,5 @@ import { ensureTokenPrefix, removeToken } from 'src/auth/token'; -import { IThread, IUser } from 'src/types'; +import { IThread } from 'src/types'; import { IFeedback } from 'src/types/feedback'; @@ -81,7 +81,8 @@ export class APIBase { path: string, token?: string, data?: Payload, - signal?: AbortSignal + signal?: AbortSignal, + expect401?: boolean ): Promise { try { const headers: { Authorization?: string; 'Content-Type'?: string } = {}; @@ -105,7 +106,7 @@ export class APIBase { if (!res.ok) { const body = await res.json(); - if (res.status === 401 && this.on401) { + if (res.status === 401 && !expect401 && this.on401) { removeToken(); this.on401(); } @@ -122,8 +123,8 @@ export class APIBase { } } - async get(endpoint: string, token?: string) { - return await this.fetch('GET', endpoint, token); + async get(endpoint: string, token?: string, expect401?: boolean) { + return await this.fetch('GET', endpoint, token, { expect401 }); } async post( @@ -159,11 +160,6 @@ export class ChainlitAPI extends APIBase { return res.json(); } - async getUser(accessToken?: string): Promise { - const res = await this.get(`/user`, accessToken); - return res.json(); - } - async logout() { const res = await this.post(`/logout`, {}); return res.json(); diff --git a/libs/react-client/src/auth/user.ts b/libs/react-client/src/auth/user.ts index c39ec6ade7..a45b80f198 100644 --- a/libs/react-client/src/auth/user.ts +++ b/libs/react-client/src/auth/user.ts @@ -6,6 +6,9 @@ import { IUser, useApi } from '..'; import { useAuthConfig } from './config'; import { getToken, useTokenManagement } from './token'; +// Crappy logic due to lack of something like an `` component. +let isInitialized = false; + export const useUser = () => { console.log('useUser'); @@ -13,38 +16,47 @@ export const useUser = () => { const { cookieAuth } = useAuthConfig(); const { handleSetAccessToken } = useTokenManagement(); - const { data: userData, mutate: mutateUserData } = useApi('/user', { - revalidateOnMount: false - }); + const { data: userData, mutate: mutateUserData } = useApi( + cookieAuth ? '/user' : null, + { + expect401: true + // onErrorRetry: (error, key, config, revalidate, { retryCount }) => { + // console.log('onError'); + // // 401 is a normal response until we're logged in. + // if (error.status === 401) { + // // Make sure we remove user though + // setUser(null); + // return; + // } + + // // On other errors, retry after 5 seconds. + // setTimeout(() => revalidate({ retryCount }), config.errorRetryInterval) + // } + } + ); - // Attempt to get user when cookieAuth are available. + // Not using cookie auth, callback to header tokens useEffect(() => { - if (!user) { - if (cookieAuth) { - console.log('cookieAuth', user, cookieAuth); - mutateUserData(); - return; - } - - // Not using cookie auth, callback to header tokens - console.log('tokenAuth', user, cookieAuth); + if (!isInitialized && !user && !cookieAuth) { const token = getToken(); if (token) handleSetAccessToken(token); } - }, [user, cookieAuth]); + }, [cookieAuth]); - // When user data is available, set the user object. + // When user data is available from the API, set the user object. useEffect(() => { - console.log('userData effect'); - - if (userData) { + if (!isInitialized && userData) { console.log('setUser', userData); setUser(userData); } }, [userData]); + // Make sure effects are only executed once. useEffect(() => { - console.log('useUser effect'); + if (!isInitialized) { + isInitialized = true; + console.log('isInitialized'); + } }); return {