Add AP inbox endpoint + device auth signaling
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m2s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m2s
- POST /inbox with HTTP Signature verification - Device ID cookie tracking + adoption from account - Silent auth checks local Redis for did_auth signals - Replaces shared-Redis coupling with AP activity delivery Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ Art-DAG L1 Server Application Factory.
|
||||
Creates and configures the FastAPI application with all routers and middleware.
|
||||
"""
|
||||
|
||||
import secrets
|
||||
import time
|
||||
from pathlib import Path
|
||||
from urllib.parse import quote
|
||||
@@ -18,8 +19,10 @@ from artdag_common.middleware.auth import get_user_from_cookie
|
||||
from .config import settings
|
||||
|
||||
# Paths that should never trigger a silent auth check
|
||||
_SKIP_PREFIXES = ("/auth/", "/static/", "/api/", "/ipfs/", "/download/")
|
||||
_SKIP_PREFIXES = ("/auth/", "/static/", "/api/", "/ipfs/", "/download/", "/inbox")
|
||||
_SILENT_CHECK_COOLDOWN = 300 # 5 minutes
|
||||
_DEVICE_COOKIE = "artdag_did"
|
||||
_DEVICE_COOKIE_MAX_AGE = 30 * 24 * 3600 # 30 days
|
||||
|
||||
|
||||
def create_app() -> FastAPI:
|
||||
@@ -46,6 +49,30 @@ def create_app() -> FastAPI:
|
||||
async def shutdown():
|
||||
await close_db()
|
||||
|
||||
# Device ID middleware — track browser identity across domains
|
||||
@app.middleware("http")
|
||||
async def device_id_middleware(request: Request, call_next):
|
||||
did = request.cookies.get(_DEVICE_COOKIE)
|
||||
if did:
|
||||
request.state.device_id = did
|
||||
request.state._new_device_id = False
|
||||
else:
|
||||
request.state.device_id = secrets.token_urlsafe(32)
|
||||
request.state._new_device_id = True
|
||||
|
||||
response = await call_next(request)
|
||||
|
||||
if getattr(request.state, "_new_device_id", False):
|
||||
response.set_cookie(
|
||||
key=_DEVICE_COOKIE,
|
||||
value=request.state.device_id,
|
||||
max_age=_DEVICE_COOKIE_MAX_AGE,
|
||||
httponly=True,
|
||||
samesite="lax",
|
||||
secure=True,
|
||||
)
|
||||
return response
|
||||
|
||||
# Silent auth check — auto-login via prompt=none OAuth
|
||||
@app.middleware("http")
|
||||
async def silent_auth_check(request: Request, call_next):
|
||||
@@ -65,7 +92,24 @@ def create_app() -> FastAPI:
|
||||
pnone_at = request.cookies.get("pnone_at")
|
||||
if pnone_at:
|
||||
try:
|
||||
if (time.time() - float(pnone_at)) < _SILENT_CHECK_COOLDOWN:
|
||||
pnone_ts = float(pnone_at)
|
||||
if (time.time() - pnone_ts) < _SILENT_CHECK_COOLDOWN:
|
||||
# But first check if account signalled a login via inbox delivery
|
||||
device_id = getattr(request.state, "device_id", None)
|
||||
if device_id:
|
||||
try:
|
||||
from .dependencies import get_redis_client
|
||||
r = get_redis_client()
|
||||
auth_ts = r.get(f"did_auth:{device_id}")
|
||||
if auth_ts and float(auth_ts) > pnone_ts:
|
||||
# Login happened since our last check — retry
|
||||
current_url = str(request.url)
|
||||
return RedirectResponse(
|
||||
url=f"/auth/login?prompt=none&next={quote(current_url, safe='')}",
|
||||
status_code=302,
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return await call_next(request)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
@@ -94,11 +138,12 @@ def create_app() -> FastAPI:
|
||||
return JSONResponse({"detail": "Not found"}, status_code=404)
|
||||
|
||||
# Include routers
|
||||
from .routers import auth, storage, api, recipes, cache, runs, home, effects
|
||||
from .routers import auth, storage, api, recipes, cache, runs, home, effects, inbox
|
||||
|
||||
# Home and auth routers (root level)
|
||||
app.include_router(home.router, tags=["home"])
|
||||
app.include_router(auth.router, prefix="/auth", tags=["auth"])
|
||||
app.include_router(inbox.router, tags=["inbox"])
|
||||
|
||||
# Feature routers
|
||||
app.include_router(storage.router, prefix="/storage", tags=["storage"])
|
||||
|
||||
Reference in New Issue
Block a user