Tai Truong
fix readme
d202ada
from typing import Annotated
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query
from loguru import logger
from langflow.api.utils import CurrentActiveUser, check_langflow_version
from langflow.services.auth import utils as auth_utils
from langflow.services.deps import get_settings_service, get_store_service
from langflow.services.store.exceptions import CustomError
from langflow.services.store.schema import (
CreateComponentResponse,
DownloadComponentResponse,
ListComponentResponseModel,
StoreComponentCreate,
TagResponse,
UsersLikesResponse,
)
router = APIRouter(prefix="/store", tags=["Components Store"])
def get_user_store_api_key(user: CurrentActiveUser):
if not user.store_api_key:
raise HTTPException(status_code=400, detail="You must have a store API key set.")
try:
return auth_utils.decrypt_api_key(user.store_api_key, get_settings_service())
except Exception as e:
raise HTTPException(status_code=500, detail="Failed to decrypt API key. Please set a new one.") from e
def get_optional_user_store_api_key(user: CurrentActiveUser):
if not user.store_api_key:
return None
try:
return auth_utils.decrypt_api_key(user.store_api_key, get_settings_service())
except Exception: # noqa: BLE001
logger.exception("Failed to decrypt API key")
return user.store_api_key
@router.get("/check/")
async def check_if_store_is_enabled():
return {
"enabled": get_settings_service().settings.store,
}
@router.get("/check/api_key")
async def check_if_store_has_api_key(
api_key: Annotated[str | None, Depends(get_optional_user_store_api_key)],
):
if api_key is None:
return {"has_api_key": False, "is_valid": False}
try:
is_valid = await get_store_service().check_api_key(api_key)
except Exception as e:
raise HTTPException(status_code=400, detail=str(e)) from e
return {"has_api_key": api_key is not None, "is_valid": is_valid}
@router.post("/components/", status_code=201)
async def share_component(
component: StoreComponentCreate,
store_api_key: Annotated[str, Depends(get_user_store_api_key)],
) -> CreateComponentResponse:
try:
await check_langflow_version(component)
return await get_store_service().upload(store_api_key, component)
except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
@router.patch("/components/{component_id}", status_code=201)
async def update_shared_component(
component_id: UUID,
component: StoreComponentCreate,
store_api_key: Annotated[str, Depends(get_user_store_api_key)],
) -> CreateComponentResponse:
try:
await check_langflow_version(component)
return await get_store_service().update(store_api_key, component_id, component)
except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
@router.get("/components/")
async def get_components(
*,
component_id: Annotated[str | None, Query()] = None,
search: Annotated[str | None, Query()] = None,
private: Annotated[bool | None, Query()] = None,
is_component: Annotated[bool | None, Query()] = None,
tags: Annotated[list[str] | None, Query()] = None,
sort: Annotated[list[str] | None, Query()] = None,
liked: Annotated[bool, Query()] = False,
filter_by_user: Annotated[bool, Query()] = False,
fields: Annotated[list[str] | None, Query()] = None,
page: int = 1,
limit: int = 10,
store_api_key: Annotated[str | None, Depends(get_optional_user_store_api_key)],
) -> ListComponentResponseModel:
try:
return await get_store_service().get_list_component_response_model(
component_id=component_id,
search=search,
private=private,
is_component=is_component,
fields=fields,
tags=tags,
sort=sort,
liked=liked,
filter_by_user=filter_by_user,
page=page,
limit=limit,
store_api_key=store_api_key,
)
except CustomError as exc:
raise HTTPException(status_code=exc.status_code, detail=str(exc)) from exc
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc)) from exc
@router.get("/components/{component_id}")
async def download_component(
component_id: UUID,
store_api_key: Annotated[str, Depends(get_user_store_api_key)],
) -> DownloadComponentResponse:
try:
component = await get_store_service().download(store_api_key, component_id)
except CustomError as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc)) from exc
if component is None:
raise HTTPException(status_code=400, detail="Component not found")
return component
@router.get("/tags", response_model=list[TagResponse])
async def get_tags():
try:
return await get_store_service().get_tags()
except CustomError as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc)) from exc
@router.get("/users/likes", response_model=list[UsersLikesResponse])
async def get_list_of_components_liked_by_user(
store_api_key: Annotated[str, Depends(get_user_store_api_key)],
):
try:
return await get_store_service().get_user_likes(store_api_key)
except CustomError as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc)) from exc
@router.post("/users/likes/{component_id}")
async def like_component(
component_id: UUID,
store_api_key: Annotated[str, Depends(get_user_store_api_key)],
) -> UsersLikesResponse:
try:
store_service = get_store_service()
result = await store_service.like_component(store_api_key, str(component_id))
likes_count = await store_service.get_component_likes_count(str(component_id), store_api_key)
return UsersLikesResponse(likes_count=likes_count, liked_by_user=result)
except CustomError as exc:
raise HTTPException(status_code=exc.status_code, detail=str(exc)) from exc
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc)) from exc