mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-20 10:20:15 +01:00
* fix: add basePath pattern to support login/register and image paths * Fix linter errors * refactor: Update import statements for getBasePath and isEnabled, and add path utility functions with tests - Refactored imports in addImages.js and StableDiffusion.js to use getBasePath from '@librechat/api'. - Consolidated isEnabled and getBasePath imports in validateImageRequest.js. - Introduced new path utility functions in path.ts and corresponding unit tests in path.spec.ts to validate base path extraction logic. * fix: Update domain server base URL in MarkdownComponents and refactor authentication redirection logic - Changed the domain server base URL in MarkdownComponents.tsx to use the API base URL. - Refactored the useAuthRedirect hook to utilize React Router's navigate for redirection instead of window.location, ensuring a smoother SPA experience. - Added unit tests for the useAuthRedirect hook to verify authentication redirection behavior. * test: Mock isEnabled in validateImages.spec.js for improved test isolation - Updated validateImages.spec.js to mock the isEnabled function from @librechat/api, ensuring that tests can run independently of the actual implementation. - Cleared the DOMAIN_CLIENT environment variable before tests to avoid interference with basePath resolution. --------- Co-authored-by: Danny Avila <danny@librechat.ai>
118 lines
4.2 KiB
TypeScript
118 lines
4.2 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { ErrorTypes, registerPage } from 'librechat-data-provider';
|
|
import { OpenIDIcon, useToastContext } from '@librechat/client';
|
|
import { useOutletContext, useSearchParams } from 'react-router-dom';
|
|
import type { TLoginLayoutContext } from '~/common';
|
|
import { ErrorMessage } from '~/components/Auth/ErrorMessage';
|
|
import SocialButton from '~/components/Auth/SocialButton';
|
|
import { useAuthContext } from '~/hooks/AuthContext';
|
|
import { getLoginError } from '~/utils';
|
|
import { useLocalize } from '~/hooks';
|
|
import LoginForm from './LoginForm';
|
|
|
|
function Login() {
|
|
const localize = useLocalize();
|
|
const { showToast } = useToastContext();
|
|
const { error, setError, login } = useAuthContext();
|
|
const { startupConfig } = useOutletContext<TLoginLayoutContext>();
|
|
|
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
// Determine if auto-redirect should be disabled based on the URL parameter
|
|
const disableAutoRedirect = searchParams.get('redirect') === 'false';
|
|
|
|
// Persist the disable flag locally so that once detected, auto-redirect stays disabled.
|
|
const [isAutoRedirectDisabled, setIsAutoRedirectDisabled] = useState(disableAutoRedirect);
|
|
|
|
useEffect(() => {
|
|
const oauthError = searchParams?.get('error');
|
|
if (oauthError && oauthError === ErrorTypes.AUTH_FAILED) {
|
|
showToast({
|
|
message: localize('com_auth_error_oauth_failed'),
|
|
status: 'error',
|
|
});
|
|
const newParams = new URLSearchParams(searchParams);
|
|
newParams.delete('error');
|
|
setSearchParams(newParams, { replace: true });
|
|
}
|
|
}, [searchParams, setSearchParams, showToast, localize]);
|
|
|
|
// Once the disable flag is detected, update local state and remove the parameter from the URL.
|
|
useEffect(() => {
|
|
if (disableAutoRedirect) {
|
|
setIsAutoRedirectDisabled(true);
|
|
const newParams = new URLSearchParams(searchParams);
|
|
newParams.delete('redirect');
|
|
setSearchParams(newParams, { replace: true });
|
|
}
|
|
}, [disableAutoRedirect, searchParams, setSearchParams]);
|
|
|
|
// Determine whether we should auto-redirect to OpenID.
|
|
const shouldAutoRedirect =
|
|
startupConfig?.openidLoginEnabled &&
|
|
startupConfig?.openidAutoRedirect &&
|
|
startupConfig?.serverDomain &&
|
|
!isAutoRedirectDisabled;
|
|
|
|
useEffect(() => {
|
|
if (shouldAutoRedirect) {
|
|
console.log('Auto-redirecting to OpenID provider...');
|
|
window.location.href = `${startupConfig.serverDomain}/oauth/openid`;
|
|
}
|
|
}, [shouldAutoRedirect, startupConfig]);
|
|
|
|
// Render fallback UI if auto-redirect is active.
|
|
if (shouldAutoRedirect) {
|
|
return (
|
|
<div className="flex min-h-screen flex-col items-center justify-center p-4">
|
|
<p className="text-lg font-semibold">
|
|
{localize('com_ui_redirecting_to_provider', { 0: startupConfig.openidLabel })}
|
|
</p>
|
|
<div className="mt-4">
|
|
<SocialButton
|
|
key="openid"
|
|
enabled={startupConfig.openidLoginEnabled}
|
|
serverDomain={startupConfig.serverDomain}
|
|
oauthPath="openid"
|
|
Icon={() =>
|
|
startupConfig.openidImageUrl ? (
|
|
<img src={startupConfig.openidImageUrl} alt="OpenID Logo" className="h-5 w-5" />
|
|
) : (
|
|
<OpenIDIcon />
|
|
)
|
|
}
|
|
label={startupConfig.openidLabel}
|
|
id="openid"
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
{error != null && <ErrorMessage>{localize(getLoginError(error))}</ErrorMessage>}
|
|
{startupConfig?.emailLoginEnabled === true && (
|
|
<LoginForm
|
|
onSubmit={login}
|
|
startupConfig={startupConfig}
|
|
error={error}
|
|
setError={setError}
|
|
/>
|
|
)}
|
|
{startupConfig?.registrationEnabled === true && (
|
|
<p className="my-4 text-center text-sm font-light text-gray-700 dark:text-white">
|
|
{' '}
|
|
{localize('com_auth_no_account')}{' '}
|
|
<a
|
|
href={registerPage()}
|
|
className="inline-flex p-1 text-sm font-medium text-green-600 transition-colors hover:text-green-700 dark:text-green-400 dark:hover:text-green-300"
|
|
>
|
|
{localize('com_auth_sign_up')}
|
|
</a>
|
|
</p>
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
export default Login;
|