"""Owner session routes — backup-key download and restore-on-new-browser.""" from __future__ import annotations from pathlib import Path from fastapi import APIRouter, Form, Request from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse from fastapi.templating import Jinja2Templates import imptune.config as cfg from imptune.db.models import Owner from imptune.services.session import COOKIE_MAX_AGE, COOKIE_NAME, is_same_origin router = APIRouter(prefix="/session") templates = Jinja2Templates( directory=str(Path(__file__).parent.parent / "templates") ) @router.get("/key/download") def download_key(request: Request) -> PlainTextResponse: """Mark the current owner permanent and hand back its key as a backup file.""" owner: Owner = request.state.owner if not owner.is_permanent: owner.is_permanent = True owner.save() return PlainTextResponse( content=owner.key, headers={"Content-Disposition": 'attachment; filename="imptune-backup-key.txt"'}, ) @router.get("/restore", response_class=HTMLResponse) def restore_page(request: Request, error: str = "") -> HTMLResponse: return templates.TemplateResponse( request=request, name="session_restore.html", context={"error": error}, ) @router.post("/restore") def restore_session(request: Request, key: str = Form(...)): """Re-associate this browser with a previously downloaded backup key.""" if not is_same_origin(request): return templates.TemplateResponse( request=request, name="session_restore.html", context={"error": "Request rejected — please submit this form directly from this site."}, status_code=403, ) owner = Owner.get_or_none(Owner.key == key.strip()) if owner is None: return templates.TemplateResponse( request=request, name="session_restore.html", context={"error": "Key not found."}, status_code=404, ) response = RedirectResponse(url="/", status_code=303) response.set_cookie( COOKIE_NAME, owner.key, max_age=COOKIE_MAX_AGE, httponly=True, samesite="lax", secure=cfg.COOKIE_SECURE, ) return response