mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-09 12:08:50 +01:00
🛂 feat: OpenID Logout Redirect to end_session_endpoint (#5626)
* WIP: end session endpoint * refactor: move useGetBannerQuery outside of package * refactor: add queriesEnabled and move useGetEndpointsConfigQuery to data-provider (local) * refactor: move useGetEndpointsQuery import to data-provider * refactor: relocate useGetEndpointsQuery import to improve module organization * refactor: move `useGetStartupConfig` from package to `~/data-provider` * refactor: move useGetUserBalance to data-provider and update imports * refactor: update query enabled conditions to include config check * refactor: remove unused useConfigOverride import from useAppStartup * refactor: integrate queriesEnabled state into file and search queries and move useGetSearchEnabledQuery to data-provider (local) * refactor: move useGetUserQuery to data-provider and update imports * refactor: enhance loginUser mutation with success and error handling as pass in options to hook * refactor: update enabled condition in queries to handle undefined config * refactor: enhance authentication mutations with queriesEnabled state management * refactor: improve conditional rendering for error messages and feature flags in Login component * refactor: remove unused queriesEnabled state from AuthContextProvider * refactor: implement queriesEnabled state management in LoginLayout with timeout handling * refactor: add conditional check for end session endpoint in OpenID strategy * ci: fix tests after changes * refactor: remove endSessionEndpoint from user schema and update logoutController to use OpenID issuer's end_session_endpoint * refactor: update logoutController to use end_session_endpoint from issuer metadata
This commit is contained in:
parent
d93f5c9061
commit
45dd2b262f
73 changed files with 385 additions and 270 deletions
|
|
@ -1 +1,2 @@
|
|||
export * from './queries';
|
||||
export * from './mutations';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { useResetRecoilState } from 'recoil';
|
||||
import { useResetRecoilState, useSetRecoilState } from 'recoil';
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { MutationKeys, dataService } from 'librechat-data-provider';
|
||||
import { MutationKeys, dataService, request } from 'librechat-data-provider';
|
||||
import type { UseMutationResult } from '@tanstack/react-query';
|
||||
import type * as t from 'librechat-data-provider';
|
||||
import useClearStates from '~/hooks/Config/useClearStates';
|
||||
|
|
@ -9,15 +9,17 @@ import store from '~/store';
|
|||
/* login/logout */
|
||||
export const useLogoutUserMutation = (
|
||||
options?: t.LogoutOptions,
|
||||
): UseMutationResult<unknown, unknown, undefined, unknown> => {
|
||||
): UseMutationResult<t.TLogoutResponse, unknown, undefined, unknown> => {
|
||||
const queryClient = useQueryClient();
|
||||
const clearStates = useClearStates();
|
||||
const resetDefaultPreset = useResetRecoilState(store.defaultPreset);
|
||||
const setQueriesEnabled = useSetRecoilState<boolean>(store.queriesEnabled);
|
||||
|
||||
return useMutation([MutationKeys.logoutUser], {
|
||||
mutationFn: () => dataService.logout(),
|
||||
...(options || {}),
|
||||
onSuccess: (...args) => {
|
||||
setQueriesEnabled(false);
|
||||
resetDefaultPreset();
|
||||
clearStates();
|
||||
queryClient.removeQueries();
|
||||
|
|
@ -26,20 +28,39 @@ export const useLogoutUserMutation = (
|
|||
});
|
||||
};
|
||||
|
||||
export const useLoginUserMutation = (): UseMutationResult<
|
||||
t.TLoginResponse,
|
||||
unknown,
|
||||
t.TLoginUser,
|
||||
unknown
|
||||
> => {
|
||||
export const useLoginUserMutation = (
|
||||
options?: t.MutationOptions<t.TLoginResponse, t.TLoginUser, unknown, unknown>,
|
||||
): UseMutationResult<t.TLoginResponse, unknown, t.TLoginUser, unknown> => {
|
||||
const queryClient = useQueryClient();
|
||||
const clearStates = useClearStates();
|
||||
const resetDefaultPreset = useResetRecoilState(store.defaultPreset);
|
||||
return useMutation((payload: t.TLoginUser) => dataService.login(payload), {
|
||||
onMutate: () => {
|
||||
const setQueriesEnabled = useSetRecoilState<boolean>(store.queriesEnabled);
|
||||
return useMutation([MutationKeys.loginUser], {
|
||||
mutationFn: (payload: t.TLoginUser) => dataService.login(payload),
|
||||
...(options || {}),
|
||||
onMutate: (vars) => {
|
||||
resetDefaultPreset();
|
||||
clearStates();
|
||||
queryClient.removeQueries();
|
||||
options?.onMutate?.(vars);
|
||||
},
|
||||
onSuccess: (...args) => {
|
||||
setQueriesEnabled(true);
|
||||
options?.onSuccess?.(...args);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useRefreshTokenMutation = (
|
||||
options?: t.MutationOptions<t.TRefreshTokenResponse | undefined, undefined, unknown, unknown>,
|
||||
): UseMutationResult<t.TRefreshTokenResponse | undefined, unknown, undefined, unknown> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation([MutationKeys.refreshToken], {
|
||||
mutationFn: () => request.refreshToken(),
|
||||
...(options || {}),
|
||||
onMutate: (vars) => {
|
||||
queryClient.removeQueries();
|
||||
options?.onMutate?.(vars);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
|||
20
client/src/data-provider/Auth/queries.ts
Normal file
20
client/src/data-provider/Auth/queries.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { useRecoilValue } from 'recoil';
|
||||
import { QueryKeys, dataService } from 'librechat-data-provider';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import type { QueryObserverResult, UseQueryOptions } from '@tanstack/react-query';
|
||||
import type t from 'librechat-data-provider';
|
||||
import store from '~/store';
|
||||
|
||||
export const useGetUserQuery = (
|
||||
config?: UseQueryOptions<t.TUser>,
|
||||
): QueryObserverResult<t.TUser> => {
|
||||
const queriesEnabled = useRecoilValue<boolean>(store.queriesEnabled);
|
||||
return useQuery<t.TUser>([QueryKeys.user], () => dataService.getUser(), {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
retry: false,
|
||||
...config,
|
||||
enabled: (config?.enabled ?? true) === true && queriesEnabled,
|
||||
});
|
||||
};
|
||||
1
client/src/data-provider/Endpoints/index.ts
Normal file
1
client/src/data-provider/Endpoints/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './queries';
|
||||
41
client/src/data-provider/Endpoints/queries.ts
Normal file
41
client/src/data-provider/Endpoints/queries.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { useRecoilValue } from 'recoil';
|
||||
import { QueryKeys, dataService } from 'librechat-data-provider';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import type { QueryObserverResult, UseQueryOptions } from '@tanstack/react-query';
|
||||
import type t from 'librechat-data-provider';
|
||||
import store from '~/store';
|
||||
|
||||
export const useGetEndpointsQuery = <TData = t.TEndpointsConfig>(
|
||||
config?: UseQueryOptions<t.TEndpointsConfig, unknown, TData>,
|
||||
): QueryObserverResult<TData> => {
|
||||
const queriesEnabled = useRecoilValue<boolean>(store.queriesEnabled);
|
||||
return useQuery<t.TEndpointsConfig, unknown, TData>(
|
||||
[QueryKeys.endpoints],
|
||||
() => dataService.getAIEndpoints(),
|
||||
{
|
||||
staleTime: Infinity,
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
...config,
|
||||
enabled: (config?.enabled ?? true) === true && queriesEnabled,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const useGetStartupConfig = (
|
||||
config?: UseQueryOptions<t.TStartupConfig>,
|
||||
): QueryObserverResult<t.TStartupConfig> => {
|
||||
const queriesEnabled = useRecoilValue<boolean>(store.queriesEnabled);
|
||||
return useQuery<t.TStartupConfig>(
|
||||
[QueryKeys.startupConfig],
|
||||
() => dataService.getStartupConfig(),
|
||||
{
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
...config,
|
||||
enabled: (config?.enabled ?? true) === true && queriesEnabled,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
|
@ -1,17 +1,21 @@
|
|||
import { useRecoilValue } from 'recoil';
|
||||
import { QueryKeys, dataService } from 'librechat-data-provider';
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import type { QueryObserverResult, UseQueryOptions } from '@tanstack/react-query';
|
||||
import type t from 'librechat-data-provider';
|
||||
import { addFileToCache } from '~/utils';
|
||||
import store from '~/store';
|
||||
|
||||
export const useGetFiles = <TData = t.TFile[] | boolean>(
|
||||
config?: UseQueryOptions<t.TFile[], unknown, TData>,
|
||||
): QueryObserverResult<TData, unknown> => {
|
||||
const queriesEnabled = useRecoilValue<boolean>(store.queriesEnabled);
|
||||
return useQuery<t.TFile[], unknown, TData>([QueryKeys.files], () => dataService.getFiles(), {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
...config,
|
||||
enabled: (config?.enabled ?? true) === true && queriesEnabled,
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
1
client/src/data-provider/Misc/index.ts
Normal file
1
client/src/data-provider/Misc/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './queries';
|
||||
45
client/src/data-provider/Misc/queries.ts
Normal file
45
client/src/data-provider/Misc/queries.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import { useRecoilValue } from 'recoil';
|
||||
import { QueryKeys, dataService } from 'librechat-data-provider';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import type { QueryObserverResult, UseQueryOptions } from '@tanstack/react-query';
|
||||
import type t from 'librechat-data-provider';
|
||||
import store from '~/store';
|
||||
|
||||
export const useGetBannerQuery = (
|
||||
config?: UseQueryOptions<t.TBannerResponse>,
|
||||
): QueryObserverResult<t.TBannerResponse> => {
|
||||
const queriesEnabled = useRecoilValue<boolean>(store.queriesEnabled);
|
||||
return useQuery<t.TBannerResponse>([QueryKeys.banner], () => dataService.getBanner(), {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
...config,
|
||||
enabled: (config?.enabled ?? true) === true && queriesEnabled,
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetUserBalance = (
|
||||
config?: UseQueryOptions<string>,
|
||||
): QueryObserverResult<string> => {
|
||||
const queriesEnabled = useRecoilValue<boolean>(store.queriesEnabled);
|
||||
return useQuery<string>([QueryKeys.balance], () => dataService.getUserBalance(), {
|
||||
refetchOnWindowFocus: true,
|
||||
refetchOnReconnect: true,
|
||||
refetchOnMount: true,
|
||||
...config,
|
||||
enabled: (config?.enabled ?? true) === true && queriesEnabled,
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetSearchEnabledQuery = (
|
||||
config?: UseQueryOptions<boolean>,
|
||||
): QueryObserverResult<boolean> => {
|
||||
const queriesEnabled = useRecoilValue<boolean>(store.queriesEnabled);
|
||||
return useQuery<boolean>([QueryKeys.searchEnabled], () => dataService.getSearchEnabled(), {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
...config,
|
||||
enabled: (config?.enabled ?? true) === true && queriesEnabled,
|
||||
});
|
||||
};
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
export * from './Auth';
|
||||
export * from './Agents';
|
||||
export * from './Endpoints';
|
||||
export * from './Files';
|
||||
export * from './Messages';
|
||||
export * from './Misc';
|
||||
export * from './Tools';
|
||||
export * from './connection';
|
||||
export * from './mutations';
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {
|
|||
defaultOrderQuery,
|
||||
defaultAssistantsVersion,
|
||||
} from 'librechat-data-provider';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useQuery, useInfiniteQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import type {
|
||||
UseInfiniteQueryOptions,
|
||||
|
|
@ -28,6 +29,7 @@ import type {
|
|||
SharedLinksResponse,
|
||||
} from 'librechat-data-provider';
|
||||
import { findPageForConversation } from '~/utils';
|
||||
import store from '~/store';
|
||||
|
||||
export const useGetPresetsQuery = (
|
||||
config?: UseQueryOptions<TPreset[]>,
|
||||
|
|
@ -115,6 +117,7 @@ export const useConversationsInfiniteQuery = (
|
|||
params?: ConversationListParams,
|
||||
config?: UseInfiniteQueryOptions<ConversationListResponse, unknown>,
|
||||
) => {
|
||||
const queriesEnabled = useRecoilValue<boolean>(store.queriesEnabled);
|
||||
return useInfiniteQuery<ConversationListResponse, unknown>(
|
||||
params?.isArchived === true ? [QueryKeys.archivedConversations] : [QueryKeys.allConversations],
|
||||
({ pageParam = '' }) =>
|
||||
|
|
@ -135,6 +138,7 @@ export const useConversationsInfiniteQuery = (
|
|||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
...config,
|
||||
enabled: (config?.enabled ?? true) === true && queriesEnabled,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
|
@ -156,7 +160,7 @@ export const useSharedLinksQuery = (
|
|||
sortBy,
|
||||
sortDirection,
|
||||
}),
|
||||
getNextPageParam: (lastPage) => lastPage?.nextCursor ?? undefined,
|
||||
getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,
|
||||
keepPreviousData: true,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
cacheTime: 30 * 60 * 1000, // 30 minutes
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue