diff --git a/buckler_aiohttp.py b/buckler_aiohttp.py new file mode 100644 index 0000000..a2c8ed6 --- /dev/null +++ b/buckler_aiohttp.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +""" +Session interface middlewares to integrate the aiohttp app with Buckler. +""" +import json +from datetime import datetime + +import aiohttp +from aiohttp import web + +import config + +@web.middleware +async def buckler_session(request, handler): + """ + Verifies the user with the configured Buckler app and retrieves any + session data they may have. Redirects them to the login page otherwise. + """ + 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 aiohttp.ClientSession() as session: + async with session.get(url, params=params) as resp: + data = await resp.json() + if data.get('error'): + raise web.HTTPFound(location=config.buckler['login_url']) + request['session'] = data['session_data'] + request['meta'] = data['meta'] + + resp = await handler(request) + + if request['session'] != data['session_data']: # session data modified + url = config.buckler['url'] + '/set_session' + data = json.dumps(request['session']) + session.post(url, params=params, data=data) # TODO: error handle? + + last_used = datetime.fromisoformat(request['meta']['last_used']) + now = datetime.now(last_used.tzinfo) + delta = now - last_used + if delta.seconds > 600: + resp.set_cookie( + 'userid', + user_id, + max_age=30*24*60*60, + secure=True, + httponly=True) + resp.set_cookie( + 'session', + user_sid, + max_age=30*24*60*60, + secure=True, + httponly=True) + + return resp