yangdx
		
	commited on
		
		
					Commit 
							
							·
						
						382e628
	
1
								Parent(s):
							
							030c42e
								
Fix linting
Browse files- lightrag/api/auth.py +21 -16
 - lightrag/api/lightrag_server.py +8 -17
 - lightrag/api/utils_api.py +10 -8
 - lightrag_webui/src/AppRouter.tsx +11 -11
 - lightrag_webui/src/api/lightrag.ts +6 -6
 - lightrag_webui/src/features/LoginPage.tsx +7 -7
 - lightrag_webui/src/locales/en.json +2 -2
 - lightrag_webui/src/locales/zh.json +2 -2
 - lightrag_webui/src/stores/state.ts +12 -12
 
    	
        lightrag/api/auth.py
    CHANGED
    
    | 
         @@ -17,18 +17,26 @@ class AuthHandler: 
     | 
|
| 17 | 
         
             
                    self.secret = os.getenv("TOKEN_SECRET", "4f85ds4f56dsf46")
         
     | 
| 18 | 
         
             
                    self.algorithm = "HS256"
         
     | 
| 19 | 
         
             
                    self.expire_hours = int(os.getenv("TOKEN_EXPIRE_HOURS", 4))
         
     | 
| 20 | 
         
            -
                    self.guest_expire_hours = int( 
     | 
| 
         | 
|
| 
         | 
|
| 21 | 
         | 
| 22 | 
         
            -
                def create_token( 
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 23 | 
         
             
                    """
         
     | 
| 24 | 
         
             
                    Create JWT token
         
     | 
| 25 | 
         
            -
             
     | 
| 26 | 
         
             
                    Args:
         
     | 
| 27 | 
         
             
                        username: Username
         
     | 
| 28 | 
         
             
                        role: User role, default is "user", guest is "guest"
         
     | 
| 29 | 
         
             
                        custom_expire_hours: Custom expiration time (hours), if None use default value
         
     | 
| 30 | 
         
             
                        metadata: Additional metadata
         
     | 
| 31 | 
         
            -
             
     | 
| 32 | 
         
             
                    Returns:
         
     | 
| 33 | 
         
             
                        str: Encoded JWT token
         
     | 
| 34 | 
         
             
                    """
         
     | 
| 
         @@ -40,29 +48,26 @@ class AuthHandler: 
     | 
|
| 40 | 
         
             
                            expire_hours = self.expire_hours
         
     | 
| 41 | 
         
             
                    else:
         
     | 
| 42 | 
         
             
                        expire_hours = custom_expire_hours
         
     | 
| 43 | 
         
            -
             
     | 
| 44 | 
         
             
                    expire = datetime.utcnow() + timedelta(hours=expire_hours)
         
     | 
| 45 | 
         
            -
             
     | 
| 46 | 
         
             
                    # Create payload
         
     | 
| 47 | 
         
             
                    payload = TokenPayload(
         
     | 
| 48 | 
         
            -
                        sub=username,
         
     | 
| 49 | 
         
            -
                        exp=expire,
         
     | 
| 50 | 
         
            -
                        role=role,
         
     | 
| 51 | 
         
            -
                        metadata=metadata or {}
         
     | 
| 52 | 
         
             
                    )
         
     | 
| 53 | 
         
            -
             
     | 
| 54 | 
         
             
                    return jwt.encode(payload.dict(), self.secret, algorithm=self.algorithm)
         
     | 
| 55 | 
         | 
| 56 | 
         
             
                def validate_token(self, token: str) -> dict:
         
     | 
| 57 | 
         
             
                    """
         
     | 
| 58 | 
         
             
                    Validate JWT token
         
     | 
| 59 | 
         
            -
             
     | 
| 60 | 
         
             
                    Args:
         
     | 
| 61 | 
         
             
                        token: JWT token
         
     | 
| 62 | 
         
            -
             
     | 
| 63 | 
         
             
                    Returns:
         
     | 
| 64 | 
         
             
                        dict: Dictionary containing user information
         
     | 
| 65 | 
         
            -
             
     | 
| 66 | 
         
             
                    Raises:
         
     | 
| 67 | 
         
             
                        HTTPException: If token is invalid or expired
         
     | 
| 68 | 
         
             
                    """
         
     | 
| 
         @@ -75,13 +80,13 @@ class AuthHandler: 
     | 
|
| 75 | 
         
             
                            raise HTTPException(
         
     | 
| 76 | 
         
             
                                status_code=status.HTTP_401_UNAUTHORIZED, detail="Token expired"
         
     | 
| 77 | 
         
             
                            )
         
     | 
| 78 | 
         
            -
             
     | 
| 79 | 
         
             
                        # Return complete payload instead of just username
         
     | 
| 80 | 
         
             
                        return {
         
     | 
| 81 | 
         
             
                            "username": payload["sub"],
         
     | 
| 82 | 
         
             
                            "role": payload.get("role", "user"),
         
     | 
| 83 | 
         
             
                            "metadata": payload.get("metadata", {}),
         
     | 
| 84 | 
         
            -
                            "exp": expire_time
         
     | 
| 85 | 
         
             
                        }
         
     | 
| 86 | 
         
             
                    except jwt.PyJWTError:
         
     | 
| 87 | 
         
             
                        raise HTTPException(
         
     | 
| 
         | 
|
| 17 | 
         
             
                    self.secret = os.getenv("TOKEN_SECRET", "4f85ds4f56dsf46")
         
     | 
| 18 | 
         
             
                    self.algorithm = "HS256"
         
     | 
| 19 | 
         
             
                    self.expire_hours = int(os.getenv("TOKEN_EXPIRE_HOURS", 4))
         
     | 
| 20 | 
         
            +
                    self.guest_expire_hours = int(
         
     | 
| 21 | 
         
            +
                        os.getenv("GUEST_TOKEN_EXPIRE_HOURS", 2)
         
     | 
| 22 | 
         
            +
                    )  # Guest token default expiration time
         
     | 
| 23 | 
         | 
| 24 | 
         
            +
                def create_token(
         
     | 
| 25 | 
         
            +
                    self,
         
     | 
| 26 | 
         
            +
                    username: str,
         
     | 
| 27 | 
         
            +
                    role: str = "user",
         
     | 
| 28 | 
         
            +
                    custom_expire_hours: int = None,
         
     | 
| 29 | 
         
            +
                    metadata: dict = None,
         
     | 
| 30 | 
         
            +
                ) -> str:
         
     | 
| 31 | 
         
             
                    """
         
     | 
| 32 | 
         
             
                    Create JWT token
         
     | 
| 33 | 
         
            +
             
     | 
| 34 | 
         
             
                    Args:
         
     | 
| 35 | 
         
             
                        username: Username
         
     | 
| 36 | 
         
             
                        role: User role, default is "user", guest is "guest"
         
     | 
| 37 | 
         
             
                        custom_expire_hours: Custom expiration time (hours), if None use default value
         
     | 
| 38 | 
         
             
                        metadata: Additional metadata
         
     | 
| 39 | 
         
            +
             
     | 
| 40 | 
         
             
                    Returns:
         
     | 
| 41 | 
         
             
                        str: Encoded JWT token
         
     | 
| 42 | 
         
             
                    """
         
     | 
| 
         | 
|
| 48 | 
         
             
                            expire_hours = self.expire_hours
         
     | 
| 49 | 
         
             
                    else:
         
     | 
| 50 | 
         
             
                        expire_hours = custom_expire_hours
         
     | 
| 51 | 
         
            +
             
     | 
| 52 | 
         
             
                    expire = datetime.utcnow() + timedelta(hours=expire_hours)
         
     | 
| 53 | 
         
            +
             
     | 
| 54 | 
         
             
                    # Create payload
         
     | 
| 55 | 
         
             
                    payload = TokenPayload(
         
     | 
| 56 | 
         
            +
                        sub=username, exp=expire, role=role, metadata=metadata or {}
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 57 | 
         
             
                    )
         
     | 
| 58 | 
         
            +
             
     | 
| 59 | 
         
             
                    return jwt.encode(payload.dict(), self.secret, algorithm=self.algorithm)
         
     | 
| 60 | 
         | 
| 61 | 
         
             
                def validate_token(self, token: str) -> dict:
         
     | 
| 62 | 
         
             
                    """
         
     | 
| 63 | 
         
             
                    Validate JWT token
         
     | 
| 64 | 
         
            +
             
     | 
| 65 | 
         
             
                    Args:
         
     | 
| 66 | 
         
             
                        token: JWT token
         
     | 
| 67 | 
         
            +
             
     | 
| 68 | 
         
             
                    Returns:
         
     | 
| 69 | 
         
             
                        dict: Dictionary containing user information
         
     | 
| 70 | 
         
            +
             
     | 
| 71 | 
         
             
                    Raises:
         
     | 
| 72 | 
         
             
                        HTTPException: If token is invalid or expired
         
     | 
| 73 | 
         
             
                    """
         
     | 
| 
         | 
|
| 80 | 
         
             
                            raise HTTPException(
         
     | 
| 81 | 
         
             
                                status_code=status.HTTP_401_UNAUTHORIZED, detail="Token expired"
         
     | 
| 82 | 
         
             
                            )
         
     | 
| 83 | 
         
            +
             
     | 
| 84 | 
         
             
                        # Return complete payload instead of just username
         
     | 
| 85 | 
         
             
                        return {
         
     | 
| 86 | 
         
             
                            "username": payload["sub"],
         
     | 
| 87 | 
         
             
                            "role": payload.get("role", "user"),
         
     | 
| 88 | 
         
             
                            "metadata": payload.get("metadata", {}),
         
     | 
| 89 | 
         
            +
                            "exp": expire_time,
         
     | 
| 90 | 
         
             
                        }
         
     | 
| 91 | 
         
             
                    except jwt.PyJWTError:
         
     | 
| 92 | 
         
             
                        raise HTTPException(
         
     | 
    	
        lightrag/api/lightrag_server.py
    CHANGED
    
    | 
         @@ -350,22 +350,17 @@ def create_app(args): 
     | 
|
| 350 | 
         
             
                    if not (username and password):
         
     | 
| 351 | 
         
             
                        # Authentication not configured, return guest token
         
     | 
| 352 | 
         
             
                        guest_token = auth_handler.create_token(
         
     | 
| 353 | 
         
            -
                            username="guest",
         
     | 
| 354 | 
         
            -
                            role="guest",
         
     | 
| 355 | 
         
            -
                            metadata={"auth_mode": "disabled"}
         
     | 
| 356 | 
         
             
                        )
         
     | 
| 357 | 
         
             
                        return {
         
     | 
| 358 | 
         
             
                            "auth_configured": False,
         
     | 
| 359 | 
         
             
                            "access_token": guest_token,
         
     | 
| 360 | 
         
             
                            "token_type": "bearer",
         
     | 
| 361 | 
         
             
                            "auth_mode": "disabled",
         
     | 
| 362 | 
         
            -
                            "message": "Authentication is disabled. Using guest access."
         
     | 
| 363 | 
         
             
                        }
         
     | 
| 364 | 
         
            -
             
     | 
| 365 | 
         
            -
                    return {
         
     | 
| 366 | 
         
            -
                        "auth_configured": True,
         
     | 
| 367 | 
         
            -
                        "auth_mode": "enabled"
         
     | 
| 368 | 
         
            -
                    }
         
     | 
| 369 | 
         | 
| 370 | 
         
             
                @app.post("/login", dependencies=[Depends(optional_api_key)])
         
     | 
| 371 | 
         
             
                async def login(form_data: OAuth2PasswordRequestForm = Depends()):
         
     | 
| 
         @@ -375,15 +370,13 @@ def create_app(args): 
     | 
|
| 375 | 
         
             
                    if not (username and password):
         
     | 
| 376 | 
         
             
                        # Authentication not configured, return guest token
         
     | 
| 377 | 
         
             
                        guest_token = auth_handler.create_token(
         
     | 
| 378 | 
         
            -
                            username="guest",
         
     | 
| 379 | 
         
            -
                            role="guest",
         
     | 
| 380 | 
         
            -
                            metadata={"auth_mode": "disabled"}
         
     | 
| 381 | 
         
             
                        )
         
     | 
| 382 | 
         
             
                        return {
         
     | 
| 383 | 
         
             
                            "access_token": guest_token,
         
     | 
| 384 | 
         
             
                            "token_type": "bearer",
         
     | 
| 385 | 
         
             
                            "auth_mode": "disabled",
         
     | 
| 386 | 
         
            -
                            "message": "Authentication is disabled. Using guest access."
         
     | 
| 387 | 
         
             
                        }
         
     | 
| 388 | 
         | 
| 389 | 
         
             
                    if form_data.username != username or form_data.password != password:
         
     | 
| 
         @@ -393,14 +386,12 @@ def create_app(args): 
     | 
|
| 393 | 
         | 
| 394 | 
         
             
                    # Regular user login
         
     | 
| 395 | 
         
             
                    user_token = auth_handler.create_token(
         
     | 
| 396 | 
         
            -
                        username=username,
         
     | 
| 397 | 
         
            -
                        role="user",
         
     | 
| 398 | 
         
            -
                        metadata={"auth_mode": "enabled"}
         
     | 
| 399 | 
         
             
                    )
         
     | 
| 400 | 
         
             
                    return {
         
     | 
| 401 | 
         
             
                        "access_token": user_token,
         
     | 
| 402 | 
         
             
                        "token_type": "bearer",
         
     | 
| 403 | 
         
            -
                        "auth_mode": "enabled"
         
     | 
| 404 | 
         
             
                    }
         
     | 
| 405 | 
         | 
| 406 | 
         
             
                @app.get("/health", dependencies=[Depends(optional_api_key)])
         
     | 
| 
         | 
|
| 350 | 
         
             
                    if not (username and password):
         
     | 
| 351 | 
         
             
                        # Authentication not configured, return guest token
         
     | 
| 352 | 
         
             
                        guest_token = auth_handler.create_token(
         
     | 
| 353 | 
         
            +
                            username="guest", role="guest", metadata={"auth_mode": "disabled"}
         
     | 
| 
         | 
|
| 
         | 
|
| 354 | 
         
             
                        )
         
     | 
| 355 | 
         
             
                        return {
         
     | 
| 356 | 
         
             
                            "auth_configured": False,
         
     | 
| 357 | 
         
             
                            "access_token": guest_token,
         
     | 
| 358 | 
         
             
                            "token_type": "bearer",
         
     | 
| 359 | 
         
             
                            "auth_mode": "disabled",
         
     | 
| 360 | 
         
            +
                            "message": "Authentication is disabled. Using guest access.",
         
     | 
| 361 | 
         
             
                        }
         
     | 
| 362 | 
         
            +
             
     | 
| 363 | 
         
            +
                    return {"auth_configured": True, "auth_mode": "enabled"}
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 364 | 
         | 
| 365 | 
         
             
                @app.post("/login", dependencies=[Depends(optional_api_key)])
         
     | 
| 366 | 
         
             
                async def login(form_data: OAuth2PasswordRequestForm = Depends()):
         
     | 
| 
         | 
|
| 370 | 
         
             
                    if not (username and password):
         
     | 
| 371 | 
         
             
                        # Authentication not configured, return guest token
         
     | 
| 372 | 
         
             
                        guest_token = auth_handler.create_token(
         
     | 
| 373 | 
         
            +
                            username="guest", role="guest", metadata={"auth_mode": "disabled"}
         
     | 
| 
         | 
|
| 
         | 
|
| 374 | 
         
             
                        )
         
     | 
| 375 | 
         
             
                        return {
         
     | 
| 376 | 
         
             
                            "access_token": guest_token,
         
     | 
| 377 | 
         
             
                            "token_type": "bearer",
         
     | 
| 378 | 
         
             
                            "auth_mode": "disabled",
         
     | 
| 379 | 
         
            +
                            "message": "Authentication is disabled. Using guest access.",
         
     | 
| 380 | 
         
             
                        }
         
     | 
| 381 | 
         | 
| 382 | 
         
             
                    if form_data.username != username or form_data.password != password:
         
     | 
| 
         | 
|
| 386 | 
         | 
| 387 | 
         
             
                    # Regular user login
         
     | 
| 388 | 
         
             
                    user_token = auth_handler.create_token(
         
     | 
| 389 | 
         
            +
                        username=username, role="user", metadata={"auth_mode": "enabled"}
         
     | 
| 
         | 
|
| 
         | 
|
| 390 | 
         
             
                    )
         
     | 
| 391 | 
         
             
                    return {
         
     | 
| 392 | 
         
             
                        "access_token": user_token,
         
     | 
| 393 | 
         
             
                        "token_type": "bearer",
         
     | 
| 394 | 
         
            +
                        "auth_mode": "enabled",
         
     | 
| 395 | 
         
             
                    }
         
     | 
| 396 | 
         | 
| 397 | 
         
             
                @app.get("/health", dependencies=[Depends(optional_api_key)])
         
     | 
    	
        lightrag/api/utils_api.py
    CHANGED
    
    | 
         @@ -46,8 +46,10 @@ def get_auth_dependency(): 
     | 
|
| 46 | 
         
             
                        return
         
     | 
| 47 | 
         | 
| 48 | 
         
             
                    # Check if authentication is configured
         
     | 
| 49 | 
         
            -
                    auth_configured = bool( 
     | 
| 50 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 51 | 
         
             
                    # If authentication is not configured, accept any token including guest tokens
         
     | 
| 52 | 
         
             
                    if not auth_configured:
         
     | 
| 53 | 
         
             
                        if token:  # If token is provided, still validate it
         
     | 
| 
         @@ -62,22 +64,22 @@ def get_auth_dependency(): 
     | 
|
| 62 | 
         
             
                                # Ignore validation errors but log them
         
     | 
| 63 | 
         
             
                                print(f"Token validation error (ignored): {str(e)}")
         
     | 
| 64 | 
         
             
                        return
         
     | 
| 65 | 
         
            -
             
     | 
| 66 | 
         
             
                    # If authentication is configured, validate the token and reject guest tokens
         
     | 
| 67 | 
         
             
                    if not token:
         
     | 
| 68 | 
         
             
                        raise HTTPException(
         
     | 
| 69 | 
         
             
                            status_code=status.HTTP_401_UNAUTHORIZED, detail="Token required"
         
     | 
| 70 | 
         
             
                        )
         
     | 
| 71 | 
         
            -
             
     | 
| 72 | 
         
             
                    token_info = auth_handler.validate_token(token)
         
     | 
| 73 | 
         
            -
             
     | 
| 74 | 
         
             
                    # Reject guest tokens when authentication is configured
         
     | 
| 75 | 
         
             
                    if token_info.get("role") == "guest":
         
     | 
| 76 | 
         
             
                        raise HTTPException(
         
     | 
| 77 | 
         
            -
                            status_code=status.HTTP_401_UNAUTHORIZED, 
     | 
| 78 | 
         
            -
                            detail="Authentication required. Guest access not allowed when authentication is configured."
         
     | 
| 79 | 
         
             
                        )
         
     | 
| 80 | 
         
            -
             
     | 
| 81 | 
         
             
                    # At this point, we have a valid non-guest token
         
     | 
| 82 | 
         
             
                    return
         
     | 
| 83 | 
         | 
| 
         | 
|
| 46 | 
         
             
                        return
         
     | 
| 47 | 
         | 
| 48 | 
         
             
                    # Check if authentication is configured
         
     | 
| 49 | 
         
            +
                    auth_configured = bool(
         
     | 
| 50 | 
         
            +
                        os.getenv("AUTH_USERNAME") and os.getenv("AUTH_PASSWORD")
         
     | 
| 51 | 
         
            +
                    )
         
     | 
| 52 | 
         
            +
             
     | 
| 53 | 
         
             
                    # If authentication is not configured, accept any token including guest tokens
         
     | 
| 54 | 
         
             
                    if not auth_configured:
         
     | 
| 55 | 
         
             
                        if token:  # If token is provided, still validate it
         
     | 
| 
         | 
|
| 64 | 
         
             
                                # Ignore validation errors but log them
         
     | 
| 65 | 
         
             
                                print(f"Token validation error (ignored): {str(e)}")
         
     | 
| 66 | 
         
             
                        return
         
     | 
| 67 | 
         
            +
             
     | 
| 68 | 
         
             
                    # If authentication is configured, validate the token and reject guest tokens
         
     | 
| 69 | 
         
             
                    if not token:
         
     | 
| 70 | 
         
             
                        raise HTTPException(
         
     | 
| 71 | 
         
             
                            status_code=status.HTTP_401_UNAUTHORIZED, detail="Token required"
         
     | 
| 72 | 
         
             
                        )
         
     | 
| 73 | 
         
            +
             
     | 
| 74 | 
         
             
                    token_info = auth_handler.validate_token(token)
         
     | 
| 75 | 
         
            +
             
     | 
| 76 | 
         
             
                    # Reject guest tokens when authentication is configured
         
     | 
| 77 | 
         
             
                    if token_info.get("role") == "guest":
         
     | 
| 78 | 
         
             
                        raise HTTPException(
         
     | 
| 79 | 
         
            +
                            status_code=status.HTTP_401_UNAUTHORIZED,
         
     | 
| 80 | 
         
            +
                            detail="Authentication required. Guest access not allowed when authentication is configured.",
         
     | 
| 81 | 
         
             
                        )
         
     | 
| 82 | 
         
            +
             
     | 
| 83 | 
         
             
                    # At this point, we have a valid non-guest token
         
     | 
| 84 | 
         
             
                    return
         
     | 
| 85 | 
         | 
    	
        lightrag_webui/src/AppRouter.tsx
    CHANGED
    
    | 
         @@ -18,7 +18,7 @@ const ProtectedRoute = ({ children }: ProtectedRouteProps) => { 
     | 
|
| 18 | 
         | 
| 19 | 
         
             
              useEffect(() => {
         
     | 
| 20 | 
         
             
                let isMounted = true; // Flag to prevent state updates after unmount
         
     | 
| 21 | 
         
            -
             
     | 
| 22 | 
         
             
                // This effect will run when the component mounts
         
     | 
| 23 | 
         
             
                // and will check if authentication is required
         
     | 
| 24 | 
         
             
                const checkAuthStatus = async () => {
         
     | 
| 
         @@ -28,12 +28,12 @@ const ProtectedRoute = ({ children }: ProtectedRouteProps) => { 
     | 
|
| 28 | 
         
             
                      if (isMounted) setIsChecking(false);
         
     | 
| 29 | 
         
             
                      return;
         
     | 
| 30 | 
         
             
                    }
         
     | 
| 31 | 
         
            -
             
     | 
| 32 | 
         
             
                    const status = await getAuthStatus()
         
     | 
| 33 | 
         
            -
             
     | 
| 34 | 
         
             
                    // Only proceed if component is still mounted
         
     | 
| 35 | 
         
             
                    if (!isMounted) return;
         
     | 
| 36 | 
         
            -
             
     | 
| 37 | 
         
             
                    if (!status.auth_configured && status.access_token) {
         
     | 
| 38 | 
         
             
                      // If auth is not configured, use the guest token
         
     | 
| 39 | 
         
             
                      useAuthStore.getState().login(status.access_token, true)
         
     | 
| 
         @@ -53,7 +53,7 @@ const ProtectedRoute = ({ children }: ProtectedRouteProps) => { 
     | 
|
| 53 | 
         | 
| 54 | 
         
             
                // Execute immediately
         
     | 
| 55 | 
         
             
                checkAuthStatus()
         
     | 
| 56 | 
         
            -
             
     | 
| 57 | 
         
             
                // Cleanup function to prevent state updates after unmount
         
     | 
| 58 | 
         
             
                return () => {
         
     | 
| 59 | 
         
             
                  isMounted = false;
         
     | 
| 
         @@ -80,23 +80,23 @@ const AppRouter = () => { 
     | 
|
| 80 | 
         
             
              // Check token validity and auth configuration on app initialization
         
     | 
| 81 | 
         
             
              useEffect(() => {
         
     | 
| 82 | 
         
             
                let isMounted = true; // Flag to prevent state updates after unmount
         
     | 
| 83 | 
         
            -
             
     | 
| 84 | 
         
             
                const checkAuth = async () => {
         
     | 
| 85 | 
         
             
                  try {
         
     | 
| 86 | 
         
             
                    const token = localStorage.getItem('LIGHTRAG-API-TOKEN')
         
     | 
| 87 | 
         
            -
             
     | 
| 88 | 
         
             
                    // If we have a token, we're already authenticated
         
     | 
| 89 | 
         
             
                    if (token && isAuthenticated) {
         
     | 
| 90 | 
         
             
                      if (isMounted) setInitializing(false);
         
     | 
| 91 | 
         
             
                      return;
         
     | 
| 92 | 
         
             
                    }
         
     | 
| 93 | 
         
            -
             
     | 
| 94 | 
         
             
                    // If no token or not authenticated, check if auth is configured
         
     | 
| 95 | 
         
             
                    const status = await getAuthStatus()
         
     | 
| 96 | 
         
            -
             
     | 
| 97 | 
         
             
                    // Only proceed if component is still mounted
         
     | 
| 98 | 
         
             
                    if (!isMounted) return;
         
     | 
| 99 | 
         
            -
             
     | 
| 100 | 
         
             
                    if (!status.auth_configured && status.access_token) {
         
     | 
| 101 | 
         
             
                      // If auth is not configured, use the guest token
         
     | 
| 102 | 
         
             
                      useAuthStore.getState().login(status.access_token, true)
         
     | 
| 
         @@ -122,7 +122,7 @@ const AppRouter = () => { 
     | 
|
| 122 | 
         | 
| 123 | 
         
             
                // Execute immediately
         
     | 
| 124 | 
         
             
                checkAuth()
         
     | 
| 125 | 
         
            -
             
     | 
| 126 | 
         
             
                // Cleanup function to prevent state updates after unmount
         
     | 
| 127 | 
         
             
                return () => {
         
     | 
| 128 | 
         
             
                  isMounted = false;
         
     | 
| 
         | 
|
| 18 | 
         | 
| 19 | 
         
             
              useEffect(() => {
         
     | 
| 20 | 
         
             
                let isMounted = true; // Flag to prevent state updates after unmount
         
     | 
| 21 | 
         
            +
             
     | 
| 22 | 
         
             
                // This effect will run when the component mounts
         
     | 
| 23 | 
         
             
                // and will check if authentication is required
         
     | 
| 24 | 
         
             
                const checkAuthStatus = async () => {
         
     | 
| 
         | 
|
| 28 | 
         
             
                      if (isMounted) setIsChecking(false);
         
     | 
| 29 | 
         
             
                      return;
         
     | 
| 30 | 
         
             
                    }
         
     | 
| 31 | 
         
            +
             
     | 
| 32 | 
         
             
                    const status = await getAuthStatus()
         
     | 
| 33 | 
         
            +
             
     | 
| 34 | 
         
             
                    // Only proceed if component is still mounted
         
     | 
| 35 | 
         
             
                    if (!isMounted) return;
         
     | 
| 36 | 
         
            +
             
     | 
| 37 | 
         
             
                    if (!status.auth_configured && status.access_token) {
         
     | 
| 38 | 
         
             
                      // If auth is not configured, use the guest token
         
     | 
| 39 | 
         
             
                      useAuthStore.getState().login(status.access_token, true)
         
     | 
| 
         | 
|
| 53 | 
         | 
| 54 | 
         
             
                // Execute immediately
         
     | 
| 55 | 
         
             
                checkAuthStatus()
         
     | 
| 56 | 
         
            +
             
     | 
| 57 | 
         
             
                // Cleanup function to prevent state updates after unmount
         
     | 
| 58 | 
         
             
                return () => {
         
     | 
| 59 | 
         
             
                  isMounted = false;
         
     | 
| 
         | 
|
| 80 | 
         
             
              // Check token validity and auth configuration on app initialization
         
     | 
| 81 | 
         
             
              useEffect(() => {
         
     | 
| 82 | 
         
             
                let isMounted = true; // Flag to prevent state updates after unmount
         
     | 
| 83 | 
         
            +
             
     | 
| 84 | 
         
             
                const checkAuth = async () => {
         
     | 
| 85 | 
         
             
                  try {
         
     | 
| 86 | 
         
             
                    const token = localStorage.getItem('LIGHTRAG-API-TOKEN')
         
     | 
| 87 | 
         
            +
             
     | 
| 88 | 
         
             
                    // If we have a token, we're already authenticated
         
     | 
| 89 | 
         
             
                    if (token && isAuthenticated) {
         
     | 
| 90 | 
         
             
                      if (isMounted) setInitializing(false);
         
     | 
| 91 | 
         
             
                      return;
         
     | 
| 92 | 
         
             
                    }
         
     | 
| 93 | 
         
            +
             
     | 
| 94 | 
         
             
                    // If no token or not authenticated, check if auth is configured
         
     | 
| 95 | 
         
             
                    const status = await getAuthStatus()
         
     | 
| 96 | 
         
            +
             
     | 
| 97 | 
         
             
                    // Only proceed if component is still mounted
         
     | 
| 98 | 
         
             
                    if (!isMounted) return;
         
     | 
| 99 | 
         
            +
             
     | 
| 100 | 
         
             
                    if (!status.auth_configured && status.access_token) {
         
     | 
| 101 | 
         
             
                      // If auth is not configured, use the guest token
         
     | 
| 102 | 
         
             
                      useAuthStore.getState().login(status.access_token, true)
         
     | 
| 
         | 
|
| 122 | 
         | 
| 123 | 
         
             
                // Execute immediately
         
     | 
| 124 | 
         
             
                checkAuth()
         
     | 
| 125 | 
         
            +
             
     | 
| 126 | 
         
             
                // Cleanup function to prevent state updates after unmount
         
     | 
| 127 | 
         
             
                return () => {
         
     | 
| 128 | 
         
             
                  isMounted = false;
         
     | 
    	
        lightrag_webui/src/api/lightrag.ts
    CHANGED
    
    | 
         @@ -375,7 +375,7 @@ export const getAuthStatus = async (): Promise<AuthStatusResponse> => { 
     | 
|
| 375 | 
         
             
                    'Accept': 'application/json' // Explicitly request JSON
         
     | 
| 376 | 
         
             
                  }
         
     | 
| 377 | 
         
             
                });
         
     | 
| 378 | 
         
            -
             
     | 
| 379 | 
         
             
                // Check if response is HTML (which indicates a redirect or wrong endpoint)
         
     | 
| 380 | 
         
             
                const contentType = response.headers['content-type'] || '';
         
     | 
| 381 | 
         
             
                if (contentType.includes('text/html')) {
         
     | 
| 
         @@ -385,13 +385,13 @@ export const getAuthStatus = async (): Promise<AuthStatusResponse> => { 
     | 
|
| 385 | 
         
             
                    auth_mode: 'enabled'
         
     | 
| 386 | 
         
             
                  };
         
     | 
| 387 | 
         
             
                }
         
     | 
| 388 | 
         
            -
             
     | 
| 389 | 
         
             
                // Strict validation of the response data
         
     | 
| 390 | 
         
            -
                if (response.data && 
     | 
| 391 | 
         
             
                    typeof response.data === 'object' &&
         
     | 
| 392 | 
         
             
                    'auth_configured' in response.data &&
         
     | 
| 393 | 
         
             
                    typeof response.data.auth_configured === 'boolean') {
         
     | 
| 394 | 
         
            -
             
     | 
| 395 | 
         
             
                  // For unconfigured auth, ensure we have an access token
         
     | 
| 396 | 
         
             
                  if (!response.data.auth_configured) {
         
     | 
| 397 | 
         
             
                    if (response.data.access_token && typeof response.data.access_token === 'string') {
         
     | 
| 
         @@ -404,10 +404,10 @@ export const getAuthStatus = async (): Promise<AuthStatusResponse> => { 
     | 
|
| 404 | 
         
             
                    return response.data;
         
     | 
| 405 | 
         
             
                  }
         
     | 
| 406 | 
         
             
                }
         
     | 
| 407 | 
         
            -
             
     | 
| 408 | 
         
             
                // If response data is invalid but we got a response, log it
         
     | 
| 409 | 
         
             
                console.warn('Received invalid auth status response:', response.data);
         
     | 
| 410 | 
         
            -
             
     | 
| 411 | 
         
             
                // Default to auth configured if response is invalid
         
     | 
| 412 | 
         
             
                return {
         
     | 
| 413 | 
         
             
                  auth_configured: true,
         
     | 
| 
         | 
|
| 375 | 
         
             
                    'Accept': 'application/json' // Explicitly request JSON
         
     | 
| 376 | 
         
             
                  }
         
     | 
| 377 | 
         
             
                });
         
     | 
| 378 | 
         
            +
             
     | 
| 379 | 
         
             
                // Check if response is HTML (which indicates a redirect or wrong endpoint)
         
     | 
| 380 | 
         
             
                const contentType = response.headers['content-type'] || '';
         
     | 
| 381 | 
         
             
                if (contentType.includes('text/html')) {
         
     | 
| 
         | 
|
| 385 | 
         
             
                    auth_mode: 'enabled'
         
     | 
| 386 | 
         
             
                  };
         
     | 
| 387 | 
         
             
                }
         
     | 
| 388 | 
         
            +
             
     | 
| 389 | 
         
             
                // Strict validation of the response data
         
     | 
| 390 | 
         
            +
                if (response.data &&
         
     | 
| 391 | 
         
             
                    typeof response.data === 'object' &&
         
     | 
| 392 | 
         
             
                    'auth_configured' in response.data &&
         
     | 
| 393 | 
         
             
                    typeof response.data.auth_configured === 'boolean') {
         
     | 
| 394 | 
         
            +
             
     | 
| 395 | 
         
             
                  // For unconfigured auth, ensure we have an access token
         
     | 
| 396 | 
         
             
                  if (!response.data.auth_configured) {
         
     | 
| 397 | 
         
             
                    if (response.data.access_token && typeof response.data.access_token === 'string') {
         
     | 
| 
         | 
|
| 404 | 
         
             
                    return response.data;
         
     | 
| 405 | 
         
             
                  }
         
     | 
| 406 | 
         
             
                }
         
     | 
| 407 | 
         
            +
             
     | 
| 408 | 
         
             
                // If response data is invalid but we got a response, log it
         
     | 
| 409 | 
         
             
                console.warn('Received invalid auth status response:', response.data);
         
     | 
| 410 | 
         
            +
             
     | 
| 411 | 
         
             
                // Default to auth configured if response is invalid
         
     | 
| 412 | 
         
             
                return {
         
     | 
| 413 | 
         
             
                  auth_configured: true,
         
     | 
    	
        lightrag_webui/src/features/LoginPage.tsx
    CHANGED
    
    | 
         @@ -23,7 +23,7 @@ const LoginPage = () => { 
     | 
|
| 23 | 
         
             
              // Check if authentication is configured
         
     | 
| 24 | 
         
             
              useEffect(() => {
         
     | 
| 25 | 
         
             
                let isMounted = true; // Flag to prevent state updates after unmount
         
     | 
| 26 | 
         
            -
             
     | 
| 27 | 
         
             
                const checkAuthConfig = async () => {
         
     | 
| 28 | 
         
             
                  try {
         
     | 
| 29 | 
         
             
                    // If already authenticated, redirect to home
         
     | 
| 
         @@ -34,10 +34,10 @@ const LoginPage = () => { 
     | 
|
| 34 | 
         | 
| 35 | 
         
             
                    // Check auth status
         
     | 
| 36 | 
         
             
                    const status = await getAuthStatus()
         
     | 
| 37 | 
         
            -
             
     | 
| 38 | 
         
             
                    // Only proceed if component is still mounted
         
     | 
| 39 | 
         
             
                    if (!isMounted) return;
         
     | 
| 40 | 
         
            -
             
     | 
| 41 | 
         
             
                    if (!status.auth_configured && status.access_token) {
         
     | 
| 42 | 
         
             
                      // If auth is not configured, use the guest token and redirect
         
     | 
| 43 | 
         
             
                      login(status.access_token, true)
         
     | 
| 
         @@ -59,7 +59,7 @@ const LoginPage = () => { 
     | 
|
| 59 | 
         | 
| 60 | 
         
             
                // Execute immediately
         
     | 
| 61 | 
         
             
                checkAuthConfig()
         
     | 
| 62 | 
         
            -
             
     | 
| 63 | 
         
             
                // Cleanup function to prevent state updates after unmount
         
     | 
| 64 | 
         
             
                return () => {
         
     | 
| 65 | 
         
             
                  isMounted = false;
         
     | 
| 
         @@ -81,18 +81,18 @@ const LoginPage = () => { 
     | 
|
| 81 | 
         
             
                try {
         
     | 
| 82 | 
         
             
                  setLoading(true)
         
     | 
| 83 | 
         
             
                  const response = await loginToServer(username, password)
         
     | 
| 84 | 
         
            -
             
     | 
| 85 | 
         
             
                  // Check authentication mode
         
     | 
| 86 | 
         
             
                  const isGuestMode = response.auth_mode === 'disabled'
         
     | 
| 87 | 
         
             
                  login(response.access_token, isGuestMode)
         
     | 
| 88 | 
         
            -
             
     | 
| 89 | 
         
             
                  if (isGuestMode) {
         
     | 
| 90 | 
         
             
                    // Show authentication disabled notification
         
     | 
| 91 | 
         
             
                    toast.info(response.message || t('login.authDisabled', 'Authentication is disabled. Using guest access.'))
         
     | 
| 92 | 
         
             
                  } else {
         
     | 
| 93 | 
         
             
                    toast.success(t('login.successMessage'))
         
     | 
| 94 | 
         
             
                  }
         
     | 
| 95 | 
         
            -
             
     | 
| 96 | 
         
             
                  navigate('/')
         
     | 
| 97 | 
         
             
                } catch (error) {
         
     | 
| 98 | 
         
             
                  console.error('Login failed...', error)
         
     | 
| 
         | 
|
| 23 | 
         
             
              // Check if authentication is configured
         
     | 
| 24 | 
         
             
              useEffect(() => {
         
     | 
| 25 | 
         
             
                let isMounted = true; // Flag to prevent state updates after unmount
         
     | 
| 26 | 
         
            +
             
     | 
| 27 | 
         
             
                const checkAuthConfig = async () => {
         
     | 
| 28 | 
         
             
                  try {
         
     | 
| 29 | 
         
             
                    // If already authenticated, redirect to home
         
     | 
| 
         | 
|
| 34 | 
         | 
| 35 | 
         
             
                    // Check auth status
         
     | 
| 36 | 
         
             
                    const status = await getAuthStatus()
         
     | 
| 37 | 
         
            +
             
     | 
| 38 | 
         
             
                    // Only proceed if component is still mounted
         
     | 
| 39 | 
         
             
                    if (!isMounted) return;
         
     | 
| 40 | 
         
            +
             
     | 
| 41 | 
         
             
                    if (!status.auth_configured && status.access_token) {
         
     | 
| 42 | 
         
             
                      // If auth is not configured, use the guest token and redirect
         
     | 
| 43 | 
         
             
                      login(status.access_token, true)
         
     | 
| 
         | 
|
| 59 | 
         | 
| 60 | 
         
             
                // Execute immediately
         
     | 
| 61 | 
         
             
                checkAuthConfig()
         
     | 
| 62 | 
         
            +
             
     | 
| 63 | 
         
             
                // Cleanup function to prevent state updates after unmount
         
     | 
| 64 | 
         
             
                return () => {
         
     | 
| 65 | 
         
             
                  isMounted = false;
         
     | 
| 
         | 
|
| 81 | 
         
             
                try {
         
     | 
| 82 | 
         
             
                  setLoading(true)
         
     | 
| 83 | 
         
             
                  const response = await loginToServer(username, password)
         
     | 
| 84 | 
         
            +
             
     | 
| 85 | 
         
             
                  // Check authentication mode
         
     | 
| 86 | 
         
             
                  const isGuestMode = response.auth_mode === 'disabled'
         
     | 
| 87 | 
         
             
                  login(response.access_token, isGuestMode)
         
     | 
| 88 | 
         
            +
             
     | 
| 89 | 
         
             
                  if (isGuestMode) {
         
     | 
| 90 | 
         
             
                    // Show authentication disabled notification
         
     | 
| 91 | 
         
             
                    toast.info(response.message || t('login.authDisabled', 'Authentication is disabled. Using guest access.'))
         
     | 
| 92 | 
         
             
                  } else {
         
     | 
| 93 | 
         
             
                    toast.success(t('login.successMessage'))
         
     | 
| 94 | 
         
             
                  }
         
     | 
| 95 | 
         
            +
             
     | 
| 96 | 
         
             
                  navigate('/')
         
     | 
| 97 | 
         
             
                } catch (error) {
         
     | 
| 98 | 
         
             
                  console.error('Login failed...', error)
         
     | 
    	
        lightrag_webui/src/locales/en.json
    CHANGED
    
    | 
         @@ -29,8 +29,8 @@ 
     | 
|
| 29 | 
         
             
                "successMessage": "Login succeeded",
         
     | 
| 30 | 
         
             
                "errorEmptyFields": "Please enter your username and password",
         
     | 
| 31 | 
         
             
                "errorInvalidCredentials": "Login failed, please check username and password",
         
     | 
| 32 | 
         
            -
                "authDisabled": "Authentication is disabled. Using  
     | 
| 33 | 
         
            -
                "guestMode": " 
     | 
| 34 | 
         
             
              },
         
     | 
| 35 | 
         
             
              "documentPanel": {
         
     | 
| 36 | 
         
             
                "clearDocuments": {
         
     | 
| 
         | 
|
| 29 | 
         
             
                "successMessage": "Login succeeded",
         
     | 
| 30 | 
         
             
                "errorEmptyFields": "Please enter your username and password",
         
     | 
| 31 | 
         
             
                "errorInvalidCredentials": "Login failed, please check username and password",
         
     | 
| 32 | 
         
            +
                "authDisabled": "Authentication is disabled. Using login free mode.",
         
     | 
| 33 | 
         
            +
                "guestMode": "Login Free"
         
     | 
| 34 | 
         
             
              },
         
     | 
| 35 | 
         
             
              "documentPanel": {
         
     | 
| 36 | 
         
             
                "clearDocuments": {
         
     | 
    	
        lightrag_webui/src/locales/zh.json
    CHANGED
    
    | 
         @@ -29,8 +29,8 @@ 
     | 
|
| 29 | 
         
             
                "successMessage": "登录成功",
         
     | 
| 30 | 
         
             
                "errorEmptyFields": "请输入您的用户名和密码",
         
     | 
| 31 | 
         
             
                "errorInvalidCredentials": "登录失败,请检查用户名和密码",
         
     | 
| 32 | 
         
            -
                "authDisabled": " 
     | 
| 33 | 
         
            -
                "guestMode": " 
     | 
| 34 | 
         
             
              },
         
     | 
| 35 | 
         
             
              "documentPanel": {
         
     | 
| 36 | 
         
             
                "clearDocuments": {
         
     | 
| 
         | 
|
| 29 | 
         
             
                "successMessage": "登录成功",
         
     | 
| 30 | 
         
             
                "errorEmptyFields": "请输入您的用户名和密码",
         
     | 
| 31 | 
         
             
                "errorInvalidCredentials": "登录失败,请检查用户名和密码",
         
     | 
| 32 | 
         
            +
                "authDisabled": "认证已禁用,使用无需登陆模式。",
         
     | 
| 33 | 
         
            +
                "guestMode": "无需登陆"
         
     | 
| 34 | 
         
             
              },
         
     | 
| 35 | 
         
             
              "documentPanel": {
         
     | 
| 36 | 
         
             
                "clearDocuments": {
         
     | 
    	
        lightrag_webui/src/stores/state.ts
    CHANGED
    
    | 
         @@ -73,10 +73,10 @@ const isGuestToken = (token: string): boolean => { 
     | 
|
| 73 | 
         
             
                // JWT tokens are in the format: header.payload.signature
         
     | 
| 74 | 
         
             
                const parts = token.split('.');
         
     | 
| 75 | 
         
             
                if (parts.length !== 3) return false;
         
     | 
| 76 | 
         
            -
             
     | 
| 77 | 
         
             
                // Decode the payload (second part)
         
     | 
| 78 | 
         
             
                const payload = JSON.parse(atob(parts[1]));
         
     | 
| 79 | 
         
            -
             
     | 
| 80 | 
         
             
                // Check if the token has a role field with value "guest"
         
     | 
| 81 | 
         
             
                return payload.role === 'guest';
         
     | 
| 82 | 
         
             
              } catch (e) {
         
     | 
| 
         @@ -91,9 +91,9 @@ const initAuthState = (): { isAuthenticated: boolean; isGuestMode: boolean } => 
     | 
|
| 91 | 
         
             
              if (!token) {
         
     | 
| 92 | 
         
             
                return { isAuthenticated: false, isGuestMode: false };
         
     | 
| 93 | 
         
             
              }
         
     | 
| 94 | 
         
            -
             
     | 
| 95 | 
         
            -
              return { 
     | 
| 96 | 
         
            -
                isAuthenticated: true, 
     | 
| 97 | 
         
             
                isGuestMode: isGuestToken(token)
         
     | 
| 98 | 
         
             
              };
         
     | 
| 99 | 
         
             
            };
         
     | 
| 
         @@ -101,29 +101,29 @@ const initAuthState = (): { isAuthenticated: boolean; isGuestMode: boolean } => 
     | 
|
| 101 | 
         
             
            export const useAuthStore = create<AuthState>(set => {
         
     | 
| 102 | 
         
             
              // Get initial state from localStorage
         
     | 
| 103 | 
         
             
              const initialState = initAuthState();
         
     | 
| 104 | 
         
            -
             
     | 
| 105 | 
         
             
              return {
         
     | 
| 106 | 
         
             
                isAuthenticated: initialState.isAuthenticated,
         
     | 
| 107 | 
         
             
                showLoginModal: false,
         
     | 
| 108 | 
         
             
                isGuestMode: initialState.isGuestMode,
         
     | 
| 109 | 
         
            -
             
     | 
| 110 | 
         
             
                login: (token, isGuest = false) => {
         
     | 
| 111 | 
         
             
                  localStorage.setItem('LIGHTRAG-API-TOKEN', token);
         
     | 
| 112 | 
         
            -
                  set({ 
     | 
| 113 | 
         
            -
                    isAuthenticated: true, 
     | 
| 114 | 
         
             
                    showLoginModal: false,
         
     | 
| 115 | 
         
             
                    isGuestMode: isGuest
         
     | 
| 116 | 
         
             
                  });
         
     | 
| 117 | 
         
             
                },
         
     | 
| 118 | 
         
            -
             
     | 
| 119 | 
         
             
                logout: () => {
         
     | 
| 120 | 
         
             
                  localStorage.removeItem('LIGHTRAG-API-TOKEN');
         
     | 
| 121 | 
         
            -
                  set({ 
     | 
| 122 | 
         
             
                    isAuthenticated: false,
         
     | 
| 123 | 
         
             
                    isGuestMode: false
         
     | 
| 124 | 
         
             
                  });
         
     | 
| 125 | 
         
             
                },
         
     | 
| 126 | 
         
            -
             
     | 
| 127 | 
         
             
                setShowLoginModal: (show) => set({ showLoginModal: show })
         
     | 
| 128 | 
         
             
              };
         
     | 
| 129 | 
         
             
            });
         
     | 
| 
         | 
|
| 73 | 
         
             
                // JWT tokens are in the format: header.payload.signature
         
     | 
| 74 | 
         
             
                const parts = token.split('.');
         
     | 
| 75 | 
         
             
                if (parts.length !== 3) return false;
         
     | 
| 76 | 
         
            +
             
     | 
| 77 | 
         
             
                // Decode the payload (second part)
         
     | 
| 78 | 
         
             
                const payload = JSON.parse(atob(parts[1]));
         
     | 
| 79 | 
         
            +
             
     | 
| 80 | 
         
             
                // Check if the token has a role field with value "guest"
         
     | 
| 81 | 
         
             
                return payload.role === 'guest';
         
     | 
| 82 | 
         
             
              } catch (e) {
         
     | 
| 
         | 
|
| 91 | 
         
             
              if (!token) {
         
     | 
| 92 | 
         
             
                return { isAuthenticated: false, isGuestMode: false };
         
     | 
| 93 | 
         
             
              }
         
     | 
| 94 | 
         
            +
             
     | 
| 95 | 
         
            +
              return {
         
     | 
| 96 | 
         
            +
                isAuthenticated: true,
         
     | 
| 97 | 
         
             
                isGuestMode: isGuestToken(token)
         
     | 
| 98 | 
         
             
              };
         
     | 
| 99 | 
         
             
            };
         
     | 
| 
         | 
|
| 101 | 
         
             
            export const useAuthStore = create<AuthState>(set => {
         
     | 
| 102 | 
         
             
              // Get initial state from localStorage
         
     | 
| 103 | 
         
             
              const initialState = initAuthState();
         
     | 
| 104 | 
         
            +
             
     | 
| 105 | 
         
             
              return {
         
     | 
| 106 | 
         
             
                isAuthenticated: initialState.isAuthenticated,
         
     | 
| 107 | 
         
             
                showLoginModal: false,
         
     | 
| 108 | 
         
             
                isGuestMode: initialState.isGuestMode,
         
     | 
| 109 | 
         
            +
             
     | 
| 110 | 
         
             
                login: (token, isGuest = false) => {
         
     | 
| 111 | 
         
             
                  localStorage.setItem('LIGHTRAG-API-TOKEN', token);
         
     | 
| 112 | 
         
            +
                  set({
         
     | 
| 113 | 
         
            +
                    isAuthenticated: true,
         
     | 
| 114 | 
         
             
                    showLoginModal: false,
         
     | 
| 115 | 
         
             
                    isGuestMode: isGuest
         
     | 
| 116 | 
         
             
                  });
         
     | 
| 117 | 
         
             
                },
         
     | 
| 118 | 
         
            +
             
     | 
| 119 | 
         
             
                logout: () => {
         
     | 
| 120 | 
         
             
                  localStorage.removeItem('LIGHTRAG-API-TOKEN');
         
     | 
| 121 | 
         
            +
                  set({
         
     | 
| 122 | 
         
             
                    isAuthenticated: false,
         
     | 
| 123 | 
         
             
                    isGuestMode: false
         
     | 
| 124 | 
         
             
                  });
         
     | 
| 125 | 
         
             
                },
         
     | 
| 126 | 
         
            +
             
     | 
| 127 | 
         
             
                setShowLoginModal: (show) => set({ showLoginModal: show })
         
     | 
| 128 | 
         
             
              };
         
     | 
| 129 | 
         
             
            });
         
     |