mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-31 23:58:50 +01:00
Auth fix (#624)
* chore(eslint): add ignore pattern for packages/data-provider/types
chore(data-provider): fix import formatting in index.ts
chore(data-provider): add types/index.d.ts to tsconfig include
* fix(Auth): fix "skip login" bug, where UI would render in an unauthenticated state
fix(Login.tsx): replace navigate('/chat/new') with navigate('/chat/new', { replace: true })
fix(AuthContext.tsx): replace navigate(redirect) with navigate(redirect, { replace: true })
fix(AuthContext.tsx): replace navigate('/login') with navigate('/login', { replace: true })
fix(AuthContext.tsx): replace navigate('/login') with navigate('/login', { replace: true })
fix(routes/Chat.jsx): add check for isAuthenticated: navigate to '/login' and render null if not authenticated
fix(routes/index.jsx): add check for isAuthenticated: navigate to '/login' and render null if not authenticated
* refactor(SubmitButton.jsx): create a set of endpoints to hide set tokens
fix(SubmitButton.jsx): fix condition to check if token is provided for certain endpoints
This commit is contained in:
parent
747e087cf5
commit
f5672ddcf8
10 changed files with 47 additions and 21 deletions
|
|
@ -13,6 +13,9 @@ module.exports = {
|
|||
'plugin:jest/recommended',
|
||||
'prettier'
|
||||
],
|
||||
ignorePatterns: [
|
||||
'packages/data-provider/types/**/*',
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ function Login() {
|
|||
|
||||
useEffect(() => {
|
||||
if (isAuthenticated) {
|
||||
navigate('/chat/new');
|
||||
navigate('/chat/new', { replace: true });
|
||||
}
|
||||
}, [isAuthenticated, navigate]);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export default function SubmitButton({
|
|||
const { getToken } = store.useToken(endpoint);
|
||||
|
||||
const isTokenProvided = endpointsConfig?.[endpoint]?.userProvide ? !!getToken() : true;
|
||||
const endpointsToHideSetTokens = new Set(['openAI', 'azureOpenAI', 'bingAI']);
|
||||
|
||||
const clickHandler = (e) => {
|
||||
e.preventDefault();
|
||||
|
|
@ -38,7 +39,7 @@ export default function SubmitButton({
|
|||
</div>
|
||||
</button>
|
||||
);
|
||||
} else if (!isTokenProvided && (endpoint !== 'openAI' || endpoint !== 'azureOpenAI' )) {
|
||||
} else if (!isTokenProvided && (!endpointsToHideSetTokens.has(endpoint))) {
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ const AuthContextProvider = ({
|
|||
setTokenHeader(token);
|
||||
setIsAuthenticated(isAuthenticated);
|
||||
if (redirect) {
|
||||
navigate(redirect);
|
||||
navigate(redirect, { replace: true });
|
||||
}
|
||||
},
|
||||
[navigate]
|
||||
|
|
@ -101,7 +101,8 @@ const AuthContextProvider = ({
|
|||
setUserContext({ token, isAuthenticated: true, user, redirect: '/chat/new' });
|
||||
},
|
||||
onError: (error) => {
|
||||
doSetError(error.message);
|
||||
doSetError((error as Error).message);
|
||||
navigate('/login', { replace: true });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -122,7 +123,7 @@ const AuthContextProvider = ({
|
|||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
doSetError(error.message);
|
||||
doSetError((error as Error).message);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -131,9 +132,8 @@ const AuthContextProvider = ({
|
|||
if (userQuery.data) {
|
||||
setUser(userQuery.data);
|
||||
} else if (userQuery.isError) {
|
||||
//@ts-ignore - userQuery.error is of type unknown
|
||||
doSetError(userQuery?.error.message);
|
||||
navigate('/login');
|
||||
doSetError((userQuery?.error as Error).message);
|
||||
navigate('/login', { replace: true });
|
||||
}
|
||||
if (error && isAuthenticated) {
|
||||
doSetError(undefined);
|
||||
|
|
@ -143,7 +143,7 @@ const AuthContextProvider = ({
|
|||
if (tokenFromCookie) {
|
||||
setUserContext({ token: tokenFromCookie, isAuthenticated: true, user: userQuery.data });
|
||||
} else {
|
||||
navigate('/login');
|
||||
navigate('/login', { replace: true });
|
||||
}
|
||||
}
|
||||
}, [
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import { useAuthContext } from '~/hooks/AuthContext';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
|
|
@ -14,6 +15,7 @@ import {
|
|||
} from '@librechat/data-provider';
|
||||
|
||||
export default function Chat() {
|
||||
const { isAuthenticated } = useAuthContext();
|
||||
const [shouldNavigate, setShouldNavigate] = useState(true);
|
||||
const searchQuery = useRecoilValue(store.searchQuery);
|
||||
const [conversation, setConversation] = useRecoilState(store.conversation);
|
||||
|
|
@ -29,6 +31,18 @@ export default function Chat() {
|
|||
const getConversationMutation = useGetConversationByIdMutation(conversationId);
|
||||
const { data: config } = useGetStartupConfig();
|
||||
|
||||
useEffect(() => {
|
||||
let timeout = setTimeout(() => {
|
||||
if (!isAuthenticated) {
|
||||
navigate('/login', { replace: true });
|
||||
}
|
||||
}, 300)
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
}, [isAuthenticated, navigate]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isSubmitting && !shouldNavigate) {
|
||||
setShouldNavigate(true);
|
||||
|
|
@ -41,7 +55,7 @@ export default function Chat() {
|
|||
if (conversation === null && conversationId === 'new') {
|
||||
newConversation();
|
||||
setShouldNavigate(true);
|
||||
}
|
||||
}
|
||||
// No current conversation and conversationId exists
|
||||
else if (conversation === null && conversationId) {
|
||||
getConversationMutation.mutate(conversationId, {
|
||||
|
|
@ -53,24 +67,24 @@ export default function Chat() {
|
|||
onError: (error) => {
|
||||
console.error('Failed to fetch the conversation');
|
||||
console.error(error);
|
||||
navigate(`/chat/new`);
|
||||
navigate('/chat/new');
|
||||
newConversation();
|
||||
setShouldNavigate(true);
|
||||
}
|
||||
});
|
||||
setMessages(null);
|
||||
}
|
||||
}
|
||||
// No current conversation and no conversationId
|
||||
else if (conversation === null) {
|
||||
navigate(`/chat/new`);
|
||||
navigate('/chat/new');
|
||||
setShouldNavigate(true);
|
||||
}
|
||||
}
|
||||
// Current conversationId is 'search'
|
||||
else if (conversation?.conversationId === 'search') {
|
||||
navigate(`/search/${searchQuery}`);
|
||||
setShouldNavigate(true);
|
||||
}
|
||||
// Conversation change and isSubmitting
|
||||
}
|
||||
// Conversation change and isSubmitting
|
||||
else if (conversation?.conversationId !== conversationId && isSubmitting) {
|
||||
setShouldNavigate(false);
|
||||
}
|
||||
|
|
@ -101,6 +115,10 @@ export default function Chat() {
|
|||
}
|
||||
}, [messagesQuery.data, messagesQuery.isError, setMessages]);
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// if not a conversation
|
||||
if (conversation?.conversationId === 'search') return null;
|
||||
// if conversationId not match
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export default function Root() {
|
|||
const setIsSearchEnabled = useSetRecoilState(store.isSearchEnabled);
|
||||
const setEndpointsConfig = useSetRecoilState(store.endpointsConfig);
|
||||
const setPresets = useSetRecoilState(store.presets);
|
||||
const { user } = useAuthContext();
|
||||
const { user, isAuthenticated } = useAuthContext();
|
||||
|
||||
const searchEnabledQuery = useGetSearchEnabledQuery();
|
||||
const endpointsQuery = useGetEndpointsQuery();
|
||||
|
|
@ -57,6 +57,10 @@ export default function Root() {
|
|||
}
|
||||
}, [searchEnabledQuery.data, searchEnabledQuery.isError]);
|
||||
|
||||
if (!isAuthenticated) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex h-screen">
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export default function Search() {
|
|||
searchPlaceholderConversation();
|
||||
setSearchQuery(query);
|
||||
} else {
|
||||
navigate(`/chat/new`);
|
||||
navigate('/chat/new');
|
||||
}
|
||||
} else if (conversation?.conversationId === 'search') {
|
||||
// jump to search page
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const AuthLayout = () => (
|
|||
export const router = createBrowserRouter([
|
||||
{
|
||||
path: 'register',
|
||||
element: <Registration />
|
||||
element: <Registration />
|
||||
},
|
||||
{
|
||||
path: 'forgot-password',
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ export * from './types';
|
|||
export * from './react-query-service';
|
||||
export * from './headers-helpers';
|
||||
export * from './sse.mjs';
|
||||
export {default as createPayload} from './createPayload';
|
||||
export { default as createPayload } from './createPayload';
|
||||
|
|
@ -23,5 +23,5 @@
|
|||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist", "types"],
|
||||
"include": ["src/**/*"]
|
||||
"include": ["src/**/*", "types/index.d.ts"]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue