Skip to content
Merged
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
7 changes: 7 additions & 0 deletions backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@ async def lifespan(_app: FastAPI) -> AsyncGenerator[None, None]:
system_init_service = SystemInitializationService(db, get_settings())
providers = system_init_service.initialize_providers(raise_on_error=True)
logger.info("Initialized providers: %s", ", ".join(p.name for p in providers))

# Initialize default users (mock user in development mode)
success = system_init_service.initialize_default_users(raise_on_error=True)
if success:
logger.info("Default users initialized successfully")
else:
logger.warning("Default users initialization skipped or failed")
except StopIteration:
logger.error("Failed to get database session")
return
Expand Down
31 changes: 31 additions & 0 deletions backend/rag_solution/services/system_initialization_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,34 @@ def _setup_watsonx_models(self, provider_id: UUID4, raise_on_error: bool) -> Non
logger.error(f"Error setting up WatsonX models: {e!s}")
if raise_on_error:
raise

def initialize_default_users(self, raise_on_error: bool = False) -> bool:
"""Initialize default users based on environment configuration.

In development (SKIP_AUTH=true), creates the mock user for testing.
This ensures users are automatically recreated after database wipes.

Args:
raise_on_error: Whether to raise exceptions on errors

Returns:
bool: True if user initialization succeeded or was skipped, False otherwise
"""
try:
# Only create mock user when authentication is bypassed
if self.settings.skip_auth:
from core.mock_auth import ensure_mock_user_exists

logger.info("Initializing mock user for development (SKIP_AUTH=true)")
user_id = ensure_mock_user_exists(self.db, self.settings)
logger.info(f"Mock user initialized successfully: {user_id}")
return True
else:
logger.info("Authentication enabled, skipping mock user initialization")
return True

except Exception as e:
logger.error(f"Error initializing default users: {e!s}")
if raise_on_error:
raise
return False
55 changes: 55 additions & 0 deletions backend/scripts/create_mock_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env python3
"""Create the mock user in the database.

NOTE: As of the latest version, mock users are automatically created at
application startup via SystemInitializationService.initialize_default_users().

This script is now primarily a backup utility for:
- Manual user creation in emergency situations
- Testing user creation logic independently
- Recovering from user creation failures

For normal operation, simply restart the backend and the mock user will be
automatically created when SKIP_AUTH=true.
"""

import contextlib
import sys
from pathlib import Path

# Add backend to path
sys.path.insert(0, str(Path(__file__).parent.parent))

from sqlalchemy.orm import Session

from core.config import get_settings
from core.mock_auth import ensure_mock_user_exists
from rag_solution.file_management.database import get_db

if __name__ == "__main__":
print("\n🔧 Creating Mock User\n")

settings = get_settings()

# Get database session
db_gen = get_db()
db: Session = next(db_gen)

try:
# Create mock user with full initialization
user_id = ensure_mock_user_exists(db, settings)
print("✓ Mock user created successfully!")
print(f" User ID: {user_id}")
print(f" Email: {settings.mock_user_email}")
print(f" Name: {settings.mock_user_name}")
print()

except Exception as e:
print(f"✗ Error creating mock user: {e}")
import traceback

traceback.print_exc()
sys.exit(1)
finally:
with contextlib.suppress(StopIteration):
next(db_gen)
58 changes: 54 additions & 4 deletions backend/tests/unit/test_system_initialization_service_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from core.config import Settings
from core.custom_exceptions import LLMProviderError
from rag_solution.schemas.llm_model_schema import ModelType
from rag_solution.schemas.llm_provider_schema import LLMProviderInput, LLMProviderOutput
from rag_solution.schemas.llm_provider_schema import LLMProviderInput, LLMProviderOutput, LLMProviderUpdate
from rag_solution.services.system_initialization_service import SystemInitializationService


Expand Down Expand Up @@ -334,9 +334,12 @@ def test_initialize_single_provider_update_existing(self, service):
result = service._initialize_single_provider("openai", config, existing_provider, False)

assert result is updated_provider
service.llm_provider_service.update_provider.assert_called_once_with(
existing_provider.id, config.model_dump(exclude_unset=True)
)
# Verify update_provider was called with LLMProviderUpdate (not dict)
call_args = service.llm_provider_service.update_provider.call_args
assert call_args[0][0] == existing_provider.id
assert isinstance(call_args[0][1], LLMProviderUpdate)
assert call_args[0][1].name == "openai"
assert call_args[0][1].base_url == "https://api.openai.com"

def test_initialize_single_provider_create_error_no_raise(self, service):
"""Test _initialize_single_provider handles create error with raise_on_error=False."""
Expand Down Expand Up @@ -450,3 +453,50 @@ def test_setup_watsonx_models_error_with_raise(self, service):
service._setup_watsonx_models(provider_id, True)

assert "Model creation failed" in str(exc_info.value)

def test_initialize_default_users_skip_auth_true(self, service, mock_settings):
"""Test initialize_default_users creates mock user when SKIP_AUTH=true."""
mock_settings.skip_auth = True
mock_user_id = uuid4()

with patch("core.mock_auth.ensure_mock_user_exists") as mock_ensure_user:
mock_ensure_user.return_value = mock_user_id

result = service.initialize_default_users(raise_on_error=False)

assert result is True
mock_ensure_user.assert_called_once_with(service.db, mock_settings)

def test_initialize_default_users_skip_auth_false(self, service, mock_settings):
"""Test initialize_default_users skips creation when SKIP_AUTH=false."""
mock_settings.skip_auth = False

result = service.initialize_default_users(raise_on_error=False)

assert result is True
# Should not attempt to import or call ensure_mock_user_exists

def test_initialize_default_users_error_no_raise(self, service, mock_settings):
"""Test initialize_default_users handles errors gracefully with raise_on_error=False."""
mock_settings.skip_auth = True

with patch("core.mock_auth.ensure_mock_user_exists") as mock_ensure_user:
mock_ensure_user.side_effect = Exception("User creation failed")

result = service.initialize_default_users(raise_on_error=False)

assert result is False
mock_ensure_user.assert_called_once()

def test_initialize_default_users_error_with_raise(self, service, mock_settings):
"""Test initialize_default_users raises exception when raise_on_error=True."""
mock_settings.skip_auth = True

with patch("core.mock_auth.ensure_mock_user_exists") as mock_ensure_user:
mock_ensure_user.side_effect = Exception("User creation failed")

with pytest.raises(Exception) as exc_info:
service.initialize_default_users(raise_on_error=True)

assert "User creation failed" in str(exc_info.value)
mock_ensure_user.assert_called_once()
Loading