import { useState, useEffect, useRef } from 'react' import { useNavigate } from 'react-router-dom' import { useAuthStore } from '@/stores/state' import { loginToServer, getAuthStatus } from '@/api/lightrag' import { toast } from 'sonner' import { useTranslation } from 'react-i18next' import { Card, CardContent, CardHeader } from '@/components/ui/Card' import Input from '@/components/ui/Input' import Button from '@/components/ui/Button' import { ZapIcon } from 'lucide-react' import AppSettings from '@/components/AppSettings' const LoginPage = () => { const navigate = useNavigate() const { login, isAuthenticated } = useAuthStore() const { t } = useTranslation() const [loading, setLoading] = useState(false) const [username, setUsername] = useState('') const [password, setPassword] = useState('') const [checkingAuth, setCheckingAuth] = useState(true) const authCheckRef = useRef(false); // Prevent duplicate calls in Vite dev mode useEffect(() => { console.log('LoginPage mounted') }, []); // Check if authentication is configured, skip login if not useEffect(() => { let isMounted = true; // Flag to prevent state updates after unmount const checkAuthConfig = async () => { // Prevent duplicate calls in Vite dev mode if (authCheckRef.current) { return; } authCheckRef.current = true; try { // If already authenticated, redirect to home if (isAuthenticated) { navigate('/') return } // Check auth status const status = await getAuthStatus() // Set session flag for version check to avoid duplicate checks in App component if (status.core_version || status.api_version) { sessionStorage.setItem('VERSION_CHECKED_FROM_LOGIN', 'true'); } if (!status.auth_configured && status.access_token) { // If auth is not configured, use the guest token and redirect login(status.access_token, true, status.core_version, status.api_version) if (status.message) { toast.info(status.message) } navigate('/') return } // Only set checkingAuth to false if we need to show the login page if (isMounted) { setCheckingAuth(false); } } catch (error) { console.error('Failed to check auth configuration:', error) // Also set checkingAuth to false in case of error if (isMounted) { setCheckingAuth(false); } } // Removed finally block as we're setting checkingAuth earlier } // Execute immediately checkAuthConfig() // Cleanup function to prevent state updates after unmount return () => { isMounted = false; setCheckingAuth(false); } }, [isAuthenticated, login, navigate]) // Don't render anything while checking auth if (checkingAuth) { return null } const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() if (!username || !password) { toast.error(t('login.errorEmptyFields')) return } try { setLoading(true) const response = await loginToServer(username, password) // Check authentication mode const isGuestMode = response.auth_mode === 'disabled' login(response.access_token, isGuestMode, response.core_version, response.api_version) // Set session flag for version check if (response.core_version || response.api_version) { sessionStorage.setItem('VERSION_CHECKED_FROM_LOGIN', 'true'); } if (isGuestMode) { // Show authentication disabled notification toast.info(response.message || t('login.authDisabled', 'Authentication is disabled. Using guest access.')) } else { toast.success(t('login.successMessage')) } // Navigate to home page after successful login navigate('/') } catch (error) { console.error('Login failed...', error) toast.error(t('login.errorInvalidCredentials')) // Clear any existing auth state useAuthStore.getState().logout() // Clear local storage localStorage.removeItem('LIGHTRAG-API-TOKEN') } finally { setLoading(false) } } return (
LightRAG Logo

LightRAG

{t('login.description')}

setUsername(e.target.value)} required className="h-11 flex-1" />
setPassword(e.target.value)} required className="h-11 flex-1" />
) } export default LoginPage