fix: A16 — ACL sur l'export et les pièces jointes (v7.3.4)
FlowDeck CI / docker (push) Successful in 1m44s
FlowDeck CI / lint (push) Successful in 1m49s
FlowDeck CI / test (push) Successful in 21m5s

- `export.py` : `_load_page_or_404(request, page_id)` — 401 sans session,
  404 si `PermissionManager.can_view_page` refuse (les 4 formats d'export)
- `dashboard.py` : helper `_require_page_view` sur `GET /api/pages/{id}/download`
  et `GET /api/pages/{id}/file-content`
- +1 test de non-régression → suite **1026/1026**, `ruff check app tests` OK
This commit is contained in:
2026-09-30 23:20:26 -04:00
parent 5a537f5dc3
commit 72fcef2ba9
8 changed files with 57 additions and 12 deletions
+16 -2
View File
@@ -1158,9 +1158,21 @@ def _file_page_disk_path(page: dict):
return (full, filename, mime, size)
def _require_page_view(request: Request, page_id: int) -> None:
"""A16 : lecture d'une pièce jointe = session + `can_view_page` (404 sinon)."""
user = SessionManager.decode_session(request.cookies.get("flowdeck_session", ""))
if not user or not user.get("id"):
raise HTTPException(401, "Authentication required")
from app.services.permission_manager import PermissionManager
if not PermissionManager(user["id"], bool(user.get("is_admin"))).can_view_page(page_id):
raise HTTPException(404, "Page not found")
@router.get("/api/pages/{page_id}/download")
async def download_page_file(page_id: int):
async def download_page_file(request: Request, page_id: int):
"""Download the original uploaded file of a ``file`` page (attachment)."""
_require_page_view(request, page_id)
with get_conn() as conn:
row = conn.execute(
"SELECT id, title, content, content_format FROM pages "
@@ -1181,13 +1193,15 @@ async def download_page_file(page_id: int):
@router.get("/api/pages/{page_id}/file-content")
async def page_file_content(page_id: int):
async def page_file_content(request: Request, page_id: int):
"""Return the textual content of a ``file`` page (for copy to clipboard).
Binary files (PDF, images…) answer ``{ok: false}`` — the clipboard copy is
only meaningful for plain-text / code / markdown files.
"""
from app.services.export import _file_text
_require_page_view(request, page_id)
with get_conn() as conn:
row = conn.execute(
"SELECT id, title, content, content_format FROM pages "