Sergiusz Bazanski | edeb3cc | 2019-12-18 14:16:53 +0100 | [diff] [blame] | 1 | from flask import abort, session, current_app |
| 2 | from flask_login import current_user |
| 3 | from flask_login.signals import user_logged_out |
| 4 | import requests |
| 5 | import functools |
| 6 | import time |
| 7 | |
| 8 | |
| 9 | def cap_check(capability, user=None): |
| 10 | '''Checks if specified user (or current user) has desired capacifier |
| 11 | capability''' |
| 12 | if not user and not current_user.is_authenticated: |
| 13 | return False |
| 14 | |
| 15 | user = user or current_user.get_id() |
| 16 | |
| 17 | cache_key = '{}-{}'.format(user, capability) |
| 18 | cached_cap = session.get('_caps', {}).get(cache_key, (False, 0)) |
| 19 | |
| 20 | if cached_cap[1] > time.time(): |
| 21 | return cached_cap[0] |
| 22 | |
| 23 | allowed = requests.get( |
| 24 | 'https://capacifier.hackerspace.pl/%s/%s' % (capability, user) |
| 25 | ).status_code == 200 |
| 26 | |
| 27 | if '_caps' not in session: |
| 28 | session['_caps'] = {} |
| 29 | |
| 30 | session['_caps'][cache_key] = \ |
| 31 | (allowed, time.time() + current_app.config.get('CAP_TTL', 3600)) |
| 32 | |
| 33 | return allowed |
| 34 | |
| 35 | |
| 36 | @user_logged_out.connect |
| 37 | def caps_cleanup(app, user): |
| 38 | # Cleanup caps cache |
| 39 | session.pop('_caps', None) |
| 40 | |
| 41 | |
| 42 | def cap_required(capability): |
| 43 | '''Decorator to check if user has desired capacifier capability, returns |
| 44 | 403 otherwise''' |
| 45 | |
| 46 | def inner(func): |
| 47 | @functools.wraps(func) |
| 48 | def wrapped(*args, **kwargs): |
| 49 | if not cap_check(capability): |
| 50 | abort(403) |
| 51 | |
| 52 | return func(*args, **kwargs) |
| 53 | |
| 54 | return wrapped |
| 55 | return inner |