128 lines
4.5 KiB
Python
128 lines
4.5 KiB
Python
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Form, Request
|
|
from fastapi.responses import JSONResponse, RedirectResponse
|
|
|
|
from app.core.db.common import CommonSessionLocal
|
|
from app.core.security.csrf import get_or_create_csrf_token, validate_csrf
|
|
from app.core.security.session_auth import get_current_user
|
|
from app.core.templating import templates
|
|
from app.modules.alerts.service import ALERT_PRIORITIES, count_unread_alerts, list_my_alerts, mark_alert_read, mark_all_alerts_read
|
|
from app.modules.core.rbac.deps import get_user_permissions, get_user_roles
|
|
|
|
router = APIRouter(prefix="/alerts", tags=["alerts-ui"])
|
|
|
|
|
|
def _redirect_login():
|
|
return RedirectResponse(url="/login", status_code=303)
|
|
|
|
|
|
def _base_ctx(request: Request, db, current_user, **ctx):
|
|
base = {
|
|
"request": request,
|
|
"current_user": current_user,
|
|
"current_user_roles": get_user_roles(db, current_user.id),
|
|
"current_user_permissions": get_user_permissions(db, current_user.id),
|
|
"csrf_token": get_or_create_csrf_token(request),
|
|
}
|
|
base.update(ctx)
|
|
return base
|
|
|
|
|
|
@router.get("/poll")
|
|
def poll_unread_alerts(request: Request, limit: int = 5):
|
|
"""Lightweight polling endpoint used by the base layout toast popup.
|
|
|
|
Returns a small list of unread alerts for the logged-in user. It does not
|
|
mark alerts as read; the normal /alerts page and existing read actions
|
|
continue to control read status.
|
|
"""
|
|
db = CommonSessionLocal()
|
|
try:
|
|
current_user = get_current_user(request, db)
|
|
if not current_user:
|
|
return JSONResponse({"authenticated": False, "unread_count": 0, "alerts": []}, status_code=401)
|
|
|
|
safe_limit = max(1, min(int(limit or 5), 10))
|
|
rows = list_my_alerts(db, current_user, status="unread", priority="all", limit=safe_limit)
|
|
payload = []
|
|
for row in rows:
|
|
created_at = getattr(row, "created_at_utc", None)
|
|
payload.append(
|
|
{
|
|
"id": row.id,
|
|
"title": row.title or "Alert",
|
|
"message": row.message or "",
|
|
"priority": row.priority or "normal",
|
|
"alert_type": row.alert_type or "general",
|
|
"target_url": row.target_url or "/alerts",
|
|
"created_at_utc": created_at.isoformat() if created_at else None,
|
|
}
|
|
)
|
|
|
|
return JSONResponse(
|
|
{
|
|
"authenticated": True,
|
|
"unread_count": count_unread_alerts(db, current_user),
|
|
"alerts": payload,
|
|
}
|
|
)
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
@router.get("")
|
|
def alerts_list(request: Request, status: str = "all", priority: str = "all"):
|
|
db = CommonSessionLocal()
|
|
try:
|
|
current_user = get_current_user(request, db)
|
|
if not current_user:
|
|
return _redirect_login()
|
|
status = status if status in {"all", "unread", "read"} else "all"
|
|
priority = priority if priority in ALERT_PRIORITIES else "all"
|
|
rows = list_my_alerts(db, current_user, status=status, priority=priority, limit=150)
|
|
return templates.TemplateResponse(
|
|
"modules/alerts/templates/alerts/list.html",
|
|
_base_ctx(
|
|
request,
|
|
db,
|
|
current_user,
|
|
title="My Alerts",
|
|
alerts=rows,
|
|
status=status,
|
|
priority=priority,
|
|
priorities=ALERT_PRIORITIES,
|
|
unread_count=count_unread_alerts(db, current_user),
|
|
),
|
|
)
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
@router.post("/{alert_id}/read")
|
|
def mark_read(request: Request, alert_id: int, csrf_token: str = Form(...)):
|
|
db = CommonSessionLocal()
|
|
try:
|
|
current_user = get_current_user(request, db)
|
|
if not current_user:
|
|
return _redirect_login()
|
|
validate_csrf(request, csrf_token)
|
|
mark_alert_read(db, current_user, alert_id)
|
|
return RedirectResponse(url="/alerts", status_code=303)
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
@router.post("/read-all")
|
|
def mark_all_read(request: Request, csrf_token: str = Form(...)):
|
|
db = CommonSessionLocal()
|
|
try:
|
|
current_user = get_current_user(request, db)
|
|
if not current_user:
|
|
return _redirect_login()
|
|
validate_csrf(request, csrf_token)
|
|
mark_all_alerts_read(db, current_user)
|
|
return RedirectResponse(url="/alerts", status_code=303)
|
|
finally:
|
|
db.close()
|