new changes

This commit is contained in:
Niranjan
2026-04-07 13:30:25 +05:30
parent 6dea3b4307
commit 7b394d6446
10 changed files with 197 additions and 7 deletions

View File

@@ -1,4 +1,6 @@
"""YakPanel - Dashboard API"""
import os
from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func
@@ -10,6 +12,24 @@ from app.models.user import User
router = APIRouter(prefix="/dashboard", tags=["dashboard"])
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,
}
@router.get("/stats")
async def get_stats(
current_user: User = Depends(get_current_user),
@@ -18,10 +38,10 @@ async def get_stats(
"""Get dashboard statistics"""
import psutil
from app.services.site_service import get_site_count
from app.services.site_service import get_site_count, ssl_alert_summary
from app.models.ftp import Ftp
from app.models.database import Database
from sqlalchemy import select, func
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
@@ -32,11 +52,14 @@ async def get_stats(
cpu_percent = psutil.cpu_percent(interval=1)
memory = psutil.virtual_memory()
disk = psutil.disk_usage("/")
inodes = _root_inode_usage()
ssl_alerts = await ssl_alert_summary(db)
return {
"site_count": site_count,
"ftp_count": ftp_count,
"database_count": database_count,
"ssl_alerts": ssl_alerts,
"system": {
"cpu_percent": cpu_percent,
"memory_percent": memory.percent,
@@ -45,5 +68,8 @@ async def get_stats(
"disk_percent": disk.percent,
"disk_used_gb": round(disk.used / 1024 / 1024 / 1024, 2),
"disk_total_gb": round(disk.total / 1024 / 1024 / 1024, 2),
"inode_percent": inodes["percent"],
"inode_used": inodes["used"],
"inode_total": inodes["total"],
},
}

View File

@@ -20,6 +20,38 @@ class CreateFirewallRuleRequest(BaseModel):
ps: str = ""
@router.get("/status")
async def firewall_backend_status(current_user: User = Depends(get_current_user)):
"""UFW and firewalld presence/state for the Security UI (read-only)."""
ufw_out, _ = exec_shell_sync("ufw status 2>/dev/null", timeout=5)
ufw_text = (ufw_out or "").strip()
ufw_detected = bool(ufw_text) and "Status:" in ufw_text
ufw_active: bool | None = None
if ufw_detected:
if "Status: active" in ufw_text:
ufw_active = True
elif "Status: inactive" in ufw_text:
ufw_active = False
fw_state_out, _ = exec_shell_sync("firewall-cmd --state 2>/dev/null", timeout=5)
fw_line = (fw_state_out or "").strip().lower()
firewalld_running = fw_line == "running"
firewalld_detected = fw_line in ("running", "not running")
return {
"ufw": {
"detected": ufw_detected,
"active": ufw_active,
"summary_line": ufw_text.split("\n")[0] if ufw_text else "",
},
"firewalld": {
"detected": firewalld_detected,
"running": firewalld_running,
"state": fw_line or None,
},
}
@router.get("/list")
async def firewall_list(
current_user: User = Depends(get_current_user),