From 43996656d395ebfde8efb8e6b4a243ea75cab0c4 Mon Sep 17 00:00:00 2001 From: yangdx Date: Tue, 18 Mar 2025 03:30:43 +0800 Subject: [PATCH] Fix linting --- lightrag/api/auth.py | 37 +++++++++++++---------- lightrag/api/lightrag_server.py | 25 +++++---------- lightrag/api/utils_api.py | 18 ++++++----- lightrag_webui/src/AppRouter.tsx | 22 +++++++------- lightrag_webui/src/api/lightrag.ts | 12 ++++---- lightrag_webui/src/features/LoginPage.tsx | 14 ++++----- lightrag_webui/src/locales/en.json | 4 +-- lightrag_webui/src/locales/zh.json | 4 +-- lightrag_webui/src/stores/state.ts | 24 +++++++-------- 9 files changed, 79 insertions(+), 81 deletions(-) diff --git a/lightrag/api/auth.py b/lightrag/api/auth.py index c0b22f2c..78a1da1a 100644 --- a/lightrag/api/auth.py +++ b/lightrag/api/auth.py @@ -17,18 +17,26 @@ class AuthHandler: self.secret = os.getenv("TOKEN_SECRET", "4f85ds4f56dsf46") self.algorithm = "HS256" self.expire_hours = int(os.getenv("TOKEN_EXPIRE_HOURS", 4)) - self.guest_expire_hours = int(os.getenv("GUEST_TOKEN_EXPIRE_HOURS", 2)) # Guest token default expiration time + self.guest_expire_hours = int( + os.getenv("GUEST_TOKEN_EXPIRE_HOURS", 2) + ) # Guest token default expiration time - def create_token(self, username: str, role: str = "user", custom_expire_hours: int = None, metadata: dict = None) -> str: + def create_token( + self, + username: str, + role: str = "user", + custom_expire_hours: int = None, + metadata: dict = None, + ) -> str: """ Create JWT token - + Args: username: Username role: User role, default is "user", guest is "guest" custom_expire_hours: Custom expiration time (hours), if None use default value metadata: Additional metadata - + Returns: str: Encoded JWT token """ @@ -40,29 +48,26 @@ class AuthHandler: expire_hours = self.expire_hours else: expire_hours = custom_expire_hours - + expire = datetime.utcnow() + timedelta(hours=expire_hours) - + # Create payload payload = TokenPayload( - sub=username, - exp=expire, - role=role, - metadata=metadata or {} + sub=username, exp=expire, role=role, metadata=metadata or {} ) - + return jwt.encode(payload.dict(), self.secret, algorithm=self.algorithm) def validate_token(self, token: str) -> dict: """ Validate JWT token - + Args: token: JWT token - + Returns: dict: Dictionary containing user information - + Raises: HTTPException: If token is invalid or expired """ @@ -75,13 +80,13 @@ class AuthHandler: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Token expired" ) - + # Return complete payload instead of just username return { "username": payload["sub"], "role": payload.get("role", "user"), "metadata": payload.get("metadata", {}), - "exp": expire_time + "exp": expire_time, } except jwt.PyJWTError: raise HTTPException( diff --git a/lightrag/api/lightrag_server.py b/lightrag/api/lightrag_server.py index 1fac9322..801f122e 100644 --- a/lightrag/api/lightrag_server.py +++ b/lightrag/api/lightrag_server.py @@ -350,22 +350,17 @@ def create_app(args): if not (username and password): # Authentication not configured, return guest token guest_token = auth_handler.create_token( - username="guest", - role="guest", - metadata={"auth_mode": "disabled"} + username="guest", role="guest", metadata={"auth_mode": "disabled"} ) return { "auth_configured": False, "access_token": guest_token, "token_type": "bearer", "auth_mode": "disabled", - "message": "Authentication is disabled. Using guest access." + "message": "Authentication is disabled. Using guest access.", } - - return { - "auth_configured": True, - "auth_mode": "enabled" - } + + return {"auth_configured": True, "auth_mode": "enabled"} @app.post("/login", dependencies=[Depends(optional_api_key)]) async def login(form_data: OAuth2PasswordRequestForm = Depends()): @@ -375,15 +370,13 @@ def create_app(args): if not (username and password): # Authentication not configured, return guest token guest_token = auth_handler.create_token( - username="guest", - role="guest", - metadata={"auth_mode": "disabled"} + username="guest", role="guest", metadata={"auth_mode": "disabled"} ) return { "access_token": guest_token, "token_type": "bearer", "auth_mode": "disabled", - "message": "Authentication is disabled. Using guest access." + "message": "Authentication is disabled. Using guest access.", } if form_data.username != username or form_data.password != password: @@ -393,14 +386,12 @@ def create_app(args): # Regular user login user_token = auth_handler.create_token( - username=username, - role="user", - metadata={"auth_mode": "enabled"} + username=username, role="user", metadata={"auth_mode": "enabled"} ) return { "access_token": user_token, "token_type": "bearer", - "auth_mode": "enabled" + "auth_mode": "enabled", } @app.get("/health", dependencies=[Depends(optional_api_key)]) diff --git a/lightrag/api/utils_api.py b/lightrag/api/utils_api.py index d5160acf..adf855cc 100644 --- a/lightrag/api/utils_api.py +++ b/lightrag/api/utils_api.py @@ -46,8 +46,10 @@ def get_auth_dependency(): return # Check if authentication is configured - auth_configured = bool(os.getenv("AUTH_USERNAME") and os.getenv("AUTH_PASSWORD")) - + auth_configured = bool( + os.getenv("AUTH_USERNAME") and os.getenv("AUTH_PASSWORD") + ) + # If authentication is not configured, accept any token including guest tokens if not auth_configured: if token: # If token is provided, still validate it @@ -62,22 +64,22 @@ def get_auth_dependency(): # Ignore validation errors but log them print(f"Token validation error (ignored): {str(e)}") return - + # If authentication is configured, validate the token and reject guest tokens if not token: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Token required" ) - + token_info = auth_handler.validate_token(token) - + # Reject guest tokens when authentication is configured if token_info.get("role") == "guest": raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Authentication required. Guest access not allowed when authentication is configured." + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Authentication required. Guest access not allowed when authentication is configured.", ) - + # At this point, we have a valid non-guest token return diff --git a/lightrag_webui/src/AppRouter.tsx b/lightrag_webui/src/AppRouter.tsx index f7258393..0e3c9c95 100644 --- a/lightrag_webui/src/AppRouter.tsx +++ b/lightrag_webui/src/AppRouter.tsx @@ -18,7 +18,7 @@ const ProtectedRoute = ({ children }: ProtectedRouteProps) => { 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 () => { @@ -28,12 +28,12 @@ const ProtectedRoute = ({ children }: ProtectedRouteProps) => { 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) @@ -53,7 +53,7 @@ const ProtectedRoute = ({ children }: ProtectedRouteProps) => { // Execute immediately checkAuthStatus() - + // Cleanup function to prevent state updates after unmount return () => { isMounted = false; @@ -80,23 +80,23 @@ const AppRouter = () => { // Check token validity and auth configuration on app initialization useEffect(() => { 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) @@ -122,7 +122,7 @@ const AppRouter = () => { // Execute immediately checkAuth() - + // Cleanup function to prevent state updates after unmount return () => { isMounted = false; diff --git a/lightrag_webui/src/api/lightrag.ts b/lightrag_webui/src/api/lightrag.ts index c681fa74..ed063d21 100644 --- a/lightrag_webui/src/api/lightrag.ts +++ b/lightrag_webui/src/api/lightrag.ts @@ -375,7 +375,7 @@ export const getAuthStatus = async (): Promise => { 'Accept': 'application/json' // Explicitly request JSON } }); - + // Check if response is HTML (which indicates a redirect or wrong endpoint) const contentType = response.headers['content-type'] || ''; if (contentType.includes('text/html')) { @@ -385,13 +385,13 @@ export const getAuthStatus = async (): Promise => { auth_mode: 'enabled' }; } - + // Strict validation of the response data - if (response.data && + if (response.data && typeof response.data === 'object' && 'auth_configured' in response.data && typeof response.data.auth_configured === 'boolean') { - + // For unconfigured auth, ensure we have an access token if (!response.data.auth_configured) { if (response.data.access_token && typeof response.data.access_token === 'string') { @@ -404,10 +404,10 @@ export const getAuthStatus = async (): Promise => { return response.data; } } - + // If response data is invalid but we got a response, log it console.warn('Received invalid auth status response:', response.data); - + // Default to auth configured if response is invalid return { auth_configured: true, diff --git a/lightrag_webui/src/features/LoginPage.tsx b/lightrag_webui/src/features/LoginPage.tsx index deda9818..485ed8ae 100644 --- a/lightrag_webui/src/features/LoginPage.tsx +++ b/lightrag_webui/src/features/LoginPage.tsx @@ -23,7 +23,7 @@ const LoginPage = () => { // Check if authentication is configured useEffect(() => { let isMounted = true; // Flag to prevent state updates after unmount - + const checkAuthConfig = async () => { try { // If already authenticated, redirect to home @@ -34,10 +34,10 @@ const LoginPage = () => { // Check auth status 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 and redirect login(status.access_token, true) @@ -59,7 +59,7 @@ const LoginPage = () => { // Execute immediately checkAuthConfig() - + // Cleanup function to prevent state updates after unmount return () => { isMounted = false; @@ -81,18 +81,18 @@ const LoginPage = () => { try { setLoading(true) const response = await loginToServer(username, password) - + // Check authentication mode const isGuestMode = response.auth_mode === 'disabled' login(response.access_token, isGuestMode) - + 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('/') } catch (error) { console.error('Login failed...', error) diff --git a/lightrag_webui/src/locales/en.json b/lightrag_webui/src/locales/en.json index 93dc2c6c..631331ce 100644 --- a/lightrag_webui/src/locales/en.json +++ b/lightrag_webui/src/locales/en.json @@ -29,8 +29,8 @@ "successMessage": "Login succeeded", "errorEmptyFields": "Please enter your username and password", "errorInvalidCredentials": "Login failed, please check username and password", - "authDisabled": "Authentication is disabled. Using guest access.", - "guestMode": "Guest Mode" + "authDisabled": "Authentication is disabled. Using login free mode.", + "guestMode": "Login Free" }, "documentPanel": { "clearDocuments": { diff --git a/lightrag_webui/src/locales/zh.json b/lightrag_webui/src/locales/zh.json index f6330f5e..f51501cd 100644 --- a/lightrag_webui/src/locales/zh.json +++ b/lightrag_webui/src/locales/zh.json @@ -29,8 +29,8 @@ "successMessage": "登录成功", "errorEmptyFields": "请输入您的用户名和密码", "errorInvalidCredentials": "登录失败,请检查用户名和密码", - "authDisabled": "认证已禁用,使用访客访问模式。", - "guestMode": "访客模式" + "authDisabled": "认证已禁用,使用无需登陆模式。", + "guestMode": "无需登陆" }, "documentPanel": { "clearDocuments": { diff --git a/lightrag_webui/src/stores/state.ts b/lightrag_webui/src/stores/state.ts index eb9075de..2117b003 100644 --- a/lightrag_webui/src/stores/state.ts +++ b/lightrag_webui/src/stores/state.ts @@ -73,10 +73,10 @@ const isGuestToken = (token: string): boolean => { // JWT tokens are in the format: header.payload.signature const parts = token.split('.'); if (parts.length !== 3) return false; - + // Decode the payload (second part) const payload = JSON.parse(atob(parts[1])); - + // Check if the token has a role field with value "guest" return payload.role === 'guest'; } catch (e) { @@ -91,9 +91,9 @@ const initAuthState = (): { isAuthenticated: boolean; isGuestMode: boolean } => if (!token) { return { isAuthenticated: false, isGuestMode: false }; } - - return { - isAuthenticated: true, + + return { + isAuthenticated: true, isGuestMode: isGuestToken(token) }; }; @@ -101,29 +101,29 @@ const initAuthState = (): { isAuthenticated: boolean; isGuestMode: boolean } => export const useAuthStore = create(set => { // Get initial state from localStorage const initialState = initAuthState(); - + return { isAuthenticated: initialState.isAuthenticated, showLoginModal: false, isGuestMode: initialState.isGuestMode, - + login: (token, isGuest = false) => { localStorage.setItem('LIGHTRAG-API-TOKEN', token); - set({ - isAuthenticated: true, + set({ + isAuthenticated: true, showLoginModal: false, isGuestMode: isGuest }); }, - + logout: () => { localStorage.removeItem('LIGHTRAG-API-TOKEN'); - set({ + set({ isAuthenticated: false, isGuestMode: false }); }, - + setShowLoginModal: (show) => set({ showLoginModal: show }) }; });