mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-02-27 12:54:09 +01:00
* added support for url query param persistance * refactor: authentication redirect handling - Introduced utility functions for managing login redirects, including `persistRedirectToSession`, `buildLoginRedirectUrl`, and `getPostLoginRedirect`. - Updated `Login` and `AuthContextProvider` components to utilize these utilities for improved redirect logic. - Refactored `useAuthRedirect` to streamline navigation to the login page while preserving intended destinations. - Cleaned up the `StartupLayout` to remove unnecessary redirect handling, ensuring a more straightforward navigation flow. - Added a new `redirect.ts` file to encapsulate redirect-related logic, enhancing code organization and maintainability. * fix: enhance safe redirect validation logic - Updated the `isSafeRedirect` function to improve validation of redirect URLs. - Ensured that only safe relative paths are accepted, specifically excluding paths that lead to the login page. - Refactored the logic to streamline the checks for valid redirect targets. * test: add unit tests for redirect utility functions - Introduced comprehensive tests for `isSafeRedirect`, `buildLoginRedirectUrl`, `getPostLoginRedirect`, and `persistRedirectToSession` functions. - Validated various scenarios including safe and unsafe redirects, URL encoding, and session storage behavior. - Enhanced test coverage to ensure robust handling of redirect logic and prevent potential security issues. * chore: streamline authentication and redirect handling - Removed unused `useLocation` import from `AuthContextProvider` and replaced its usage with `window.location` for better clarity. - Updated `StartupLayout` to check for pending redirects before navigating to the new chat page, ensuring users are directed appropriately based on their session state. - Enhanced unit tests for `useAuthRedirect` to verify correct handling of redirect parameters, including encoding of the current path and query parameters. * test: add unit tests for StartupLayout redirect behavior - Introduced a new test suite for the StartupLayout component to validate redirect logic based on authentication status and session storage. - Implemented tests to ensure correct navigation to the new conversation page when authenticated without pending redirects, and to prevent navigation when a redirect URL parameter or session storage redirect is present. - Enhanced coverage for scenarios where users are not authenticated, ensuring robust handling of redirect conditions. --------- Co-authored-by: Vamsi Konakanchi <vamsi.k@trackmind.com> Co-authored-by: Danny Avila <danny@librechat.ai>
77 lines
2.3 KiB
TypeScript
77 lines
2.3 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { Outlet, useNavigate, useLocation } from 'react-router-dom';
|
|
import type { TStartupConfig } from 'librechat-data-provider';
|
|
import { TranslationKeys, useLocalize } from '~/hooks';
|
|
import { useGetStartupConfig } from '~/data-provider';
|
|
import AuthLayout from '~/components/Auth/AuthLayout';
|
|
import { REDIRECT_PARAM, SESSION_KEY } from '~/utils';
|
|
|
|
const headerMap: Record<string, TranslationKeys> = {
|
|
'/login': 'com_auth_welcome_back',
|
|
'/register': 'com_auth_create_account',
|
|
'/forgot-password': 'com_auth_reset_password',
|
|
'/reset-password': 'com_auth_reset_password',
|
|
'/login/2fa': 'com_auth_verify_your_identity',
|
|
};
|
|
|
|
export default function StartupLayout({ isAuthenticated }: { isAuthenticated?: boolean }) {
|
|
const [error, setError] = useState<TranslationKeys | null>(null);
|
|
const [headerText, setHeaderText] = useState<TranslationKeys | null>(null);
|
|
const [startupConfig, setStartupConfig] = useState<TStartupConfig | null>(null);
|
|
const {
|
|
data,
|
|
isFetching,
|
|
error: startupConfigError,
|
|
} = useGetStartupConfig({
|
|
enabled: isAuthenticated ? startupConfig === null : true,
|
|
});
|
|
const localize = useLocalize();
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
|
|
useEffect(() => {
|
|
if (isAuthenticated) {
|
|
const hasPendingRedirect =
|
|
new URLSearchParams(window.location.search).has(REDIRECT_PARAM) ||
|
|
sessionStorage.getItem(SESSION_KEY) != null;
|
|
if (!hasPendingRedirect) {
|
|
navigate('/c/new', { replace: true });
|
|
}
|
|
}
|
|
if (data) {
|
|
setStartupConfig(data);
|
|
}
|
|
}, [isAuthenticated, navigate, data]);
|
|
|
|
useEffect(() => {
|
|
document.title = startupConfig?.appTitle || 'LibreChat';
|
|
}, [startupConfig?.appTitle]);
|
|
|
|
useEffect(() => {
|
|
setError(null);
|
|
setHeaderText(null);
|
|
}, [location.pathname]);
|
|
|
|
const contextValue = {
|
|
error,
|
|
setError,
|
|
headerText,
|
|
setHeaderText,
|
|
startupConfigError,
|
|
startupConfig,
|
|
isFetching,
|
|
};
|
|
|
|
return (
|
|
<AuthLayout
|
|
header={headerText ? localize(headerText) : localize(headerMap[location.pathname])}
|
|
isFetching={isFetching}
|
|
startupConfig={startupConfig}
|
|
startupConfigError={startupConfigError}
|
|
pathname={location.pathname}
|
|
error={error}
|
|
>
|
|
<Outlet context={contextValue} />
|
|
</AuthLayout>
|
|
);
|
|
}
|