75 lines
2.1 KiB
Python
75 lines
2.1 KiB
Python
#!/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
|