bmc_hub/main.py

203 lines
6.9 KiB
Python
Raw Normal View History

2025-12-05 14:22:39 +01:00
"""
BMC Hub - FastAPI Application
Main application entry point
"""
import logging
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import RedirectResponse
from contextlib import asynccontextmanager
from app.core.config import settings
from app.core.database import init_db
from app.core.module_loader import module_loader
from app.services.email_scheduler import email_scheduler
# Import CORE Feature Routers (disse forbliver hardcoded)
from app.auth.backend import router as auth_api
from app.auth.backend import views as auth_views
from app.customers.backend import router as customers_api
from app.customers.backend import views as customers_views
from app.contacts.backend import router as contacts_api
from app.contacts.backend import views as contacts_views
from app.vendors.backend import router as vendors_api
from app.vendors.backend import views as vendors_views
from app.settings.backend import router as settings_api
from app.settings.backend import views as settings_views
from app.hardware.backend import router as hardware_api
from app.billing.backend import router as billing_api
from app.billing.frontend import views as billing_views
from app.system.backend import router as system_api
from app.dashboard.backend import views as dashboard_views
from app.dashboard.backend import router as dashboard_api
from app.devportal.backend import router as devportal_api
from app.devportal.backend import views as devportal_views
from app.timetracking.backend import router as timetracking_api
from app.timetracking.frontend import views as timetracking_views
from app.emails.backend import router as emails_api
from app.emails.frontend import views as emails_views
2025-12-05 14:22:39 +01:00
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler(),
logging.FileHandler('logs/app.log')
]
)
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""Lifecycle management - startup and shutdown"""
# Startup
logger.info("🚀 Starting BMC Hub...")
logger.info(f"Database: {settings.DATABASE_URL}")
init_db()
# Start email scheduler (background job)
email_scheduler.start()
# Load dynamic modules (hvis enabled)
if settings.MODULES_ENABLED:
logger.info("📦 Loading dynamic modules...")
module_loader.register_modules(app)
module_status = module_loader.get_module_status()
logger.info(f"✅ Loaded {len(module_status)} modules: {list(module_status.keys())}")
2025-12-05 14:22:39 +01:00
logger.info("✅ System initialized successfully")
yield
# Shutdown
logger.info("👋 Shutting down...")
email_scheduler.stop()
2025-12-05 14:22:39 +01:00
# Create FastAPI app
app = FastAPI(
title="BMC Hub API",
description="""
Central management system for BMC Networks.
**Key Features:**
- Customer management
- Hardware tracking
- Service management
- Billing integration
""",
version="1.0.0",
lifespan=lifespan,
docs_url="/api/docs",
redoc_url="/api/redoc",
openapi_url="/api/openapi.json"
)
@app.get("/")
async def root():
"""Redirect root to dashboard"""
return RedirectResponse(url="/dashboard")
2025-12-05 14:22:39 +01:00
# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=settings.ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include routers
app.include_router(auth_api.router, prefix="/api/v1/auth", tags=["Authentication"])
app.include_router(customers_api.router, prefix="/api/v1", tags=["Customers"])
app.include_router(contacts_api.router, prefix="/api/v1", tags=["Contacts"])
app.include_router(vendors_api.router, prefix="/api/v1", tags=["Vendors"])
app.include_router(settings_api.router, prefix="/api/v1", tags=["Settings"])
app.include_router(hardware_api.router, prefix="/api/v1", tags=["Hardware"])
app.include_router(billing_api.router, prefix="/api/v1", tags=["Billing"])
app.include_router(system_api.router, prefix="/api/v1", tags=["System"])
app.include_router(dashboard_api.router, prefix="/api/v1/dashboard", tags=["Dashboard"])
app.include_router(devportal_api.router, prefix="/api/v1/devportal", tags=["DEV Portal"])
app.include_router(timetracking_api, prefix="/api/v1/timetracking", tags=["Time Tracking"])
app.include_router(emails_api.router, prefix="/api/v1", tags=["Email System"])
# Frontend Routers
app.include_router(auth_views.router, tags=["Frontend"])
app.include_router(dashboard_views.router, tags=["Frontend"])
app.include_router(customers_views.router, tags=["Frontend"])
app.include_router(contacts_views.router, tags=["Frontend"])
app.include_router(vendors_views.router, tags=["Frontend"])
app.include_router(billing_views.router, tags=["Frontend"])
app.include_router(settings_views.router, tags=["Frontend"])
app.include_router(devportal_views.router, tags=["Frontend"])
app.include_router(timetracking_views.router, tags=["Frontend"])
app.include_router(emails_views.router, tags=["Frontend"])
2025-12-05 14:22:39 +01:00
# Serve static files (UI)
app.mount("/static", StaticFiles(directory="static", html=True), name="static")
@app.get("/health")
async def health_check():
"""Health check endpoint"""
return {
"status": "healthy",
"service": "BMC Hub",
"version": "1.0.0"
}
@app.get("/api/v1/modules")
async def list_modules():
"""List alle dynamic modules og deres status"""
return {
"modules_enabled": settings.MODULES_ENABLED,
"modules": module_loader.get_module_status()
}
@app.post("/api/v1/modules/{module_name}/enable")
async def enable_module_endpoint(module_name: str):
"""Enable et modul (kræver restart)"""
success = module_loader.enable_module(module_name)
return {
"success": success,
"message": f"Modul {module_name} enabled. Restart app for at loade.",
"restart_required": True
}
@app.post("/api/v1/modules/{module_name}/disable")
async def disable_module_endpoint(module_name: str):
"""Disable et modul (kræver restart)"""
success = module_loader.disable_module(module_name)
return {
"success": success,
"message": f"Modul {module_name} disabled. Restart app for at unload.",
"restart_required": True
}
2025-12-05 14:22:39 +01:00
if __name__ == "__main__":
import uvicorn
import os
# Only enable reload in local development (not in Docker)
enable_reload = os.getenv("ENABLE_RELOAD", "false").lower() == "true"
if enable_reload:
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8000,
reload=True,
reload_includes=["*.py"],
reload_dirs=["app"],
reload_excludes=[".git/*", "*.pyc", "__pycache__/*", "logs/*", "uploads/*", "data/*"],
2025-12-05 14:22:39 +01:00
log_level="info"
)
else:
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8000,
reload=False
)