2026-04-07 02:04:22 +05:30
|
|
|
"""YakPanel - Dashboard API"""
|
2026-04-07 13:30:25 +05:30
|
|
|
import os
|
|
|
|
|
|
2026-04-07 02:04:22 +05:30
|
|
|
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.api.auth import get_current_user
|
|
|
|
|
from app.models.user import User
|
|
|
|
|
|
|
|
|
|
router = APIRouter(prefix="/dashboard", tags=["dashboard"])
|
|
|
|
|
|
|
|
|
|
|
2026-04-07 13:30:25 +05:30
|
|
|
def _root_inode_usage() -> dict:
|
|
|
|
|
"""Inode use on filesystem root (Linux). Returns percent or null if unavailable."""
|
|
|
|
|
try:
|
|
|
|
|
sv = os.statvfs("/")
|
|
|
|
|
except (AttributeError, OSError):
|
|
|
|
|
return {"percent": None, "used": None, "total": None}
|
|
|
|
|
total = int(sv.f_files)
|
|
|
|
|
free = int(sv.f_ffree)
|
|
|
|
|
if total <= 0:
|
|
|
|
|
return {"percent": None, "used": None, "total": None}
|
|
|
|
|
used = max(0, total - free)
|
|
|
|
|
return {
|
|
|
|
|
"percent": round(100.0 * used / total, 1),
|
|
|
|
|
"used": used,
|
|
|
|
|
"total": total,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-04-07 02:04:22 +05:30
|
|
|
@router.get("/stats")
|
|
|
|
|
async def get_stats(
|
|
|
|
|
current_user: User = Depends(get_current_user),
|
|
|
|
|
db: AsyncSession = Depends(get_db),
|
|
|
|
|
):
|
|
|
|
|
"""Get dashboard statistics"""
|
|
|
|
|
import psutil
|
|
|
|
|
|
2026-04-07 13:30:25 +05:30
|
|
|
from app.services.site_service import get_site_count, ssl_alert_summary
|
2026-04-07 02:04:22 +05:30
|
|
|
from app.models.ftp import Ftp
|
|
|
|
|
from app.models.database import Database
|
2026-04-07 13:30:25 +05:30
|
|
|
|
2026-04-07 02:04:22 +05:30
|
|
|
site_count = await get_site_count(db)
|
|
|
|
|
ftp_result = await db.execute(select(func.count()).select_from(Ftp))
|
|
|
|
|
ftp_count = ftp_result.scalar() or 0
|
|
|
|
|
db_result = await db.execute(select(func.count()).select_from(Database))
|
|
|
|
|
database_count = db_result.scalar() or 0
|
|
|
|
|
|
|
|
|
|
# System stats
|
|
|
|
|
cpu_percent = psutil.cpu_percent(interval=1)
|
|
|
|
|
memory = psutil.virtual_memory()
|
|
|
|
|
disk = psutil.disk_usage("/")
|
2026-04-07 13:30:25 +05:30
|
|
|
inodes = _root_inode_usage()
|
|
|
|
|
ssl_alerts = await ssl_alert_summary(db)
|
2026-04-07 02:04:22 +05:30
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
"site_count": site_count,
|
|
|
|
|
"ftp_count": ftp_count,
|
|
|
|
|
"database_count": database_count,
|
2026-04-07 13:30:25 +05:30
|
|
|
"ssl_alerts": ssl_alerts,
|
2026-04-07 02:04:22 +05:30
|
|
|
"system": {
|
|
|
|
|
"cpu_percent": cpu_percent,
|
|
|
|
|
"memory_percent": memory.percent,
|
|
|
|
|
"memory_used_mb": round(memory.used / 1024 / 1024, 1),
|
|
|
|
|
"memory_total_mb": round(memory.total / 1024 / 1024, 1),
|
|
|
|
|
"disk_percent": disk.percent,
|
|
|
|
|
"disk_used_gb": round(disk.used / 1024 / 1024 / 1024, 2),
|
|
|
|
|
"disk_total_gb": round(disk.total / 1024 / 1024 / 1024, 2),
|
2026-04-07 13:30:25 +05:30
|
|
|
"inode_percent": inodes["percent"],
|
|
|
|
|
"inode_used": inodes["used"],
|
|
|
|
|
"inode_total": inodes["total"],
|
2026-04-07 02:04:22 +05:30
|
|
|
},
|
|
|
|
|
}
|