Files
onever_drive/backend/app/main.py
T

105 lines
3.7 KiB
Python

from contextlib import asynccontextmanager
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import select
from app.core.config import settings
from app.core.database import init_db, AsyncSessionLocal
from app.core.security import get_password_hash
from app.models.models import User
from app.api.auth import router as auth_router
from app.api.clients import router as clients_router
from app.api.jobs import router as jobs_router
from app.api.upload import router as upload_router
from app.api.backups import router as backups_router
from app.api.events import router as events_router
from app.api.stats import router as stats_router
from app.api.settings import router as settings_router
from app.ws.manager import ws_manager
@asynccontextmanager
async def lifespan(app: FastAPI):
# Initialize database tables
await init_db()
# Seed default administrator and initialize settings
async with AsyncSessionLocal() as session:
# Load and apply settings to storage_provider
from app.services.settings_service import get_all_settings
settings_dict = await get_all_settings(session)
# Apply storage_root
from app.storage.local import storage_provider
from pathlib import Path
import os
storage_root = settings_dict.get("storage_root")
if storage_root:
path = Path(storage_root).resolve()
os.makedirs(path, exist_ok=True)
storage_provider.root_dir = path
result = await session.execute(select(User))
admin = result.scalar_one_or_none()
if not admin:
admin_user = User(
email="admin@oneverdrive.local",
hashed_password=get_password_hash("Admin1234!"),
full_name="System Administrator",
role="ADMIN",
is_active=True
)
session.add(admin_user)
await session.commit()
print(">> [OnEver Drive] Default admin created: admin@oneverdrive.local / Admin1234!")
yield
app = FastAPI(
title=settings.PROJECT_NAME,
version=settings.VERSION,
description="Centralized Backup & Sync Platform for Windows on Proxmox VE",
lifespan=lifespan
)
# CORS Middleware to allow Web UI connections
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Register API Routers
app.include_router(auth_router, prefix=settings.API_V1_PREFIX)
app.include_router(clients_router, prefix=settings.API_V1_PREFIX)
app.include_router(jobs_router, prefix=settings.API_V1_PREFIX)
app.include_router(upload_router, prefix=settings.API_V1_PREFIX)
app.include_router(backups_router, prefix=settings.API_V1_PREFIX)
app.include_router(events_router, prefix=settings.API_V1_PREFIX)
app.include_router(stats_router, prefix=settings.API_V1_PREFIX)
app.include_router(settings_router, prefix=settings.API_V1_PREFIX)
@app.websocket("/ws/telemetry")
async def websocket_telemetry(websocket: WebSocket):
"""WebSocket endpoint for real-time dashboard telemetry and live upload meters."""
await ws_manager.connect(websocket)
try:
while True:
# Keep connection open and accept incoming ping/pong or messages
data = await websocket.receive_text()
if data == "ping":
await websocket.send_text("pong")
except WebSocketDisconnect:
ws_manager.disconnect(websocket)
except Exception:
ws_manager.disconnect(websocket)
@app.get("/health")
async def health():
return {
"status": "healthy",
"service": settings.PROJECT_NAME,
"version": settings.VERSION
}