play-api/api/auth.py

98 lines
3.4 KiB
Python

from datetime import datetime, timedelta
import json
import mysql.connector as sql
from mysql.connector import IntegrityError
import requests
class BackendException(Exception):
def __init__(self, status_code, status_message):
self.status = status_code
self.message = status_message
class Authenticator:
def __init__(self, config, logger):
self.logger = logger
self.perm_url = config['api']['permission_url'].rstrip('/')
self.headers = {'Accept': 'application/json',
'Content-Type': 'application/json'}
self.ttl = timedelta(seconds=int(config['api']['cache_seconds']))
self.session = requests.Session()
self.conninfo = {
'user': config['db']['user'],
'password': config['db']['password'],
'database': config['db']['database'],
'host': config['db'].get('host' 'localhost'),
'port': config['db'].get('port', 3306)
}
def authenticate(self, token):
# DEBUG
#return 'granted'
# END DEBUG
# DEBUG
#result = self._make_request(token)
#self.logger.error("Got response %s for %s", result, token)
#return result
# END DEBUG
self._cache_clean()
result = self._cache_read(token)
if result:
self.logger.debug("Got %s from cache for %s",
result, token)
return result
result = self._make_request(token)
self.logger.debug("Got %s from auth for %s",
result, token)
try:
self._cache_save(token, result)
self.logger.debug("Saved %s to cache for %s",
result, token)
except IntegrityError as e:
result = self._cache_read(token)
self.logger.debug("Got %s from cache under race for %s",
result, token)
return result
def _cache_clean(self):
with sql.connect(**self.conninfo) as db:
with db.cursor() as c:
c.execute("delete from `cache` where `end` < %s",
(datetime.now().timestamp(),))
db.commit()
def _cache_read(self, token):
with sql.connect(**self.conninfo) as db:
with db.cursor() as c:
c.execute("select `result` from `cache` where `token` = %s",
(token,))
result = c.fetchone()
if result:
return result[0]
return None
def _cache_save(self, token, result):
with sql.connect(**self.conninfo) as db:
with db.cursor() as c:
stmt = "insert into `cache`(`token`, `result`, `end`) " + \
"values (%s, %s, %s)"
end = datetime.now() + self.ttl
c.execute(stmt, (token, result, end.timestamp()))
db.commit()
def _make_request(self, token):
data = {'token': token}
response = self.session.post(self.perm_url,
headers=self.headers,
data=json.dumps(data))
if not response.ok:
raise BackendException(response.status_code,
response.json()['message'])
return response.json()['permission']