From 2a7ffff96d62d3e44df8e0dba12cd39701bada50 Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Wed, 21 May 2025 16:19:34 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F(frontend)=20prevent=20authen?= =?UTF-8?q?tication=20retry=20on=20401=20responses?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop retry attempts when receiving 401 Unauthorized from /me endpoint since this clearly indicates authentication status. The original purpose of the /me call is simply to determine if user is authenticated, and a 401 provides sufficient information. Prevents unnecessary network requests caused by React Query's automatic retry behavior when re-raising exceptions, which was hiding the 401 status. Improves performance and reduces server load during authentication failures. --- .../apps/impress/src/core/AppProvider.tsx | 4 +++- .../src/features/auth/api/useAuthQuery.tsx | 21 ++++++++++++++++--- .../language/hooks/useSynchronizedLanguage.ts | 4 ++-- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/frontend/apps/impress/src/core/AppProvider.tsx b/src/frontend/apps/impress/src/core/AppProvider.tsx index 03ce5097..9f18e114 100644 --- a/src/frontend/apps/impress/src/core/AppProvider.tsx +++ b/src/frontend/apps/impress/src/core/AppProvider.tsx @@ -9,6 +9,8 @@ import { useResponsiveStore } from '@/stores/'; import { ConfigProvider } from './config/'; +export const DEFAULT_QUERY_RETRY = 1; + /** * QueryClient: * - defaultOptions: @@ -19,7 +21,7 @@ import { ConfigProvider } from './config/'; const defaultOptions = { queries: { staleTime: 1000 * 60 * 3, - retry: 1, + retry: DEFAULT_QUERY_RETRY, }, }; const queryClient = new QueryClient({ diff --git a/src/frontend/apps/impress/src/features/auth/api/useAuthQuery.tsx b/src/frontend/apps/impress/src/features/auth/api/useAuthQuery.tsx index 026beec9..0b3fe070 100644 --- a/src/frontend/apps/impress/src/features/auth/api/useAuthQuery.tsx +++ b/src/frontend/apps/impress/src/features/auth/api/useAuthQuery.tsx @@ -1,9 +1,12 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query'; import { APIError, errorCauses, fetchAPI } from '@/api'; +import { DEFAULT_QUERY_RETRY } from '@/core'; import { User } from './types'; +type UserResponse = User | null; + /** * Asynchronously retrieves the current user's data from the API. * This function is called during frontend initialization to check @@ -14,8 +17,13 @@ import { User } from './types'; * @throws {Error} Throws an error if the API request fails. * @returns {Promise} A promise that resolves to the user data. */ -export const getMe = async (): Promise => { +export const getMe = async (): Promise => { const response = await fetchAPI(`users/me/`); + + if (response.status === 401) { + return null; + } + if (!response.ok) { throw new APIError( `Couldn't fetch user data: ${response.statusText}`, @@ -28,12 +36,19 @@ export const getMe = async (): Promise => { export const KEY_AUTH = 'auth'; export function useAuthQuery( - queryConfig?: UseQueryOptions, + queryConfig?: UseQueryOptions, ) { - return useQuery({ + return useQuery({ queryKey: [KEY_AUTH], queryFn: getMe, staleTime: 1000 * 60 * 15, // 15 minutes + retry: (failureCount, error) => { + // we assume that a 401 means the user is not logged in + if (error.status == 401) { + return false; + } + return failureCount < DEFAULT_QUERY_RETRY; + }, ...queryConfig, }); } diff --git a/src/frontend/apps/impress/src/features/language/hooks/useSynchronizedLanguage.ts b/src/frontend/apps/impress/src/features/language/hooks/useSynchronizedLanguage.ts index 997dc8bc..b6376505 100644 --- a/src/frontend/apps/impress/src/features/language/hooks/useSynchronizedLanguage.ts +++ b/src/frontend/apps/impress/src/features/language/hooks/useSynchronizedLanguage.ts @@ -22,7 +22,7 @@ export const useSynchronizedLanguage = () => { ); const changeBackendLanguage = useCallback( - async (language: string, user?: User) => { + async (language: string, user?: User | null) => { const closestBackendLanguage = getMatchingLocales( availableBackendLanguages, [language], @@ -52,7 +52,7 @@ export const useSynchronizedLanguage = () => { ); const changeLanguageSynchronized = useCallback( - async (language: string, user?: User) => { + async (language: string, user?: User | null) => { if (!isSynchronizingLanguage.current) { isSynchronizingLanguage.current = true; await changeFrontendLanguage(language);