feat: Initial commit for OnEver Drive centralized backup system with Windows PyQt6 agent and Proxmox LXC deployment

This commit is contained in:
2026-08-13 19:33:44 -03:00
commit 1bfb808c79
77 changed files with 10675 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
from datetime import datetime, timezone, timedelta
from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
from app.core.database import get_db
from app.models.models import Client, BackupJob, BackupSession, User
from app.schemas.schemas import DashboardStatsResponse
from app.api.deps import get_current_user
from app.storage.local import storage_provider
router = APIRouter(prefix="/stats", tags=["Dashboard Statistics"])
@router.get("", response_model=DashboardStatsResponse)
async def get_dashboard_stats(
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user)
):
# Clients aggregation
total_clients_res = await db.execute(select(func.count(Client.id)).where(Client.is_active == True))
total_clients = total_clients_res.scalar() or 0
# Consider online if last_seen_at was in the last 5 minutes
cutoff_online = datetime.now(timezone.utc) - timedelta(minutes=5)
online_clients_res = await db.execute(
select(func.count(Client.id)).where(
Client.is_active == True,
Client.status == "ONLINE",
Client.last_seen_at >= cutoff_online
)
)
online_clients = online_clients_res.scalar() or 0
offline_clients = max(0, total_clients - online_clients)
# Jobs count
total_jobs_res = await db.execute(select(func.count(BackupJob.id)).where(BackupJob.is_active == True))
total_jobs = total_jobs_res.scalar() or 0
# Backups today
today_start = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
backups_today_res = await db.execute(
select(func.count(BackupSession.id)).where(BackupSession.started_at >= today_start)
)
backups_today = backups_today_res.scalar() or 0
backups_success_res = await db.execute(
select(func.count(BackupSession.id)).where(
BackupSession.started_at >= today_start,
BackupSession.status == "SUCCESS"
)
)
backups_success = backups_success_res.scalar() or 0
backups_failed_res = await db.execute(
select(func.count(BackupSession.id)).where(
BackupSession.started_at >= today_start,
BackupSession.status == "FAILED"
)
)
backups_failed = backups_failed_res.scalar() or 0
# Active uploads
active_uploads_res = await db.execute(
select(func.count(BackupSession.id)).where(BackupSession.status.in_(["PENDING", "UPLOADING", "ASSEMBLING"]))
)
active_uploads = active_uploads_res.scalar() or 0
# Storage metrics
storage_stats = await storage_provider.get_storage_stats()
return {
"total_clients": total_clients,
"online_clients": online_clients,
"offline_clients": offline_clients,
"total_jobs": total_jobs,
"backups_today_count": backups_today,
"backups_today_success": backups_success,
"backups_today_failed": backups_failed,
"active_uploads_count": active_uploads,
"storage": storage_stats
}