Add RBAC: admin user management, audit log, runtime settings, delete PC
This commit is contained in:
@@ -10,10 +10,20 @@ from typing import List, Optional
|
||||
|
||||
from config import get_settings
|
||||
from database import get_db
|
||||
from models import Computer, Heartbeat, Notification
|
||||
from schemas import HeartbeatPayload, ComputerOut, ComputerDetailOut, HeartbeatOut, NotificationOut
|
||||
from auth import get_current_user
|
||||
from models import Computer, Heartbeat, Notification, AuditLog
|
||||
from schemas import (
|
||||
HeartbeatPayload,
|
||||
ComputerOut,
|
||||
ComputerDetailOut,
|
||||
HeartbeatOut,
|
||||
NotificationOut,
|
||||
AuditLogOut,
|
||||
SettingOut,
|
||||
SettingsUpdate,
|
||||
)
|
||||
from auth import get_current_user, require_admin, log_action
|
||||
from notifications import check_offline_computers, mark_notification_read
|
||||
from settings_store import get_setting, set_setting, get_all_settings
|
||||
|
||||
router = APIRouter(prefix="/api", tags=["api"])
|
||||
settings = get_settings()
|
||||
@@ -33,7 +43,8 @@ def heartbeat(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
token = get_agent_token(request)
|
||||
if token != settings.AGENT_TOKEN:
|
||||
expected = get_setting(db, "AGENT_TOKEN") or settings.AGENT_TOKEN
|
||||
if token != expected:
|
||||
raise HTTPException(status_code=401, detail="Invalid agent token")
|
||||
|
||||
now = datetime.now(timezone.utc)
|
||||
@@ -140,6 +151,23 @@ def get_computer(
|
||||
return computer
|
||||
|
||||
|
||||
@router.delete("/computers/{computer_id}")
|
||||
def delete_computer(
|
||||
computer_id: int,
|
||||
db: Session = Depends(get_db),
|
||||
admin=Depends(require_admin),
|
||||
):
|
||||
computer = db.query(Computer).filter(Computer.id == computer_id).first()
|
||||
if not computer:
|
||||
raise HTTPException(status_code=404, detail="Computer not found")
|
||||
|
||||
hostname = computer.hostname
|
||||
db.delete(computer)
|
||||
db.commit()
|
||||
log_action(db, admin, "computer_deleted", f"Deleted computer {hostname} (id={computer_id})")
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
@router.get("/computers/export/csv")
|
||||
def export_csv(
|
||||
status: Optional[str] = None,
|
||||
@@ -230,3 +258,40 @@ def read_all_notifications(
|
||||
)
|
||||
db.commit()
|
||||
return {"ok": True}
|
||||
|
||||
|
||||
# Admin: audit log
|
||||
|
||||
@router.get("/audit", response_model=List[AuditLogOut])
|
||||
def list_audit(
|
||||
limit: int = 200,
|
||||
db: Session = Depends(get_db),
|
||||
admin=Depends(require_admin),
|
||||
):
|
||||
return db.query(AuditLog).order_by(desc(AuditLog.timestamp)).limit(limit).all()
|
||||
|
||||
|
||||
# Admin: settings
|
||||
|
||||
@router.get("/settings")
|
||||
def list_settings(
|
||||
db: Session = Depends(get_db),
|
||||
admin=Depends(require_admin),
|
||||
):
|
||||
return get_all_settings(db)
|
||||
|
||||
|
||||
@router.post("/settings")
|
||||
def update_settings(
|
||||
payload: SettingsUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
admin=Depends(require_admin),
|
||||
):
|
||||
changed = []
|
||||
data = payload.model_dump(exclude_unset=True)
|
||||
for key, value in data.items():
|
||||
set_setting(db, key, value)
|
||||
changed.append(key)
|
||||
if changed:
|
||||
log_action(db, admin, "settings_updated", f"Updated: {', '.join(changed)}")
|
||||
return get_all_settings(db)
|
||||
|
||||
Reference in New Issue
Block a user