refactor: replace user authentication method with conditional authentication across multiple routers
This commit is contained in:
parent
560dd71228
commit
ea633aedc1
13 changed files with 67 additions and 105 deletions
|
|
@ -9,7 +9,7 @@ from fastapi import Form, File, UploadFile, Depends
|
|||
from typing import List, Optional, Union, Literal
|
||||
|
||||
from cognee.modules.users.models import User
|
||||
from cognee.modules.users.methods import get_optional_authenticated_user, get_default_user
|
||||
from cognee.modules.users.methods import get_conditional_authenticated_user
|
||||
from cognee.shared.utils import send_telemetry
|
||||
from cognee.modules.pipelines.models import PipelineRunErrored
|
||||
from cognee.shared.logging_utils import get_logger
|
||||
|
|
@ -25,7 +25,7 @@ def get_add_router() -> APIRouter:
|
|||
data: List[UploadFile] = File(default=None),
|
||||
datasetName: Optional[str] = Form(default=None),
|
||||
datasetId: Union[UUID, Literal[""], None] = Form(default=None, examples=[""]),
|
||||
user: Optional[User] = Depends(get_optional_authenticated_user),
|
||||
user: User = Depends(get_conditional_authenticated_user),
|
||||
):
|
||||
"""
|
||||
Add data to a dataset for processing and knowledge graph construction.
|
||||
|
|
@ -62,10 +62,6 @@ def get_add_router() -> APIRouter:
|
|||
- The ALLOW_HTTP_REQUESTS environment variable controls URL processing
|
||||
- datasetId value can only be the UUID of an already existing dataset
|
||||
"""
|
||||
# Use default user for anonymous requests
|
||||
if user is None:
|
||||
user = await get_default_user()
|
||||
|
||||
send_telemetry(
|
||||
"Add API Endpoint Invoked",
|
||||
user.id,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ from starlette.status import WS_1000_NORMAL_CLOSURE, WS_1008_POLICY_VIOLATION
|
|||
from cognee.api.DTO import InDTO
|
||||
from cognee.modules.pipelines.methods import get_pipeline_run
|
||||
from cognee.modules.users.models import User
|
||||
from cognee.modules.users.methods import get_optional_authenticated_user, get_default_user
|
||||
from cognee.modules.users.methods import get_conditional_authenticated_user
|
||||
from cognee.modules.users.get_user_db import get_user_db_context
|
||||
from cognee.modules.graph.methods import get_formatted_graph_data
|
||||
from cognee.modules.users.get_user_manager import get_user_manager_context
|
||||
|
|
@ -46,7 +46,7 @@ def get_cognify_router() -> APIRouter:
|
|||
router = APIRouter()
|
||||
|
||||
@router.post("", response_model=dict)
|
||||
async def cognify(payload: CognifyPayloadDTO, user: Optional[User] = Depends(get_optional_authenticated_user)):
|
||||
async def cognify(payload: CognifyPayloadDTO, user: User = Depends(get_conditional_authenticated_user)):
|
||||
"""
|
||||
Transform datasets into structured knowledge graphs through cognitive processing.
|
||||
|
||||
|
|
@ -92,10 +92,6 @@ def get_cognify_router() -> APIRouter:
|
|||
## Next Steps
|
||||
After successful processing, use the search endpoints to query the generated knowledge graph for insights, relationships, and semantic search.
|
||||
"""
|
||||
# Use default user for anonymous requests
|
||||
if user is None:
|
||||
user = await get_default_user()
|
||||
|
||||
send_telemetry(
|
||||
"Cognify API Endpoint Invoked",
|
||||
user.id,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from cognee.modules.data.methods import create_dataset, get_datasets_by_name
|
|||
from cognee.shared.logging_utils import get_logger
|
||||
from cognee.api.v1.exceptions import DataNotFoundError, DatasetNotFoundError
|
||||
from cognee.modules.users.models import User
|
||||
from cognee.modules.users.methods import get_authenticated_user
|
||||
from cognee.modules.users.methods import get_conditional_authenticated_user
|
||||
from cognee.modules.users.permissions.methods import (
|
||||
get_all_user_permission_datasets,
|
||||
give_permission_on_dataset,
|
||||
|
|
@ -74,7 +74,7 @@ def get_datasets_router() -> APIRouter:
|
|||
router = APIRouter()
|
||||
|
||||
@router.get("", response_model=list[DatasetDTO])
|
||||
async def get_datasets(user: User = Depends(get_authenticated_user)):
|
||||
async def get_datasets(user: User = Depends(get_conditional_authenticated_user)):
|
||||
"""
|
||||
Get all datasets accessible to the authenticated user.
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ def get_datasets_router() -> APIRouter:
|
|||
|
||||
@router.post("", response_model=DatasetDTO)
|
||||
async def create_new_dataset(
|
||||
dataset_data: DatasetCreationPayload, user: User = Depends(get_authenticated_user)
|
||||
dataset_data: DatasetCreationPayload, user: User = Depends(get_conditional_authenticated_user)
|
||||
):
|
||||
"""
|
||||
Create a new dataset or return existing dataset with the same name.
|
||||
|
|
@ -175,7 +175,7 @@ def get_datasets_router() -> APIRouter:
|
|||
@router.delete(
|
||||
"/{dataset_id}", response_model=None, responses={404: {"model": ErrorResponseDTO}}
|
||||
)
|
||||
async def delete_dataset(dataset_id: UUID, user: User = Depends(get_authenticated_user)):
|
||||
async def delete_dataset(dataset_id: UUID, user: User = Depends(get_conditional_authenticated_user)):
|
||||
"""
|
||||
Delete a dataset by its ID.
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ def get_datasets_router() -> APIRouter:
|
|||
responses={404: {"model": ErrorResponseDTO}},
|
||||
)
|
||||
async def delete_data(
|
||||
dataset_id: UUID, data_id: UUID, user: User = Depends(get_authenticated_user)
|
||||
dataset_id: UUID, data_id: UUID, user: User = Depends(get_conditional_authenticated_user)
|
||||
):
|
||||
"""
|
||||
Delete a specific data item from a dataset.
|
||||
|
|
@ -263,7 +263,7 @@ def get_datasets_router() -> APIRouter:
|
|||
await delete_data(data)
|
||||
|
||||
@router.get("/{dataset_id}/graph", response_model=GraphDTO)
|
||||
async def get_dataset_graph(dataset_id: UUID, user: User = Depends(get_authenticated_user)):
|
||||
async def get_dataset_graph(dataset_id: UUID, user: User = Depends(get_conditional_authenticated_user)):
|
||||
"""
|
||||
Get the knowledge graph visualization for a dataset.
|
||||
|
||||
|
|
@ -293,7 +293,7 @@ def get_datasets_router() -> APIRouter:
|
|||
response_model=list[DataDTO],
|
||||
responses={404: {"model": ErrorResponseDTO}},
|
||||
)
|
||||
async def get_dataset_data(dataset_id: UUID, user: User = Depends(get_authenticated_user)):
|
||||
async def get_dataset_data(dataset_id: UUID, user: User = Depends(get_conditional_authenticated_user)):
|
||||
"""
|
||||
Get all data items in a dataset.
|
||||
|
||||
|
|
@ -348,7 +348,7 @@ def get_datasets_router() -> APIRouter:
|
|||
@router.get("/status", response_model=dict[str, PipelineRunStatus])
|
||||
async def get_dataset_status(
|
||||
datasets: Annotated[List[UUID], Query(alias="dataset")] = [],
|
||||
user: User = Depends(get_authenticated_user),
|
||||
user: User = Depends(get_conditional_authenticated_user),
|
||||
):
|
||||
"""
|
||||
Get the processing status of datasets.
|
||||
|
|
@ -395,7 +395,7 @@ def get_datasets_router() -> APIRouter:
|
|||
|
||||
@router.get("/{dataset_id}/data/{data_id}/raw", response_class=FileResponse)
|
||||
async def get_raw_data(
|
||||
dataset_id: UUID, data_id: UUID, user: User = Depends(get_authenticated_user)
|
||||
dataset_id: UUID, data_id: UUID, user: User = Depends(get_conditional_authenticated_user)
|
||||
):
|
||||
"""
|
||||
Download the raw data file for a specific data item.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from fastapi import APIRouter
|
|||
from uuid import UUID
|
||||
from cognee.shared.logging_utils import get_logger
|
||||
from cognee.modules.users.models import User
|
||||
from cognee.modules.users.methods import get_authenticated_user
|
||||
from cognee.modules.users.methods import get_conditional_authenticated_user
|
||||
from cognee.shared.utils import send_telemetry
|
||||
|
||||
logger = get_logger()
|
||||
|
|
@ -18,7 +18,7 @@ def get_delete_router() -> APIRouter:
|
|||
data_id: UUID,
|
||||
dataset_id: UUID,
|
||||
mode: str = "soft",
|
||||
user: User = Depends(get_authenticated_user),
|
||||
user: User = Depends(get_conditional_authenticated_user),
|
||||
):
|
||||
"""Delete data by its ID from the specified dataset.
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from fastapi import APIRouter, Depends
|
|||
from fastapi.responses import JSONResponse
|
||||
|
||||
from cognee.modules.users.models import User
|
||||
from cognee.modules.users.methods import get_authenticated_user
|
||||
from cognee.modules.users.methods import get_conditional_authenticated_user
|
||||
from cognee.shared.utils import send_telemetry
|
||||
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ def get_permissions_router() -> APIRouter:
|
|||
permission_name: str,
|
||||
dataset_ids: List[UUID],
|
||||
principal_id: UUID,
|
||||
user: User = Depends(get_authenticated_user),
|
||||
user: User = Depends(get_conditional_authenticated_user),
|
||||
):
|
||||
"""
|
||||
Grant permission on datasets to a principal (user or role).
|
||||
|
|
@ -65,7 +65,7 @@ def get_permissions_router() -> APIRouter:
|
|||
)
|
||||
|
||||
@permissions_router.post("/roles")
|
||||
async def create_role(role_name: str, user: User = Depends(get_authenticated_user)):
|
||||
async def create_role(role_name: str, user: User = Depends(get_conditional_authenticated_user)):
|
||||
"""
|
||||
Create a new role.
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ def get_permissions_router() -> APIRouter:
|
|||
|
||||
@permissions_router.post("/users/{user_id}/roles")
|
||||
async def add_user_to_role(
|
||||
user_id: UUID, role_id: UUID, user: User = Depends(get_authenticated_user)
|
||||
user_id: UUID, role_id: UUID, user: User = Depends(get_conditional_authenticated_user)
|
||||
):
|
||||
"""
|
||||
Add a user to a role.
|
||||
|
|
@ -142,7 +142,7 @@ def get_permissions_router() -> APIRouter:
|
|||
|
||||
@permissions_router.post("/users/{user_id}/tenants")
|
||||
async def add_user_to_tenant(
|
||||
user_id: UUID, tenant_id: UUID, user: User = Depends(get_authenticated_user)
|
||||
user_id: UUID, tenant_id: UUID, user: User = Depends(get_conditional_authenticated_user)
|
||||
):
|
||||
"""
|
||||
Add a user to a tenant.
|
||||
|
|
@ -183,7 +183,7 @@ def get_permissions_router() -> APIRouter:
|
|||
return JSONResponse(status_code=200, content={"message": "User added to tenant"})
|
||||
|
||||
@permissions_router.post("/tenants")
|
||||
async def create_tenant(tenant_name: str, user: User = Depends(get_authenticated_user)):
|
||||
async def create_tenant(tenant_name: str, user: User = Depends(get_conditional_authenticated_user)):
|
||||
"""
|
||||
Create a new tenant.
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ from cognee.infrastructure.llm.config import (
|
|||
get_llm_config,
|
||||
)
|
||||
from cognee.modules.users.models import User
|
||||
from cognee.modules.users.methods import get_authenticated_user
|
||||
from cognee.modules.users.methods import get_conditional_authenticated_user
|
||||
|
||||
|
||||
def get_responses_router() -> APIRouter:
|
||||
|
|
@ -73,7 +73,7 @@ def get_responses_router() -> APIRouter:
|
|||
@router.post("/", response_model=ResponseBody)
|
||||
async def create_response(
|
||||
request: ResponseRequest,
|
||||
user: User = Depends(get_authenticated_user),
|
||||
user: User = Depends(get_conditional_authenticated_user),
|
||||
) -> ResponseBody:
|
||||
"""
|
||||
OpenAI-compatible responses endpoint with function calling support.
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from cognee.api.DTO import InDTO, OutDTO
|
|||
from cognee.modules.users.exceptions.exceptions import PermissionDeniedError
|
||||
from cognee.modules.users.models import User
|
||||
from cognee.modules.search.operations import get_history
|
||||
from cognee.modules.users.methods import get_optional_authenticated_user, get_default_user
|
||||
from cognee.modules.users.methods import get_conditional_authenticated_user
|
||||
from cognee.shared.utils import send_telemetry
|
||||
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ def get_search_router() -> APIRouter:
|
|||
created_at: datetime
|
||||
|
||||
@router.get("", response_model=list[SearchHistoryItem])
|
||||
async def get_search_history(user: Optional[User] = Depends(get_optional_authenticated_user)):
|
||||
async def get_search_history(user: User = Depends(get_conditional_authenticated_user)):
|
||||
"""
|
||||
Get search history for the authenticated user.
|
||||
|
||||
|
|
@ -50,10 +50,6 @@ def get_search_router() -> APIRouter:
|
|||
## Error Codes
|
||||
- **500 Internal Server Error**: Error retrieving search history
|
||||
"""
|
||||
# Use default user for anonymous requests
|
||||
if user is None:
|
||||
user = await get_default_user()
|
||||
|
||||
send_telemetry(
|
||||
"Search API Endpoint Invoked",
|
||||
user.id,
|
||||
|
|
@ -70,7 +66,7 @@ def get_search_router() -> APIRouter:
|
|||
return JSONResponse(status_code=500, content={"error": str(error)})
|
||||
|
||||
@router.post("", response_model=list)
|
||||
async def search(payload: SearchPayloadDTO, user: Optional[User] = Depends(get_optional_authenticated_user)):
|
||||
async def search(payload: SearchPayloadDTO, user: User = Depends(get_conditional_authenticated_user)):
|
||||
"""
|
||||
Search for nodes in the graph database.
|
||||
|
||||
|
|
@ -97,10 +93,6 @@ def get_search_router() -> APIRouter:
|
|||
- To search datasets not owned by the request sender, dataset UUID is needed
|
||||
- If permission is denied, returns empty list instead of error
|
||||
"""
|
||||
# Use default user for anonymous requests
|
||||
if user is None:
|
||||
user = await get_default_user()
|
||||
|
||||
send_telemetry(
|
||||
"Search API Endpoint Invoked",
|
||||
user.id,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from fastapi import APIRouter
|
||||
from cognee.api.DTO import InDTO, OutDTO
|
||||
from typing import Union, Optional, Literal
|
||||
from cognee.modules.users.methods import get_authenticated_user
|
||||
from cognee.modules.users.methods import get_conditional_authenticated_user
|
||||
from fastapi import Depends
|
||||
from cognee.modules.users.models import User
|
||||
from cognee.modules.settings.get_settings import LLMConfig, VectorDBConfig
|
||||
|
|
@ -45,7 +45,7 @@ def get_settings_router() -> APIRouter:
|
|||
router = APIRouter()
|
||||
|
||||
@router.get("", response_model=SettingsDTO)
|
||||
async def get_settings(user: User = Depends(get_authenticated_user)):
|
||||
async def get_settings(user: User = Depends(get_conditional_authenticated_user)):
|
||||
"""
|
||||
Get the current system settings.
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ def get_settings_router() -> APIRouter:
|
|||
|
||||
@router.post("", response_model=None)
|
||||
async def save_settings(
|
||||
new_settings: SettingsPayloadDTO, user: User = Depends(get_authenticated_user)
|
||||
new_settings: SettingsPayloadDTO, user: User = Depends(get_conditional_authenticated_user)
|
||||
):
|
||||
"""
|
||||
Save or update system settings.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from fastapi import APIRouter, Depends
|
|||
from fastapi.responses import HTMLResponse, JSONResponse
|
||||
from uuid import UUID
|
||||
from cognee.shared.logging_utils import get_logger
|
||||
from cognee.modules.users.methods import get_authenticated_user
|
||||
from cognee.modules.users.methods import get_conditional_authenticated_user
|
||||
from cognee.modules.data.methods import get_authorized_existing_datasets
|
||||
from cognee.modules.users.models import User
|
||||
|
||||
|
|
@ -16,7 +16,7 @@ def get_visualize_router() -> APIRouter:
|
|||
router = APIRouter()
|
||||
|
||||
@router.get("", response_model=None)
|
||||
async def visualize(dataset_id: UUID, user: User = Depends(get_authenticated_user)):
|
||||
async def visualize(dataset_id: UUID, user: User = Depends(get_conditional_authenticated_user)):
|
||||
"""
|
||||
Generate an HTML visualization of the dataset's knowledge graph.
|
||||
|
||||
|
|
|
|||
|
|
@ -4,5 +4,4 @@ from .delete_user import delete_user
|
|||
from .get_default_user import get_default_user
|
||||
from .get_user_by_email import get_user_by_email
|
||||
from .create_default_user import create_default_user
|
||||
from .get_authenticated_user import get_authenticated_user
|
||||
from .get_optional_authenticated_user import get_optional_authenticated_user
|
||||
from .get_conditional_authenticated_user import get_conditional_authenticated_user, REQUIRE_AUTHENTICATION
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
from ..get_fastapi_users import get_fastapi_users
|
||||
|
||||
|
||||
fastapi_users = get_fastapi_users()
|
||||
|
||||
get_authenticated_user = fastapi_users.current_user(active=True)
|
||||
|
||||
# from types import SimpleNamespace
|
||||
|
||||
# from ..get_fastapi_users import get_fastapi_users
|
||||
# from fastapi import HTTPException, Security
|
||||
# from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
||||
# import os
|
||||
# import jwt
|
||||
|
||||
# from uuid import UUID
|
||||
|
||||
# fastapi_users = get_fastapi_users()
|
||||
|
||||
# # Allows Swagger to understand authorization type and allow single sign on for the Swagger docs to test backend
|
||||
# bearer_scheme = HTTPBearer(scheme_name="BearerAuth", description="Paste **Bearer <JWT>**")
|
||||
|
||||
|
||||
# async def get_authenticated_user(
|
||||
# creds: HTTPAuthorizationCredentials = Security(bearer_scheme),
|
||||
# ) -> SimpleNamespace:
|
||||
# """
|
||||
# Extract and validate the JWT presented in the Authorization header.
|
||||
# """
|
||||
# if creds is None: # header missing
|
||||
# raise HTTPException(status_code=401, detail="Not authenticated")
|
||||
|
||||
# if creds.scheme.lower() != "bearer": # shouldn't happen extra guard
|
||||
# raise HTTPException(status_code=401, detail="Invalid authentication scheme")
|
||||
|
||||
# token = creds.credentials
|
||||
# try:
|
||||
# payload = jwt.decode(
|
||||
# token, os.getenv("FASTAPI_USERS_JWT_SECRET", "super_secret"), algorithms=["HS256"]
|
||||
# )
|
||||
|
||||
# auth_data = SimpleNamespace(id=UUID(payload["user_id"]))
|
||||
# return auth_data
|
||||
|
||||
# except jwt.ExpiredSignatureError:
|
||||
# raise HTTPException(status_code=401, detail="Token has expired")
|
||||
# except jwt.InvalidTokenError:
|
||||
# raise HTTPException(status_code=401, detail="Invalid token")
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import os
|
||||
from typing import Optional
|
||||
from fastapi import Depends
|
||||
from ..models import User
|
||||
from ..get_fastapi_users import get_fastapi_users
|
||||
from .get_default_user import get_default_user
|
||||
|
||||
# Check environment variable to determine authentication requirement
|
||||
REQUIRE_AUTHENTICATION = os.getenv("REQUIRE_AUTHENTICATION", "false").lower() == "true"
|
||||
|
||||
fastapi_users = get_fastapi_users()
|
||||
|
||||
if REQUIRE_AUTHENTICATION:
|
||||
# When REQUIRE_AUTHENTICATION=true, enforce authentication (original behavior)
|
||||
_auth_dependency = fastapi_users.current_user(active=True)
|
||||
else:
|
||||
# When REQUIRE_AUTHENTICATION=false (default), make authentication optional
|
||||
_auth_dependency = fastapi_users.current_user(
|
||||
optional=True, # Returns None instead of raising HTTPException(401)
|
||||
active=True # Still require users to be active when authenticated
|
||||
)
|
||||
|
||||
async def get_conditional_authenticated_user(user: Optional[User] = Depends(_auth_dependency)) -> User:
|
||||
"""
|
||||
Get authenticated user with environment-controlled behavior:
|
||||
- If REQUIRE_AUTHENTICATION=true: Enforces authentication (raises 401 if not authenticated)
|
||||
- If REQUIRE_AUTHENTICATION=false: Falls back to default user if not authenticated
|
||||
|
||||
Always returns a User object for consistent typing.
|
||||
"""
|
||||
if user is None and not REQUIRE_AUTHENTICATION:
|
||||
# When authentication is optional and user is None, use default user
|
||||
user = await get_default_user()
|
||||
|
||||
return user
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
from ..get_fastapi_users import get_fastapi_users
|
||||
|
||||
# Create optional authenticated user dependency using FastAPI Users' built-in optional parameter
|
||||
fastapi_users = get_fastapi_users()
|
||||
get_optional_authenticated_user = fastapi_users.current_user(
|
||||
optional=True, # Returns None instead of raising HTTPException(401)
|
||||
active=True # Still require users to be active when authenticated
|
||||
)
|
||||
Loading…
Add table
Reference in a new issue