🐛 fix(api_key.py): change variable name from 'e' to 'exc' for better readability and semantics

🐛 fix(endpoints.py): add 'api_key' parameter to 'process_flow' function to fix missing dependency error
🐛 fix(endpoints.py): add exception chaining to HTTPException in 'process_flow' function for better error handling
🐛 fix(utils.py): change return type of 'api_key_security' function to Optional[ApiKey] for better type hinting
🐛 fix(utils.py): change variable name from 'e' to 'exc' for better readability and semantics
This commit is contained in:
Gabriel Luiz Freitas Almeida 2023-08-28 07:00:45 -03:00
commit ed9796e473
3 changed files with 28 additions and 13 deletions

View file

@ -31,8 +31,8 @@ def get_api_keys_route(
keys = get_api_keys(db, user_id) keys = get_api_keys(db, user_id)
return ApiKeysResponse(total_count=len(keys), user_id=user_id, api_keys=keys) return ApiKeysResponse(total_count=len(keys), user_id=user_id, api_keys=keys)
except Exception as e: except Exception as exc:
raise HTTPException(status_code=400, detail=str(e)) raise HTTPException(status_code=400, detail=str(exc)) from exc
@router.post("/", response_model=UnmaskedApiKeyRead) @router.post("/", response_model=UnmaskedApiKeyRead)

View file

@ -85,7 +85,6 @@ def get_all(current_user: User = Depends(get_current_active_user)):
@router.post( @router.post(
"/process/{flow_id}", "/process/{flow_id}",
response_model=ProcessResponse, response_model=ProcessResponse,
dependencies=[Depends(api_key_security)],
) )
async def process_flow( async def process_flow(
session: Annotated[Session, Depends(get_session)], session: Annotated[Session, Depends(get_session)],
@ -94,13 +93,21 @@ async def process_flow(
tweaks: Optional[dict] = None, tweaks: Optional[dict] = None,
clear_cache: Annotated[bool, Body(embed=True)] = False, # noqa: F821 clear_cache: Annotated[bool, Body(embed=True)] = False, # noqa: F821
session_id: Annotated[Union[None, str], Body(embed=True)] = None, # noqa: F821 session_id: Annotated[Union[None, str], Body(embed=True)] = None, # noqa: F821
api_key=Depends(api_key_security),
): ):
""" """
Endpoint to process an input with a given flow_id. Endpoint to process an input with a given flow_id.
""" """
try: try:
flow = session.get(Flow, flow_id) api_key_user = api_key.user
# Get the flow that matches the flow_id and belongs to the user
flow = (
session.query(Flow)
.filter(Flow.id == flow_id)
.filter(Flow.user_id == api_key_user.id)
.first()
)
if flow is None: if flow is None:
raise ValueError(f"Flow {flow_id} not found") raise ValueError(f"Flow {flow_id} not found")
@ -120,14 +127,18 @@ async def process_flow(
# StatementError('(builtins.ValueError) badly formed hexadecimal UUID string') # StatementError('(builtins.ValueError) badly formed hexadecimal UUID string')
if "badly formed hexadecimal UUID string" in str(exc): if "badly formed hexadecimal UUID string" in str(exc):
# This means the Flow ID is not a valid UUID which means it can't find the flow # This means the Flow ID is not a valid UUID which means it can't find the flow
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
) from exc
except ValueError as exc: except ValueError as exc:
if f"Flow {flow_id} not found" in str(exc): if f"Flow {flow_id} not found" in str(exc):
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
) from exc
else: else:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc) status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(exc)
) ) from exc
except Exception as e: except Exception as e:
# Log stack trace # Log stack trace
logger.exception(e) logger.exception(e)

View file

@ -2,8 +2,9 @@ from datetime import datetime, timedelta, timezone
from fastapi import Depends, HTTPException, Security, status from fastapi import Depends, HTTPException, Security, status
from fastapi.security import APIKeyHeader, APIKeyQuery, OAuth2PasswordBearer from fastapi.security import APIKeyHeader, APIKeyQuery, OAuth2PasswordBearer
from jose import JWTError, jwt from jose import JWTError, jwt
from typing import Annotated, Coroutine from typing import Annotated, Coroutine, Optional
from uuid import UUID from uuid import UUID
from langflow.services.database.models.api_key.api_key import ApiKey
from langflow.services.database.models.api_key.crud import check_key from langflow.services.database.models.api_key.crud import check_key
from langflow.services.database.models.user.user import User from langflow.services.database.models.user.user import User
from langflow.services.database.models.user.crud import ( from langflow.services.database.models.user.crud import (
@ -31,8 +32,9 @@ async def api_key_security(
query_param: str = Security(api_key_query), query_param: str = Security(api_key_query),
header_param: str = Security(api_key_header), header_param: str = Security(api_key_header),
db: Session = Depends(get_session), db: Session = Depends(get_session),
): ) -> Optional[ApiKey]:
settings_manager = get_settings_manager() settings_manager = get_settings_manager()
result = None
if settings_manager.auth_settings.AUTO_LOGIN: if settings_manager.auth_settings.AUTO_LOGIN:
return settings_manager.auth_settings.API_KEY_SECRET_KEY return settings_manager.auth_settings.API_KEY_SECRET_KEY
@ -42,12 +44,14 @@ async def api_key_security(
detail="An API key must be passed as query or header", detail="An API key must be passed as query or header",
) )
elif query_param and check_key(db, query_param): elif query_param:
return query_param result = check_key(db, query_param)
elif header_param and check_key(db, header_param): else:
return header_param result = check_key(db, header_param)
if result:
return result
else: else:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN, status_code=status.HTTP_403_FORBIDDEN,