from __future__ import annotations import re from fastapi import APIRouter, Request from fastapi.responses import RedirectResponse, StreamingResponse from app.core.db.common import CommonSessionLocal from app.core.http_responses import ui_access_denied from app.core.security.csrf import get_or_create_csrf_token from app.core.security.session_auth import get_current_user from app.core.templating import templates from app.modules.core.rbac.deps import get_user_permissions, get_user_roles from app.modules.peer_review_export.service import ( build_peer_review_evidence, build_peer_review_zip, can_view_peer_review_export, list_peer_review_engagements, ) router = APIRouter(prefix="/peer-review", tags=["peer-review-evidence-export-ui"]) def _ctx(request: Request, db, user, **extra): base = { "request": request, "current_user": user, "current_user_roles": get_user_roles(db, user.id), "current_user_permissions": get_user_permissions(db, user.id), "csrf_token": get_or_create_csrf_token(request), "title": "Peer Review Evidence Export", } base.update(extra) return base def _safe_filename(value: str) -> str: value = re.sub(r"[^A-Za-z0-9._-]+", "_", str(value or "").strip()) value = value.strip("._") return value or "peer_review_evidence" @router.get("/evidence") def evidence_index(request: Request, financial_year: str = "", q: str = ""): db = CommonSessionLocal() try: user = get_current_user(request, db=db) if not user: return RedirectResponse(url="/login", status_code=303) if not can_view_peer_review_export(db, user): return ui_access_denied() payload = list_peer_review_engagements(db, request, user, financial_year=financial_year, q=q) return templates.TemplateResponse( "modules/peer_review_export/templates/peer_review_export/index.html", _ctx(request, db, user, **payload), ) finally: db.close() @router.get("/evidence/{subscription_id}") def evidence_detail(request: Request, subscription_id: int): db = CommonSessionLocal() try: user = get_current_user(request, db=db) if not user: return RedirectResponse(url="/login", status_code=303) if not can_view_peer_review_export(db, user): return ui_access_denied() try: payload = build_peer_review_evidence(db, request, user, subscription_id) except ValueError: return ui_access_denied() return templates.TemplateResponse( "modules/peer_review_export/templates/peer_review_export/detail.html", _ctx(request, db, user, **payload), ) finally: db.close() @router.get("/evidence/{subscription_id}/export.zip") def evidence_export_zip(request: Request, subscription_id: int): db = CommonSessionLocal() try: user = get_current_user(request, db=db) if not user: return RedirectResponse(url="/login", status_code=303) if not can_view_peer_review_export(db, user): return ui_access_denied() try: payload = build_peer_review_evidence(db, request, user, subscription_id) data = build_peer_review_zip(db, request, user, subscription_id) except ValueError: return ui_access_denied() sub = payload["subscription"] client_name = sub.client.client_name if sub.client else "client" service_name = sub.catalogue.service_name if sub.catalogue else "service" filename = _safe_filename(f"peer_review_{client_name}_{service_name}_{sub.financial_year or 'fy'}_{sub.id}.zip") return StreamingResponse( iter([data]), media_type="application/zip", headers={"Content-Disposition": f'attachment; filename="{filename}"'}, ) finally: db.close()