From 2edffd33eef29c57691e346b00fc77d498fd1ab3 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 28 Aug 2023 17:54:54 -0300 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=90=9B=20fix(endpoints.py):=20add=20m?= =?UTF-8?q?issing=20colon=20after=20if=20statement=20condition=20?= =?UTF-8?q?=F0=9F=94=92=20chore(endpoints.py):=20rename=20api=5Fkey=20para?= =?UTF-8?q?meter=20to=20api=5Fkey=5Fuser=20for=20clarity=20and=20consisten?= =?UTF-8?q?cy=20=F0=9F=94=92=20chore(endpoints.py):=20add=20type=20hint=20?= =?UTF-8?q?for=20api=5Fkey=5Fuser=20parameter=20to=20indicate=20it=20is=20?= =?UTF-8?q?of=20type=20User=20=F0=9F=94=92=20chore(endpoints.py):=20remove?= =?UTF-8?q?=20unnecessary=20assignment=20of=20api=5Fkey=5Fuser=20from=20ap?= =?UTF-8?q?i=5Fkey.user?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/endpoints.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py index 49426aeb7..9cacefcd4 100644 --- a/src/backend/langflow/api/v1/endpoints.py +++ b/src/backend/langflow/api/v1/endpoints.py @@ -1,5 +1,5 @@ from http import HTTPStatus -from typing import Annotated, Optional, Union +from typing import Annotated, Any, Optional, Union from langflow.services.auth.utils import api_key_security, get_current_active_user from langflow.services.cache.utils import save_uploaded_file @@ -40,7 +40,7 @@ def get_all(current_user: User = Depends(get_current_active_user)): native_components = build_langchain_types_dict() # custom_components is a list of dicts # need to merge all the keys into one dict - custom_components_from_file = {} + custom_components_from_file: dict[str, Any] = {} settings_manager = get_settings_manager() if settings_manager.settings.COMPONENTS_PATH: logger.info( @@ -93,19 +93,19 @@ async def process_flow( tweaks: Optional[dict] = None, clear_cache: Annotated[bool, Body(embed=True)] = False, # noqa: F821 session_id: Annotated[Union[None, str], Body(embed=True)] = None, # noqa: F821 - api_key=Depends(api_key_security), + api_key_user: User =Depends(api_key_security), ): """ Endpoint to process an input with a given flow_id. """ try: - if api_key is None: + if api_key_user is None raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid API Key", ) - api_key_user = api_key.user + # Get the flow that matches the flow_id and belongs to the user flow = ( session.query(Flow) From d9deb6fd5fd1c91686198ae119e14461899e750e Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 28 Aug 2023 17:55:04 -0300 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=94=A7=20chore(util.py):=20add=20type?= =?UTF-8?q?=20ignore=20comment=20to=20import=20statement=20for=20multiproc?= =?UTF-8?q?ess=20module=20=F0=9F=90=9B=20fix(util.py):=20fix=20condition?= =?UTF-8?q?=20to=20check=20if=20"BaseModel"=20is=20in=20the=20string=20rep?= =?UTF-8?q?resentation=20of=20=5Ftype=20to=20avoid=20skipping=20BaseModel?= =?UTF-8?q?=20types=20in=20format=5Fdict=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/utils/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/utils/util.py b/src/backend/langflow/utils/util.py index 8f0ff216a..890201294 100644 --- a/src/backend/langflow/utils/util.py +++ b/src/backend/langflow/utils/util.py @@ -10,7 +10,7 @@ from langflow.__main__ import console # type: ignore from langflow.template.frontend_node.constants import FORCE_SHOW_FIELDS from langflow.utils import constants from langflow.utils.logger import logger -from multiprocess import cpu_count +from multiprocess import cpu_count # type: ignore from rich.table import Table # type: ignore @@ -267,7 +267,7 @@ def format_dict( _type: Union[str, type] = get_type(value) - if "BaseModel" in _type: + if "BaseModel" in str(_type): continue _type = remove_optional_wrapper(_type) From 31abe8d67ecc4fba3d580dd59fbd7c5b11d8aca5 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 28 Aug 2023 17:55:14 -0300 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=90=9B=20fix(utils.py):=20fix=20missi?= =?UTF-8?q?ng=20return=20statement=20in=20api=5Fkey=5Fsecurity=20function?= =?UTF-8?q?=20=F0=9F=94=80=20refactor(utils.py):=20refactor=20create=5Fsup?= =?UTF-8?q?er=5Fuser=20function=20to=20use=20Optional=20types=20for=20user?= =?UTF-8?q?name=20and=20password=20parameters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/auth/utils.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/backend/langflow/services/auth/utils.py b/src/backend/langflow/services/auth/utils.py index 8377b26cb..333ba226b 100644 --- a/src/backend/langflow/services/auth/utils.py +++ b/src/backend/langflow/services/auth/utils.py @@ -36,7 +36,11 @@ async def api_key_security( settings_manager = get_settings_manager() result = None if settings_manager.auth_settings.AUTO_LOGIN: - return settings_manager.auth_settings.API_KEY_SECRET_KEY + # Get the first user + settings_manager.auth_settings.FIRST_SUPERUSER + result = get_user_by_username( + db, settings_manager.auth_settings.FIRST_SUPERUSER + ) elif not query_param and not header_param: raise HTTPException( @@ -50,13 +54,15 @@ async def api_key_security( else: result = check_key(db, header_param) - if result: - return result - else: + if not result: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Invalid or missing API key", ) + if isinstance(result, ApiKey): + return result.user + elif isinstance(result, User): + return result async def get_current_user( @@ -139,7 +145,9 @@ def create_token(data: dict, expires_delta: timedelta): def create_super_user( - db: Session = Depends(get_session), username: str = None, password: str = None + db: Session = Depends(get_session), + username: Optional[str] = None, + password: Optional[str] = None, ) -> User: settings_manager = get_settings_manager() From ac6d2ff8b433adf72d75c18677772aff7e0b33b4 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 28 Aug 2023 17:55:21 -0300 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=94=A5=20refactor(service.py):=20remo?= =?UTF-8?q?ve=20unused=20import=20and=20commented=20code=20in=20AuthManage?= =?UTF-8?q?r=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/auth/service.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/backend/langflow/services/auth/service.py b/src/backend/langflow/services/auth/service.py index c80b984bb..29984a75c 100644 --- a/src/backend/langflow/services/auth/service.py +++ b/src/backend/langflow/services/auth/service.py @@ -1,4 +1,3 @@ -from fastapi import Request from langflow.services.base import Service from typing import TYPE_CHECKING @@ -11,8 +10,3 @@ class AuthManager(Service): def __init__(self, settings_manager: "SettingsManager"): self.settings_manager = settings_manager - - # We need to define a function that can be passed to the Depends() function. - # This function will be called by FastAPI to run oauth2_scheme - def run_oauth2_scheme(self, request: Request): - return self.settings_manager.auth_settings.oauth2_scheme(request=request) From 1b79c1bd7e72eb96eb84a4e718d45af13e11c991 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 28 Aug 2023 17:55:29 -0300 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=90=9B=20fix(types.py):=20pass=20user?= =?UTF-8?q?=5Fid=20parameter=20to=20build=20methods=20in=20AgentVertex,=20?= =?UTF-8?q?LLMVertex,=20WrapperVertex,=20ChainVertex,=20and=20PromptVertex?= =?UTF-8?q?=20to=20enable=20user-specific=20functionality?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/graph/vertex/types.py | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/backend/langflow/graph/vertex/types.py b/src/backend/langflow/graph/vertex/types.py index 9a2dc21c5..a70a06e88 100644 --- a/src/backend/langflow/graph/vertex/types.py +++ b/src/backend/langflow/graph/vertex/types.py @@ -21,18 +21,18 @@ class AgentVertex(Vertex): elif isinstance(source_node, ChainVertex): self.chains.append(source_node) - def build(self, force: bool = False) -> Any: + def build(self, force: bool = False, user_id=None) -> Any: if not self._built or force: self._set_tools_and_chains() # First, build the tools for tool_node in self.tools: - tool_node.build() + tool_node.build(user_id=user_id) # Next, build the chains and the rest for chain_node in self.chains: - chain_node.build(tools=self.tools) + chain_node.build(tools=self.tools, user_id=user_id) - self._build() + self._build(user_id=user_id) return self._built_object @@ -49,13 +49,13 @@ class LLMVertex(Vertex): def __init__(self, data: Dict): super().__init__(data, base_type="llms") - def build(self, force: bool = False) -> Any: + def build(self, force: bool = False, user_id=None) -> Any: # LLM is different because some models might take up too much memory # or time to load. So we only load them when we need them.ß if self.vertex_type == self.built_node_type: return self.class_built_object if not self._built or force: - self._build() + self._build(user_id=user_id) self.built_node_type = self.vertex_type self.class_built_object = self._built_object # Avoid deepcopying the LLM @@ -77,11 +77,11 @@ class WrapperVertex(Vertex): def __init__(self, data: Dict): super().__init__(data, base_type="wrappers") - def build(self, force: bool = False) -> Any: + def build(self, force: bool = False, user_id=None) -> Any: if not self._built or force: if "headers" in self.params: self.params["headers"] = ast.literal_eval(self.params["headers"]) - self._build() + self._build(user_id=user_id) return self._built_object @@ -149,6 +149,7 @@ class ChainVertex(Vertex): self, force: bool = False, tools: Optional[List[Union[ToolkitVertex, ToolVertex]]] = None, + user_id=None, ) -> Any: if not self._built or force: # Check if the chain requires a PromptVertex @@ -157,7 +158,7 @@ class ChainVertex(Vertex): # Build the PromptVertex, passing the tools if available self.params[key] = value.build(tools=tools, force=force) - self._build() + self._build(user_id=user_id) return self._built_object @@ -170,6 +171,7 @@ class PromptVertex(Vertex): self, force: bool = False, tools: Optional[List[Union[ToolkitVertex, ToolVertex]]] = None, + user_id=None, ) -> Any: if not self._built or force: if ( @@ -180,7 +182,7 @@ class PromptVertex(Vertex): # Check if it is a ZeroShotPrompt and needs a tool if "ShotPrompt" in self.vertex_type: tools = ( - [tool_node.build() for tool_node in tools] + [tool_node.build(user_id=user_id) for tool_node in tools] if tools is not None else [] ) @@ -208,7 +210,7 @@ class PromptVertex(Vertex): else: self.params.pop("input_variables", None) - self._build() + self._build(user_id=user_id) return self._built_object def _built_object_repr(self): From 099921514c36ac17fb9dc35eb5b51fd9621e7e58 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 28 Aug 2023 17:56:21 -0300 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=90=9B=20fix(endpoints.py):=20add=20m?= =?UTF-8?q?issing=20colon=20after=20if=20statement=20condition=20to=20fix?= =?UTF-8?q?=20syntax=20error=20=F0=9F=94=92=20chore(endpoints.py):=20fix?= =?UTF-8?q?=20indentation=20and=20add=20missing=20colon=20after=20if=20sta?= =?UTF-8?q?tement=20condition=20for=20better=20code=20readability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/api/v1/endpoints.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py index 9cacefcd4..813aaf415 100644 --- a/src/backend/langflow/api/v1/endpoints.py +++ b/src/backend/langflow/api/v1/endpoints.py @@ -93,14 +93,14 @@ async def process_flow( tweaks: Optional[dict] = None, clear_cache: Annotated[bool, Body(embed=True)] = False, # noqa: F821 session_id: Annotated[Union[None, str], Body(embed=True)] = None, # noqa: F821 - api_key_user: User =Depends(api_key_security), + api_key_user: User = Depends(api_key_security), ): """ Endpoint to process an input with a given flow_id. """ try: - if api_key_user is None + if api_key_user is None: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid API Key",