Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add option to disable automatic superuser creation and streamline initialization #6082

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 2 additions & 28 deletions src/backend/base/langflow/initial_setup/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,11 @@

from langflow.base.constants import FIELD_FORMAT_ATTRIBUTES, NODE_FORMAT_ATTRIBUTES, ORJSON_OPTIONS
from langflow.initial_setup.constants import STARTER_FOLDER_DESCRIPTION, STARTER_FOLDER_NAME
from langflow.services.auth.utils import create_super_user
from langflow.services.database.models.flow.model import Flow, FlowCreate
from langflow.services.database.models.folder.model import Folder, FolderCreate
from langflow.services.database.models.folder.utils import (
create_default_folder_if_it_doesnt_exist,
get_default_folder_id,
)
from langflow.services.database.models.folder.utils import get_default_folder_id
from langflow.services.database.models.user.crud import get_user_by_username
from langflow.services.deps import (
get_settings_service,
get_storage_service,
get_variable_service,
session_scope,
)
from langflow.services.deps import get_settings_service, get_storage_service, session_scope
from langflow.template.field.prompt import DEFAULT_PROMPT_INTUT_TYPES
from langflow.utils.util import escape_json_dump

Expand Down Expand Up @@ -763,20 +754,3 @@ async def create_or_update_starter_projects(all_types_dict: dict, *, do_create:
project_tags=project_tags,
new_folder_id=new_folder.id,
)


async def initialize_super_user_if_needed() -> None:
settings_service = get_settings_service()
if not settings_service.auth_settings.AUTO_LOGIN:
return
username = settings_service.auth_settings.SUPERUSER
password = settings_service.auth_settings.SUPERUSER_PASSWORD
if not username or not password:
msg = "SUPERUSER and SUPERUSER_PASSWORD must be set in the settings if AUTO_LOGIN is true."
raise ValueError(msg)

async with session_scope() as async_session:
super_user = await create_super_user(db=async_session, username=username, password=password)
await get_variable_service().initialize_user_variables(super_user.id, async_session)
await create_default_folder_if_it_doesnt_exist(async_session, super_user.id)
logger.info("Super user initialized")
2 changes: 0 additions & 2 deletions src/backend/base/langflow/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from langflow.api import health_check_router, log_router, router
from langflow.initial_setup.setup import (
create_or_update_starter_projects,
initialize_super_user_if_needed,
load_bundles_from_urls,
load_flows_from_directory,
)
Expand Down Expand Up @@ -120,7 +119,6 @@ async def lifespan(_app: FastAPI):
try:
await initialize_services(fix_migration=fix_migration)
setup_llm_caching()
await initialize_super_user_if_needed()
temp_dirs, bundles_components_paths = await load_bundles_with_error_handling()
get_settings_service().settings.components_path.extend(bundles_components_paths)
all_types_dict = await get_and_cache_all_types_dict(get_settings_service())
Expand Down
3 changes: 3 additions & 0 deletions src/backend/base/langflow/services/settings/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ class AuthSettings(BaseSettings):

model_config = SettingsConfigDict(validate_assignment=True, extra="ignore", env_prefix="LANGFLOW_")

disable_superuser_creation: bool = False
"""If True, the superuser will not be created automatically."""

def reset_credentials(self) -> None:
self.SUPERUSER = DEFAULT_SUPERUSER
self.SUPERUSER_PASSWORD = DEFAULT_SUPERUSER_PASSWORD
Expand Down
33 changes: 29 additions & 4 deletions src/backend/base/langflow/services/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,24 @@
from sqlalchemy import delete
from sqlalchemy import exc as sqlalchemy_exc
from sqlmodel import col, select
from sqlmodel.ext.asyncio.session import AsyncSession

from langflow.services.auth.utils import create_super_user, verify_password
from langflow.services.cache.factory import CacheServiceFactory
from langflow.services.database.models.folder.utils import create_default_folder_if_it_doesnt_exist
from langflow.services.database.models.transactions.model import TransactionTable
from langflow.services.database.models.vertex_builds.model import VertexBuildTable
from langflow.services.database.utils import initialize_database
from langflow.services.schema import ServiceType
from langflow.services.settings.constants import DEFAULT_SUPERUSER, DEFAULT_SUPERUSER_PASSWORD
from langflow.services.settings.manager import SettingsService

from .deps import get_db_service, get_service, get_settings_service
from .deps import get_db_service, get_service, get_settings_service, get_variable_service

if TYPE_CHECKING:
from sqlmodel.ext.asyncio.session import AsyncSession

from langflow.services.database.models.user.model import User
from langflow.services.settings.manager import SettingsService


Expand Down Expand Up @@ -75,7 +79,7 @@ async def get_or_create_super_user(session: AsyncSession, username, password, is
logger.opt(exception=True).debug("Error creating superuser.")


async def setup_superuser(settings_service, session: AsyncSession) -> None:
async def setup_superuser(settings_service, session: AsyncSession) -> User:
if settings_service.auth_settings.AUTO_LOGIN:
logger.debug("AUTO_LOGIN is set to True. Creating default superuser.")
else:
Expand All @@ -86,7 +90,7 @@ async def setup_superuser(settings_service, session: AsyncSession) -> None:
password = settings_service.auth_settings.SUPERUSER_PASSWORD

is_default = (username == DEFAULT_SUPERUSER) and (password == DEFAULT_SUPERUSER_PASSWORD)

user = None
try:
user = await get_or_create_super_user(
session=session, username=username, password=password, is_default=is_default
Expand All @@ -99,6 +103,7 @@ async def setup_superuser(settings_service, session: AsyncSession) -> None:
raise RuntimeError(msg) from exc
finally:
settings_service.auth_settings.reset_credentials()
return user


async def teardown_superuser(settings_service, session: AsyncSession) -> None:
Expand Down Expand Up @@ -226,6 +231,26 @@ async def clean_vertex_builds(settings_service: SettingsService, session: AsyncS
# Don't re-raise since this is a cleanup task


async def initialize_super_user_if_needed(
settings_service: SettingsService | None = None, session: AsyncSession | None = None
) -> None:
if settings_service is None:
settings_service = get_settings_service()
if not settings_service.auth_settings.AUTO_LOGIN or settings_service.auth_settings.disable_superuser_creation:
return
username = settings_service.auth_settings.SUPERUSER
password = settings_service.auth_settings.SUPERUSER_PASSWORD
if not username or not password:
msg = "SUPERUSER and SUPERUSER_PASSWORD must be set in the settings if AUTO_LOGIN is true."
raise ValueError(msg)
user = await setup_superuser(settings_service, session)
if user is None:
return
await get_variable_service().initialize_user_variables(user.id, session)
await create_default_folder_if_it_doesnt_exist(session, user.id)
logger.info("Super user initialized")


async def initialize_services(*, fix_migration: bool = False) -> None:
"""Initialize all the services needed."""
# Test cache connection
Expand All @@ -236,7 +261,7 @@ async def initialize_services(*, fix_migration: bool = False) -> None:
await db_service.initialize_alembic_log_file()
async with db_service.with_session() as session:
settings_service = get_service(ServiceType.SETTINGS_SERVICE)
await setup_superuser(settings_service, session)
await initialize_super_user_if_needed(settings_service, session)
try:
await get_db_service().assign_orphaned_flows_to_superuser()
except sqlalchemy_exc.IntegrityError as exc:
Expand Down
3 changes: 1 addition & 2 deletions src/backend/tests/performance/test_server_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ def test_setup_llm_caching():

async def test_initialize_super_user():
"""Benchmark super user initialization."""
from langflow.initial_setup.setup import initialize_super_user_if_needed
from langflow.services.utils import initialize_services
from langflow.services.utils import initialize_services, initialize_super_user_if_needed

await initialize_services(fix_migration=False)
await initialize_super_user_if_needed()
Expand Down
Loading