Arag / app /api /widget.py
AuthorBot
P0 security: async backup, widget CORS, Redis auth.
937692a
Raw
History Blame Contribute Delete
1.44 kB
"""Author RAG — Widget Token API.
Routes (per implementation plan):
GET /api/widget/token?slug={author_slug}&domain={domain}
GET /api/widget/{author_slug} — Serves embeddable widget HTML
RULE: Token must be verified on every widget chat request.
"""
from pathlib import Path
from fastapi import APIRouter, HTTPException, Query
from fastapi.responses import FileResponse, JSONResponse
from app.core.security import sign_widget_token, verify_widget_token
router = APIRouter()
WIDGET_HTML = Path(__file__).resolve().parent.parent.parent / "static" / "addon.html"
@router.get("/token")
async def get_widget_token(
slug: str = Query(..., description="Author slug"),
domain: str = Query(..., description="Author's website domain"),
):
"""Generate a signed HMAC widget token for embedding.
The token encodes the author slug and allowed domain.
Embed via: <script src=".../static/widget.js" data-token="TOKEN">
"""
token = sign_widget_token(slug, domain)
return {"token": token, "author_slug": slug, "domain": domain}
@router.get("/{author_slug}")
async def get_widget_page(author_slug: str):
"""Serve the embeddable widget HTML page for an author."""
if not WIDGET_HTML.is_file():
raise HTTPException(404, "Widget not found")
return FileResponse(
WIDGET_HTML,
headers={
"Cache-Control": "no-cache, no-store, must-revalidate",
},
)