From f5bee3e7ae30b18925fd85a5435e0cbbecb26d0d Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Sat, 30 Sep 2023 00:05:29 -0300 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=90=9B=20fix(utils.py):=20handle=20un?= =?UTF-8?q?ique=20constraint=20failure=20when=20creating=20superuser=20and?= =?UTF-8?q?=20check=20if=20superuser=20already=20exists=20with=20the=20sam?= =?UTF-8?q?e=20username=20and=20password=20to=20avoid=20duplicate=20creati?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/utils.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/backend/langflow/services/utils.py b/src/backend/langflow/services/utils.py index 02d9816f5..e18b4938d 100644 --- a/src/backend/langflow/services/utils.py +++ b/src/backend/langflow/services/utils.py @@ -1,4 +1,4 @@ -from langflow.services.auth.utils import create_super_user +from langflow.services.auth.utils import create_super_user, verify_password from langflow.services.database.utils import initialize_database from langflow.services.manager import service_manager from langflow.services.schema import ServiceType @@ -43,10 +43,22 @@ def setup_superuser(settings_service, session): # create superuser create_super_user(db=session, username=username, password=password) except Exception as exc: - logger.exception(exc) - raise RuntimeError( - "Could not create superuser. Please create a superuser manually." - ) from exc + if "UNIQUE constraint failed: user.username" in str(exc): + # check if the password is valid, if it is, we will + # continue normally + # if not, we will raise an error + user = session.query(User).filter(User.username == username).first() + if ( + user + and user.is_superuser is True + and verify_password(password, user.password) + ): + return # superuser already exists + else: + logger.exception(exc) + raise RuntimeError( + "Could not create superuser. Please create a superuser manually." + ) from exc # reset superuser credentials settings_service.auth_settings.reset_credentials() logger.debug("Superuser created successfully.") From 98df4f265515b292bdb61f3a89033f401a093ee6 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 3 Oct 2023 12:49:17 -0300 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=90=9B=20fix(utils.py):=20refactor=20?= =?UTF-8?q?service=20initialization=20to=20improve=20readability=20and=20e?= =?UTF-8?q?rror=20handling=20=E2=9C=A8=20feat(utils.py):=20add=20session?= =?UTF-8?q?=20service=20factory=20and=20dependencies=20to=20support=20sess?= =?UTF-8?q?ion=20management?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/utils.py | 54 +++++++++++++++----------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/backend/langflow/services/utils.py b/src/backend/langflow/services/utils.py index e18b4938d..b85155d8a 100644 --- a/src/backend/langflow/services/utils.py +++ b/src/backend/langflow/services/utils.py @@ -136,30 +136,40 @@ def initialize_services(): from langflow.services.task import factory as task_factory from langflow.services.session import factory as session_service_factory # type: ignore - service_manager.register_factory(settings_factory.SettingsServiceFactory()) - service_manager.register_factory( - auth_factory.AuthServiceFactory(), dependencies=[ServiceType.SETTINGS_SERVICE] - ) - service_manager.register_factory( - database_factory.DatabaseServiceFactory(), - dependencies=[ServiceType.SETTINGS_SERVICE], - ) - service_manager.register_factory( - cache_factory.CacheServiceFactory(), dependencies=[ServiceType.SETTINGS_SERVICE] - ) - service_manager.register_factory(chat_factory.ChatServiceFactory()) + factory_and_dependencies = [ + (settings_factory.SettingsServiceFactory(), []), + ( + auth_factory.AuthServiceFactory(), + [ServiceType.SETTINGS_SERVICE], + ), + ( + database_factory.DatabaseServiceFactory(), + [ServiceType.SETTINGS_SERVICE], + ), + ( + cache_factory.CacheServiceFactory(), + [ServiceType.SETTINGS_SERVICE], + ), + (chat_factory.ChatServiceFactory(), []), + (task_factory.TaskServiceFactory(), []), + ( + session_service_factory.SessionServiceFactory(), + [ServiceType.CACHE_SERVICE], + ), + ] + for factory, dependencies in factory_and_dependencies: + try: + service_manager.register_factory(factory, dependencies=dependencies) + except Exception as exc: + logger.exception(exc) + raise RuntimeError( + "Could not initialize services. Please check your settings." + ) from exc - service_manager.register_factory(task_factory.TaskServiceFactory()) - - service_manager.register_factory( - session_service_factory.SessionServiceFactory(), - dependencies=[ServiceType.CACHE_SERVICE], - ) # Test cache connection service_manager.get(ServiceType.CACHE_SERVICE) - # Test database connection - service_manager.get(ServiceType.DATABASE_SERVICE) # Setup the superuser initialize_database() - session = next(get_session()) - setup_superuser(service_manager.get(ServiceType.SETTINGS_SERVICE), session) + setup_superuser( + service_manager.get(ServiceType.SETTINGS_SERVICE), next(get_session()) + ) From b21ddd1c93e9e76c8289782123d6cb57319339a4 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 3 Oct 2023 14:15:29 -0300 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=94=A7=20fix(utils.py):=20refactor=20?= =?UTF-8?q?setup=5Fsuperuser=20function=20to=20improve=20readability=20and?= =?UTF-8?q?=20maintainability=20=E2=9C=A8=20feat(utils.py):=20add=20get=5F?= =?UTF-8?q?or=5Fcreate=5Fsuper=5Fuser=20function=20to=20handle=20the=20cre?= =?UTF-8?q?ation=20of=20superuser=20and=20handle=20different=20scenarios?= =?UTF-8?q?=20based=20on=20existing=20users=20and=20credentials?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/utils.py | 95 +++++++++++++++----------- 1 file changed, 56 insertions(+), 39 deletions(-) diff --git a/src/backend/langflow/services/utils.py b/src/backend/langflow/services/utils.py index b85155d8a..6a6696faf 100644 --- a/src/backend/langflow/services/utils.py +++ b/src/backend/langflow/services/utils.py @@ -10,58 +10,75 @@ from .getters import get_session, get_settings_service from loguru import logger +def get_or_create_super_user(session, username, password, is_default): + from langflow.services.database.models.user.user import User + + user = session.query(User).filter(User.username == username).first() + + if user and user.is_superuser and verify_password(password, user.password): + return None # Superuser already exists + + if user and is_default: + if user.is_superuser: + if verify_password(password, user.password): + return None + else: + # Superuser exists but password is incorrect + # which means that the user has changed the + # base superuser credentials. + # This means that the user has already created + # a superuser and changed the password in the UI + # so we don't need to do anything. + logger.debug( + "Superuser exists but password is incorrect. " + "This means that the user has changed the " + "base superuser credentials." + ) + return None + else: + logger.debug( + "User with superuser credentials exists but is not a superuser." + ) + return None + + if user: + if verify_password(password, user.password): + raise ValueError( + "User with superuser credentials exists but is not a superuser." + ) + else: + raise ValueError("Incorrect superuser credentials") + + if is_default: + logger.debug("Creating default superuser.") + else: + logger.debug("Creating superuser.") + + return create_super_user(session, username, password) + + def setup_superuser(settings_service, session): - """ - Setup the superuser. - """ - # We will use the SUPERUSER and SUPERUSER_PASSWORD - # vars on settings_manager.auth_settings to create the superuser - # if it does not exist. if settings_service.auth_settings.AUTO_LOGIN: logger.debug("AUTO_LOGIN is set to True. Creating default superuser.") username = settings_service.auth_settings.SUPERUSER password = settings_service.auth_settings.SUPERUSER_PASSWORD - if username == DEFAULT_SUPERUSER and password == DEFAULT_SUPERUSER_PASSWORD: - logger.debug("Default superuser credentials detected.") - logger.debug("Creating default superuser.") - else: - logger.debug("Creating superuser.") + + is_default = (username == DEFAULT_SUPERUSER) and ( + password == DEFAULT_SUPERUSER_PASSWORD + ) try: - from langflow.services.database.models.user.user import User - - user = session.query(User).filter(User.username == username).first() - if user and user.is_superuser is True: - return + user = get_or_create_super_user(session, username, password, is_default) + if user is not None: + logger.debug("Superuser created successfully.") except Exception as exc: logger.exception(exc) raise RuntimeError( "Could not create superuser. Please create a superuser manually." ) from exc - try: - # create superuser - create_super_user(db=session, username=username, password=password) - except Exception as exc: - if "UNIQUE constraint failed: user.username" in str(exc): - # check if the password is valid, if it is, we will - # continue normally - # if not, we will raise an error - user = session.query(User).filter(User.username == username).first() - if ( - user - and user.is_superuser is True - and verify_password(password, user.password) - ): - return # superuser already exists - else: - logger.exception(exc) - raise RuntimeError( - "Could not create superuser. Please create a superuser manually." - ) from exc - # reset superuser credentials - settings_service.auth_settings.reset_credentials() - logger.debug("Superuser created successfully.") + finally: + settings_service.auth_settings.reset_credentials() def teardown_superuser(settings_service, session): From 7390c91028994c6964afc123a2539bc7e9fd093b Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 3 Oct 2023 14:27:12 -0300 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=94=A7=20chore(utils.py):=20add=20typ?= =?UTF-8?q?e=20hinting=20to=20the=20get=5For=5Fcreate=5Fsuper=5Fuser=20fun?= =?UTF-8?q?ction=20to=20improve=20code=20readability=20and=20maintainabili?= =?UTF-8?q?ty=20=F0=9F=94=A7=20chore(utils.py):=20add=20type=20hinting=20t?= =?UTF-8?q?o=20the=20session=20parameter=20in=20the=20get=5For=5Fcreate=5F?= =?UTF-8?q?super=5Fuser=20function=20to=20improve=20code=20readability=20a?= =?UTF-8?q?nd=20maintainability=20=F0=9F=94=A7=20chore(utils.py):=20add=20?= =?UTF-8?q?type=20hinting=20to=20the=20session=20parameter=20in=20the=20se?= =?UTF-8?q?tup=5Fsuperuser=20function=20to=20improve=20code=20readability?= =?UTF-8?q?=20and=20maintainability=20=F0=9F=94=A7=20chore(utils.py):=20ad?= =?UTF-8?q?d=20type=20hinting=20to=20the=20session=20parameter=20in=20the?= =?UTF-8?q?=20setup=5Fsuperuser=20function=20to=20improve=20code=20readabi?= =?UTF-8?q?lity=20and=20maintainability=20=F0=9F=94=A7=20chore(utils.py):?= =?UTF-8?q?=20add=20type=20hinting=20to=20the=20session=20parameter=20in?= =?UTF-8?q?=20the=20setup=5Fsuperuser=20function=20to=20improve=20code=20r?= =?UTF-8?q?eadability=20and=20maintainability=20=F0=9F=94=A7=20chore(utils?= =?UTF-8?q?.py):=20add=20type=20hinting=20to=20the=20session=20parameter?= =?UTF-8?q?=20in=20the=20setup=5Fsuperuser=20function=20to=20improve=20cod?= =?UTF-8?q?e=20readability=20and=20maintainability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/utils.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/backend/langflow/services/utils.py b/src/backend/langflow/services/utils.py index 6a6696faf..20c23f8c0 100644 --- a/src/backend/langflow/services/utils.py +++ b/src/backend/langflow/services/utils.py @@ -6,11 +6,12 @@ from langflow.services.settings.constants import ( DEFAULT_SUPERUSER, DEFAULT_SUPERUSER_PASSWORD, ) +from sqlmodel import Session from .getters import get_session, get_settings_service from loguru import logger -def get_or_create_super_user(session, username, password, is_default): +def get_or_create_super_user(session: Session, username, password, is_default): from langflow.services.database.models.user.user import User user = session.query(User).filter(User.username == username).first() @@ -54,10 +55,10 @@ def get_or_create_super_user(session, username, password, is_default): else: logger.debug("Creating superuser.") - return create_super_user(session, username, password) + return create_super_user(username, password, db=session) -def setup_superuser(settings_service, session): +def setup_superuser(settings_service, session: Session): if settings_service.auth_settings.AUTO_LOGIN: logger.debug("AUTO_LOGIN is set to True. Creating default superuser.") @@ -69,7 +70,9 @@ def setup_superuser(settings_service, session): ) try: - user = get_or_create_super_user(session, username, password, is_default) + user = get_or_create_super_user( + session=session, username=username, password=password, is_default=is_default + ) if user is not None: logger.debug("Superuser created successfully.") except Exception as exc: