"""Scan-to-connect: the data and the QR a phone's camera opens.""" from __future__ import annotations import io from fastapi import APIRouter, Depends, Request from fastapi.responses import Response from ..auth import Ctx from ..connect import build_base_urls, host_port from ..deps import get_ctx router = APIRouter() @router.get("/v1/connect/info") def connect_info(request: Request, ctx: Ctx = Depends(get_ctx)): """Admin: data for the "scan to connect" QR shown in the PWA settings tab.""" ctx.require_admin(request) return { "base_urls": build_base_urls(request), "invite_code": ctx.cfg.invite_code, } @router.get("/v1/connect/qr") def connect_qr(request: Request, ctx: Ctx = Depends(get_ctx), host: str | None = None): """Admin: the QR itself as SVG. `host` overrides the address (multi-NIC).""" import segno ctx.require_admin(request) scheme = request.headers.get("x-forwarded-proto") or request.url.scheme if host: # explicit override replaces the address but keeps the deep-link path/port _orig, port = host_port(request.headers.get("host"), scheme) netloc = f"{host}:{port}" if port else host base = f"{scheme}://{netloc}/app" else: bases = build_base_urls(request) base = bases[0] if bases else "http://127.0.0.1:8000/app" url = base + f"#invite={ctx.cfg.invite_code or ''}" qr = segno.make(url, error="m") buf = io.BytesIO() qr.save(buf, kind="svg", scale=8, border=2, dark="#000000", light="#ffffff") return Response(buf.getvalue(), media_type="image/svg+xml")