feat(auth): implement auto guest mode and enhance token system
- Add role-based token system with metadata support - Implement automatic guest mode for unconfigured authentication - Create new /auth-status endpoint for authentication status checking - Modify frontend to auto-detect auth status and bypass login when appropriate - Add guest mode indicator in site header for better UX This change allows users to automatically access the system without manual login when authentication is not configured, while maintaining secure authentication when credentials are properly set up.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { HashRouter as Router, Routes, Route, Navigate } from 'react-router-dom'
|
||||
import { useEffect } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useAuthStore } from '@/stores/state'
|
||||
import { getAuthStatus } from '@/api/lightrag'
|
||||
import { toast } from 'sonner'
|
||||
import { Toaster } from 'sonner'
|
||||
import App from './App'
|
||||
import LoginPage from '@/features/LoginPage'
|
||||
@@ -12,7 +14,58 @@ interface ProtectedRouteProps {
|
||||
|
||||
const ProtectedRoute = ({ children }: ProtectedRouteProps) => {
|
||||
const { isAuthenticated } = useAuthStore()
|
||||
const [isChecking, setIsChecking] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
let isMounted = true; // Flag to prevent state updates after unmount
|
||||
|
||||
// This effect will run when the component mounts
|
||||
// and will check if authentication is required
|
||||
const checkAuthStatus = async () => {
|
||||
try {
|
||||
// Skip check if already authenticated
|
||||
if (isAuthenticated) {
|
||||
if (isMounted) setIsChecking(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const status = await getAuthStatus()
|
||||
|
||||
// Only proceed if component is still mounted
|
||||
if (!isMounted) return;
|
||||
|
||||
if (!status.auth_configured && status.access_token) {
|
||||
// If auth is not configured, use the guest token
|
||||
useAuthStore.getState().login(status.access_token, true)
|
||||
if (status.message) {
|
||||
toast.info(status.message)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to check auth status:', error)
|
||||
} finally {
|
||||
// Only update state if component is still mounted
|
||||
if (isMounted) {
|
||||
setIsChecking(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Execute immediately
|
||||
checkAuthStatus()
|
||||
|
||||
// Cleanup function to prevent state updates after unmount
|
||||
return () => {
|
||||
isMounted = false;
|
||||
}
|
||||
}, [isAuthenticated])
|
||||
|
||||
// Show nothing while checking auth status
|
||||
if (isChecking) {
|
||||
return null
|
||||
}
|
||||
|
||||
// After checking, if still not authenticated, redirect to login
|
||||
if (!isAuthenticated) {
|
||||
return <Navigate to="/login" replace />
|
||||
}
|
||||
@@ -21,13 +74,65 @@ const ProtectedRoute = ({ children }: ProtectedRouteProps) => {
|
||||
}
|
||||
|
||||
const AppRouter = () => {
|
||||
// Check login at befor startup
|
||||
const [initializing, setInitializing] = useState(true)
|
||||
const { isAuthenticated } = useAuthStore()
|
||||
|
||||
// Check token validity and auth configuration on app initialization
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem('LIGHTRAG-API-TOKEN');
|
||||
if (!token) {
|
||||
useAuthStore.getState().logout();
|
||||
let isMounted = true; // Flag to prevent state updates after unmount
|
||||
|
||||
const checkAuth = async () => {
|
||||
try {
|
||||
const token = localStorage.getItem('LIGHTRAG-API-TOKEN')
|
||||
|
||||
// If we have a token, we're already authenticated
|
||||
if (token && isAuthenticated) {
|
||||
if (isMounted) setInitializing(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// If no token or not authenticated, check if auth is configured
|
||||
const status = await getAuthStatus()
|
||||
|
||||
// Only proceed if component is still mounted
|
||||
if (!isMounted) return;
|
||||
|
||||
if (!status.auth_configured && status.access_token) {
|
||||
// If auth is not configured, use the guest token
|
||||
useAuthStore.getState().login(status.access_token, true)
|
||||
if (status.message) {
|
||||
toast.info(status.message)
|
||||
}
|
||||
} else if (!token) {
|
||||
// Only logout if we don't have a token
|
||||
useAuthStore.getState().logout()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Auth initialization error:', error)
|
||||
if (isMounted && !isAuthenticated) {
|
||||
useAuthStore.getState().logout()
|
||||
}
|
||||
} finally {
|
||||
// Only update state if component is still mounted
|
||||
if (isMounted) {
|
||||
setInitializing(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Execute immediately
|
||||
checkAuth()
|
||||
|
||||
// Cleanup function to prevent state updates after unmount
|
||||
return () => {
|
||||
isMounted = false;
|
||||
}
|
||||
}, [isAuthenticated])
|
||||
|
||||
// Show nothing while initializing
|
||||
if (initializing) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider>
|
||||
|
Reference in New Issue
Block a user