diff --git a/src/backend/langflow/api/router.py b/src/backend/langflow/api/router.py index b87a24ea3..24d64b401 100644 --- a/src/backend/langflow/api/router.py +++ b/src/backend/langflow/api/router.py @@ -1,14 +1,16 @@ # Router for base api from fastapi import APIRouter + from langflow.api.v1 import ( + api_key_router, chat_router, + credentials_router, endpoints_router, - validate_router, flows_router, + login_router, store_router, users_router, - api_key_router, - login_router, + validate_router, ) router = APIRouter( @@ -22,3 +24,4 @@ router.include_router(flows_router) router.include_router(users_router) router.include_router(api_key_router) router.include_router(login_router) +router.include_router(credentials_router) diff --git a/src/backend/langflow/api/v1/__init__.py b/src/backend/langflow/api/v1/__init__.py index 197b9730f..6368a0cc8 100644 --- a/src/backend/langflow/api/v1/__init__.py +++ b/src/backend/langflow/api/v1/__init__.py @@ -1,11 +1,12 @@ -from langflow.api.v1.endpoints import router as endpoints_router -from langflow.api.v1.validate import router as validate_router +from langflow.api.v1.api_key import router as api_key_router from langflow.api.v1.chat import router as chat_router +from langflow.api.v1.credential import router as credentials_router +from langflow.api.v1.endpoints import router as endpoints_router from langflow.api.v1.flows import router as flows_router +from langflow.api.v1.login import router as login_router from langflow.api.v1.store import router as store_router from langflow.api.v1.users import router as users_router -from langflow.api.v1.api_key import router as api_key_router -from langflow.api.v1.login import router as login_router +from langflow.api.v1.validate import router as validate_router __all__ = [ "chat_router", @@ -16,4 +17,5 @@ __all__ = [ "users_router", "api_key_router", "login_router", + "credentials_router", ] diff --git a/src/backend/langflow/api/v1/credential.py b/src/backend/langflow/api/v1/credential.py new file mode 100644 index 000000000..14e6f3da4 --- /dev/null +++ b/src/backend/langflow/api/v1/credential.py @@ -0,0 +1,79 @@ +from datetime import datetime +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException +from langflow.services.auth.utils import get_current_active_user +from langflow.services.database.models.credential import Credential, CredentialCreate, CredentialRead, CredentialUpdate +from langflow.services.database.models.user.model import User +from langflow.services.deps import get_session, get_settings_service +from sqlmodel import Session +from langflow.services.auth import utils as auth_utils + +router = APIRouter(prefix="/credentials", tags=["Credentials"]) + + +@router.post("/", response_model=CredentialRead, status_code=201) +def create_credential( + *, + session: Session = Depends(get_session), + credential: CredentialCreate, + current_user: User = Depends(get_current_active_user), + settings_service=Depends(get_settings_service), +): + """Create a new credential.""" + try: + db_credential = Credential.model_validate(credential, from_attributes=True) + if not db_credential.value: + raise HTTPException(status_code=400, detail="Credential value cannot be empty") + encrypted = auth_utils.encrypt_api_key(db_credential.value, settings_service=settings_service) + db_credential.value = encrypted + db_credential.user_id = current_user.id + session.add(db_credential) + session.commit() + session.refresh(db_credential) + return db_credential + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) from e + + +@router.get("/", response_model=list[CredentialRead], status_code=200) +def read_credentials( + *, + session: Session = Depends(get_session), + current_user: User = Depends(get_current_active_user), +): + """Read all credentials.""" + try: + credentials = session.query(Credential).filter(Credential.user_id == current_user.id).all() + return credentials + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) from e + + +@router.patch("/{credential_id}", response_model=CredentialRead, status_code=200) +def update_credential( + *, + session: Session = Depends(get_session), + credential_id: UUID, + credential: CredentialUpdate, + current_user: User = Depends(get_current_active_user), +): + """Update a credential.""" + try: + db_credential = ( + session.query(Credential) + .filter(Credential.id == credential_id, Credential.user_id == current_user.id) + .first() + ) + if not db_credential: + raise HTTPException(status_code=404, detail="Credential not found") + + credential_data = credential.model_dump(exclude_unset=True) + for key, value in credential_data.items(): + setattr(db_credential, key, value) + db_credential.updated_at = datetime.utcnow() + session.commit() + session.refresh(db_credential) + return db_credential + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) from e