yangdx
commited on
Commit
·
c114561
1
Parent(s):
a8128c3
Refactor navigation and authentication flow, prevent mounting login page multiple times
Browse files- Improved protected route handling
- Enhanced direct login access detection
- Centralized navigation logic
- Optimized state reset process
- Fixed logout navigation behavior
- lightrag/api/webui/assets/{index-BiPN9eZH.js → index-CMFGmyjk.js} +0 -0
- lightrag/api/webui/index.html +0 -0
- lightrag_webui/src/AppRouter.tsx +20 -2
- lightrag_webui/src/api/lightrag.ts +0 -5
- lightrag_webui/src/components/AppSettings.tsx +1 -1
- lightrag_webui/src/features/LoginPage.tsx +3 -6
- lightrag_webui/src/features/SiteHeader.tsx +3 -6
- lightrag_webui/src/services/navigation.ts +28 -9
lightrag/api/webui/assets/{index-BiPN9eZH.js → index-CMFGmyjk.js}
RENAMED
Binary files a/lightrag/api/webui/assets/index-BiPN9eZH.js and b/lightrag/api/webui/assets/index-CMFGmyjk.js differ
|
|
lightrag/api/webui/index.html
CHANGED
Binary files a/lightrag/api/webui/index.html and b/lightrag/api/webui/index.html differ
|
|
lightrag_webui/src/AppRouter.tsx
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
import { HashRouter as Router, Routes, Route, Navigate } from 'react-router-dom'
|
2 |
import { useEffect, useState } from 'react'
|
3 |
import { useAuthStore } from '@/stores/state'
|
|
|
4 |
import { getAuthStatus } from '@/api/lightrag'
|
5 |
import { toast } from 'sonner'
|
6 |
import { Toaster } from 'sonner'
|
@@ -65,9 +66,26 @@ const ProtectedRoute = ({ children }: ProtectedRouteProps) => {
|
|
65 |
return null
|
66 |
}
|
67 |
|
68 |
-
// After checking, if still not authenticated
|
69 |
if (!isAuthenticated) {
|
70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
}
|
72 |
|
73 |
return <>{children}</>
|
|
|
1 |
import { HashRouter as Router, Routes, Route, Navigate } from 'react-router-dom'
|
2 |
import { useEffect, useState } from 'react'
|
3 |
import { useAuthStore } from '@/stores/state'
|
4 |
+
import { navigationService } from '@/services/navigation'
|
5 |
import { getAuthStatus } from '@/api/lightrag'
|
6 |
import { toast } from 'sonner'
|
7 |
import { Toaster } from 'sonner'
|
|
|
66 |
return null
|
67 |
}
|
68 |
|
69 |
+
// After checking, if still not authenticated
|
70 |
if (!isAuthenticated) {
|
71 |
+
// Get current path and check if it's a direct access
|
72 |
+
const currentPath = window.location.hash.slice(1); // Remove the '#' from hash
|
73 |
+
const isLoginPage = currentPath === '/login';
|
74 |
+
const isDirectAccess = !document.referrer;
|
75 |
+
|
76 |
+
// Handle direct access to root path
|
77 |
+
if (isDirectAccess && currentPath === '/') {
|
78 |
+
navigationService.resetAllApplicationState();
|
79 |
+
}
|
80 |
+
|
81 |
+
// Skip redirect if already on login page
|
82 |
+
if (isLoginPage) {
|
83 |
+
return null;
|
84 |
+
}
|
85 |
+
|
86 |
+
// Use React Router's Navigate for redirection
|
87 |
+
console.log('Not authenticated, redirecting to login');
|
88 |
+
return <Navigate to="/login" replace />;
|
89 |
}
|
90 |
|
91 |
return <>{children}</>
|
lightrag_webui/src/api/lightrag.ts
CHANGED
@@ -2,7 +2,6 @@ import axios, { AxiosError } from 'axios'
|
|
2 |
import { backendBaseUrl } from '@/lib/constants'
|
3 |
import { errorMessage } from '@/lib/utils'
|
4 |
import { useSettingsStore } from '@/stores/settings'
|
5 |
-
import { useAuthStore } from '@/stores/state'
|
6 |
import { navigationService } from '@/services/navigation'
|
7 |
|
8 |
// Types
|
@@ -174,10 +173,6 @@ axiosInstance.interceptors.response.use(
|
|
174 |
(error: AxiosError) => {
|
175 |
if (error.response) {
|
176 |
if (error.response?.status === 401) {
|
177 |
-
localStorage.removeItem('LIGHTRAG-API-TOKEN');
|
178 |
-
sessionStorage.clear();
|
179 |
-
useAuthStore.getState().logout();
|
180 |
-
|
181 |
// Use navigation service to handle redirection
|
182 |
navigationService.navigateToLogin();
|
183 |
|
|
|
2 |
import { backendBaseUrl } from '@/lib/constants'
|
3 |
import { errorMessage } from '@/lib/utils'
|
4 |
import { useSettingsStore } from '@/stores/settings'
|
|
|
5 |
import { navigationService } from '@/services/navigation'
|
6 |
|
7 |
// Types
|
|
|
173 |
(error: AxiosError) => {
|
174 |
if (error.response) {
|
175 |
if (error.response?.status === 401) {
|
|
|
|
|
|
|
|
|
176 |
// Use navigation service to handle redirection
|
177 |
navigationService.navigateToLogin();
|
178 |
|
lightrag_webui/src/components/AppSettings.tsx
CHANGED
@@ -32,7 +32,7 @@ export default function AppSettings({ className }: AppSettingsProps) {
|
|
32 |
return (
|
33 |
<Popover open={opened} onOpenChange={setOpened}>
|
34 |
<PopoverTrigger asChild>
|
35 |
-
<Button variant="ghost" size="icon" className={cn(
|
36 |
<PaletteIcon className="h-5 w-5" />
|
37 |
</Button>
|
38 |
</PopoverTrigger>
|
|
|
32 |
return (
|
33 |
<Popover open={opened} onOpenChange={setOpened}>
|
34 |
<PopoverTrigger asChild>
|
35 |
+
<Button variant="ghost" size="icon" className={cn('h-9 w-9', className)}>
|
36 |
<PaletteIcon className="h-5 w-5" />
|
37 |
</Button>
|
38 |
</PopoverTrigger>
|
lightrag_webui/src/features/LoginPage.tsx
CHANGED
@@ -4,8 +4,6 @@ import { useAuthStore } from '@/stores/state'
|
|
4 |
import { loginToServer, getAuthStatus } from '@/api/lightrag'
|
5 |
import { toast } from 'sonner'
|
6 |
import { useTranslation } from 'react-i18next'
|
7 |
-
import { navigationService } from '@/services/navigation'
|
8 |
-
|
9 |
import { Card, CardContent, CardHeader } from '@/components/ui/Card'
|
10 |
import Input from '@/components/ui/Input'
|
11 |
import Button from '@/components/ui/Button'
|
@@ -21,12 +19,11 @@ const LoginPage = () => {
|
|
21 |
const [password, setPassword] = useState('')
|
22 |
const [checkingAuth, setCheckingAuth] = useState(true)
|
23 |
|
24 |
-
// Reset application state on first mount
|
25 |
useEffect(() => {
|
26 |
-
|
27 |
-
}, []);
|
28 |
|
29 |
-
// Check if authentication is configured
|
30 |
useEffect(() => {
|
31 |
let isMounted = true; // Flag to prevent state updates after unmount
|
32 |
|
|
|
4 |
import { loginToServer, getAuthStatus } from '@/api/lightrag'
|
5 |
import { toast } from 'sonner'
|
6 |
import { useTranslation } from 'react-i18next'
|
|
|
|
|
7 |
import { Card, CardContent, CardHeader } from '@/components/ui/Card'
|
8 |
import Input from '@/components/ui/Input'
|
9 |
import Button from '@/components/ui/Button'
|
|
|
19 |
const [password, setPassword] = useState('')
|
20 |
const [checkingAuth, setCheckingAuth] = useState(true)
|
21 |
|
|
|
22 |
useEffect(() => {
|
23 |
+
console.log('LoginPage mounted')
|
24 |
+
}, []);
|
25 |
|
26 |
+
// Check if authentication is configured, skip login if not
|
27 |
useEffect(() => {
|
28 |
let isMounted = true; // Flag to prevent state updates after unmount
|
29 |
|
lightrag_webui/src/features/SiteHeader.tsx
CHANGED
@@ -6,8 +6,7 @@ import { useSettingsStore } from '@/stores/settings'
|
|
6 |
import { useAuthStore } from '@/stores/state'
|
7 |
import { cn } from '@/lib/utils'
|
8 |
import { useTranslation } from 'react-i18next'
|
9 |
-
import {
|
10 |
-
|
11 |
import { ZapIcon, GithubIcon, LogOutIcon } from 'lucide-react'
|
12 |
|
13 |
interface NavigationTabProps {
|
@@ -56,12 +55,10 @@ function TabsNavigation() {
|
|
56 |
|
57 |
export default function SiteHeader() {
|
58 |
const { t } = useTranslation()
|
59 |
-
const
|
60 |
-
const { logout, isGuestMode } = useAuthStore()
|
61 |
|
62 |
const handleLogout = () => {
|
63 |
-
|
64 |
-
navigate('/login')
|
65 |
}
|
66 |
|
67 |
return (
|
|
|
6 |
import { useAuthStore } from '@/stores/state'
|
7 |
import { cn } from '@/lib/utils'
|
8 |
import { useTranslation } from 'react-i18next'
|
9 |
+
import { navigationService } from '@/services/navigation'
|
|
|
10 |
import { ZapIcon, GithubIcon, LogOutIcon } from 'lucide-react'
|
11 |
|
12 |
interface NavigationTabProps {
|
|
|
55 |
|
56 |
export default function SiteHeader() {
|
57 |
const { t } = useTranslation()
|
58 |
+
const { isGuestMode } = useAuthStore()
|
|
|
59 |
|
60 |
const handleLogout = () => {
|
61 |
+
navigationService.navigateToLogin();
|
|
|
62 |
}
|
63 |
|
64 |
return (
|
lightrag_webui/src/services/navigation.ts
CHANGED
@@ -20,32 +20,51 @@ class NavigationService {
|
|
20 |
resetAllApplicationState() {
|
21 |
console.log('Resetting all application state...');
|
22 |
|
23 |
-
// Clear authentication state
|
24 |
-
localStorage.removeItem('LIGHTRAG-API-TOKEN');
|
25 |
-
sessionStorage.clear();
|
26 |
-
useAuthStore.getState().logout();
|
27 |
-
|
28 |
// Reset graph state
|
29 |
const graphStore = useGraphStore.getState();
|
|
|
30 |
graphStore.reset();
|
31 |
graphStore.setGraphDataFetchAttempted(false);
|
32 |
graphStore.setLabelsFetchAttempted(false);
|
|
|
33 |
|
34 |
// Reset backend state
|
35 |
useBackendState.getState().clear();
|
36 |
|
37 |
// Reset retrieval history while preserving other user preferences
|
38 |
useSettingsStore.getState().setRetrievalHistory([]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
}
|
40 |
|
41 |
/**
|
42 |
-
*
|
43 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
*/
|
45 |
navigateToLogin() {
|
46 |
-
// Reset state before navigation
|
47 |
-
this.resetAllApplicationState();
|
48 |
|
|
|
|
|
|
|
49 |
if (this.navigate) {
|
50 |
this.navigate('/login');
|
51 |
}
|
|
|
20 |
resetAllApplicationState() {
|
21 |
console.log('Resetting all application state...');
|
22 |
|
|
|
|
|
|
|
|
|
|
|
23 |
// Reset graph state
|
24 |
const graphStore = useGraphStore.getState();
|
25 |
+
const sigma = graphStore.sigmaInstance;
|
26 |
graphStore.reset();
|
27 |
graphStore.setGraphDataFetchAttempted(false);
|
28 |
graphStore.setLabelsFetchAttempted(false);
|
29 |
+
graphStore.setSigmaInstance(null);
|
30 |
|
31 |
// Reset backend state
|
32 |
useBackendState.getState().clear();
|
33 |
|
34 |
// Reset retrieval history while preserving other user preferences
|
35 |
useSettingsStore.getState().setRetrievalHistory([]);
|
36 |
+
|
37 |
+
// Clear authentication state
|
38 |
+
sessionStorage.clear();
|
39 |
+
|
40 |
+
if (sigma) {
|
41 |
+
sigma.getGraph().clear();
|
42 |
+
sigma.kill();
|
43 |
+
useGraphStore.getState().setSigmaInstance(null);
|
44 |
+
}
|
45 |
}
|
46 |
|
47 |
/**
|
48 |
+
* Handle direct access to login page
|
49 |
+
* @returns true if it's a direct access, false if navigated from another page
|
50 |
+
*/
|
51 |
+
handleDirectLoginAccess() {
|
52 |
+
const isDirectAccess = !document.referrer;
|
53 |
+
if (isDirectAccess) {
|
54 |
+
this.resetAllApplicationState();
|
55 |
+
}
|
56 |
+
return isDirectAccess;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Navigate to login page and reset application state
|
61 |
+
* @param skipReset whether to skip state reset (used for direct access scenario where reset is already handled)
|
62 |
*/
|
63 |
navigateToLogin() {
|
|
|
|
|
64 |
|
65 |
+
this.resetAllApplicationState();
|
66 |
+
useAuthStore.getState().logout();
|
67 |
+
|
68 |
if (this.navigate) {
|
69 |
this.navigate('/login');
|
70 |
}
|