add fastapi app middleware

This commit is contained in:
iou1name 2024-07-28 15:33:46 -04:00
parent 7f4fcf5228
commit 1153c8ba0d

74
buckler_fastapi.py Normal file
View File

@ -0,0 +1,74 @@
#!/usr/bin/env python3
"""
Session interface middlewares to integrate the fastapi app with Buckler.
"""
import json
from datetime import datetime
import httpx
from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse
from starlette.middleware.base import BaseHTTPMiddleware
import config
class BucklerSessionMiddleware(BaseHTTPMiddleware):
"""
Verifies the user with the configured Buckler app and retrieves any
session data they may have. Redirects them to the login page otherwise.
"""
def __init__(self, app):
super().__init__(app)
async def dispatch(self, request: Request, call_next):
user_id = request.cookies.get('userid', '')
user_sid = request.cookies.get('session', '')
url = config.buckler['url'] + '/get_session'
params = {
'app_id': config.buckler['app_id'],
'app_key': config.buckler['app_key'],
'userid': user_id,
'session': user_sid }
async with httpx.AsyncClient() as client:
resp = await client.get(url, params=params)
data = resp.json()
if data.get('error'): # user not logged in
response = RedirectResponse(config.buckler['login_url'])
response.set_cookie('redirect', config.server_homepage)
return response
request.state.session = data.get('session_data')
request.state.meta = data.get('meta')
response = await call_next(request)
if request.state.session != data['session_data']: # session data modified
url = config.buckler['url'] + '/set_session'
data = json.dumps(request.state.session)
async with httpx.AsyncClient() as client:
await client.post(url, params=params, data=data)
last_used = datetime.fromisoformat(request.state.meta['last_used'])
now = datetime.now(last_used.tzinfo)
delta = now - last_used
if delta.seconds > 600:
response.set_cookie(
'userid',
user_id,
domain=config.server_domain,
max_age=30*24*60*60,
secure=True,
httponly=True,
samesite='strict')
response.set_cookie(
'session',
user_sid,
domain=config.server_domain,
max_age=30*24*60*60,
secure=True,
httponly=True,
samesite='strict')
return response