63 lines
3.1 KiB
Python
63 lines
3.1 KiB
Python
"""Authenticated read/download endpoints for the operational journal."""
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from datetime import datetime
|
|
from typing import Literal
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query, Response
|
|
from fastapi.responses import StreamingResponse
|
|
|
|
from .auth_bridge import HockeyUser
|
|
from .program_log import MOSCOW, ProgramLogStore
|
|
|
|
|
|
def create_program_log_router(store: ProgramLogStore, auth_dependency):
|
|
router = APIRouter(prefix="/api/hockey/program-logs", tags=["program-log"])
|
|
|
|
async def administrator(user: HockeyUser = Depends(auth_dependency)):
|
|
if not user.is_admin:
|
|
raise HTTPException(403, "Журнал программы доступен администратору")
|
|
return user
|
|
|
|
def filters(preset: Literal["today", "week", "month", "all"] = "week",
|
|
date_from: str = Query("", max_length=10), date_to: str = Query("", max_length=10),
|
|
level: str = Query("", max_length=10), category: str = Query("", max_length=120),
|
|
actor: str = Query("", max_length=200), game_id: str = Query("", max_length=100),
|
|
device_id: str = Query("", max_length=160), q: str = Query("", max_length=300),
|
|
sort: Literal["asc", "desc"] = "desc"):
|
|
result = dict(preset=preset, date_from=date_from, date_to=date_to, level=level,
|
|
category=category, actor=actor, game_id=game_id, device_id=device_id, q=q, sort=sort)
|
|
try:
|
|
store._filters(result)
|
|
except ValueError as error:
|
|
raise HTTPException(422, str(error)) from error
|
|
return result
|
|
|
|
@router.get("/options")
|
|
async def options(response: Response, user: HockeyUser = Depends(administrator)):
|
|
response.headers["Cache-Control"] = "private, no-store"
|
|
return await asyncio.to_thread(store.options)
|
|
|
|
@router.get("/download")
|
|
async def download(selected: dict = Depends(filters), format: Literal["txt", "jsonl"] = "txt",
|
|
user: HockeyUser = Depends(administrator)):
|
|
stamp = datetime.now(MOSCOW).strftime("%Y%m%d_%H%M%S")
|
|
filename = f"hockey-log_{stamp}.{format}"
|
|
return StreamingResponse(store.download(format=format, **selected),
|
|
media_type="text/plain; charset=utf-8" if format == "txt" else "application/x-ndjson",
|
|
headers={"Content-Disposition": f'attachment; filename="{filename}"',
|
|
"Cache-Control": "private, no-store", "X-Content-Type-Options": "nosniff"})
|
|
|
|
@router.get("")
|
|
async def records(response: Response, selected: dict = Depends(filters),
|
|
limit: int = Query(100, ge=1, le=500), cursor: str = Query("", max_length=1024),
|
|
user: HockeyUser = Depends(administrator)):
|
|
response.headers["Cache-Control"] = "private, no-store"
|
|
try:
|
|
return await asyncio.to_thread(store.query, limit=limit, cursor=cursor, **selected)
|
|
except ValueError as error:
|
|
raise HTTPException(422, str(error)) from error
|
|
|
|
return router
|