""" Authentication Service Main Application """ from fastapi import FastAPI from sqlalchemy import text from app.core.config import settings from app.core.database import database_manager from app.api import auth, users, onboarding from app.services.messaging import setup_messaging, cleanup_messaging from shared.service_base import StandardFastAPIService class AuthService(StandardFastAPIService): """Authentication Service with standardized setup""" async def on_startup(self, app): """Custom startup logic including migration verification""" await self.verify_migrations() await super().on_startup(app) async def verify_migrations(self): """Verify database schema matches the latest migrations.""" try: async with self.database_manager.get_session() as session: # Check if alembic_version table exists result = await session.execute(text(""" SELECT EXISTS ( SELECT FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'alembic_version' ) """)) table_exists = result.scalar() if table_exists: # If table exists, check the version result = await session.execute(text("SELECT version_num FROM alembic_version")) version = result.scalar() self.logger.info(f"Migration verification successful: {version}") else: # If table doesn't exist, migrations might not have run yet # This is OK - the migration job should create it self.logger.warning("alembic_version table does not exist yet - migrations may not have run") except Exception as e: self.logger.warning(f"Migration verification failed (this may be expected during initial setup): {e}") def __init__(self): # Define expected database tables for health checks auth_expected_tables = [ 'users', 'refresh_tokens', 'user_onboarding_progress', 'user_onboarding_summary', 'login_attempts' ] # Define custom metrics for auth service auth_custom_metrics = { "registration_total": { "type": "counter", "description": "Total user registrations by status", "labels": ["status"] }, "login_success_total": { "type": "counter", "description": "Total successful user logins" }, "login_failure_total": { "type": "counter", "description": "Total failed user logins by reason", "labels": ["reason"] }, "token_refresh_total": { "type": "counter", "description": "Total token refreshes by status", "labels": ["status"] }, "token_verify_total": { "type": "counter", "description": "Total token verifications by status", "labels": ["status"] }, "logout_total": { "type": "counter", "description": "Total user logouts by status", "labels": ["status"] }, "registration_duration_seconds": { "type": "histogram", "description": "Registration request duration" }, "login_duration_seconds": { "type": "histogram", "description": "Login request duration" }, "token_refresh_duration_seconds": { "type": "histogram", "description": "Token refresh duration" } } super().__init__( service_name="auth-service", app_name="Authentication Service", description="Handles user authentication and authorization for bakery forecasting platform", version="1.0.0", log_level=settings.LOG_LEVEL, api_prefix="/api/v1", database_manager=database_manager, expected_tables=auth_expected_tables, enable_messaging=True, custom_metrics=auth_custom_metrics ) async def _setup_messaging(self): """Setup messaging for auth service""" await setup_messaging() self.logger.info("Messaging setup complete") async def _cleanup_messaging(self): """Cleanup messaging for auth service""" await cleanup_messaging() async def on_shutdown(self, app: FastAPI): """Custom shutdown logic for auth service""" self.logger.info("Authentication Service shutdown complete") def get_service_features(self): """Return auth-specific features""" return [ "user_authentication", "token_management", "user_onboarding", "role_based_access", "messaging_integration" ] # Create service instance service = AuthService() # Create FastAPI app with standardized setup app = service.create_app( docs_url="/docs", redoc_url="/redoc" ) # Setup standard endpoints service.setup_standard_endpoints() # Include routers with specific configurations service.add_router(auth.router, prefix="/api/v1/auth", tags=["authentication"]) service.add_router(users.router, prefix="/api/v1/users", tags=["users"]) service.add_router(onboarding.router, prefix="/api/v1/users", tags=["onboarding"])