flaschengeist/flaschengeist/system/controller/accessTokenController.py

116 lines
4.1 KiB
Python
Raw Normal View History

from ..models.accessToken import AccessToken
from flaschengeist.system.database import db
from datetime import datetime, timedelta
import secrets
from . import Singleton
import logging
2019-04-11 21:56:55 +00:00
logger = logging.getLogger("flaschenpost")
2020-01-18 22:31:49 +00:00
class AccessTokenController(metaclass=Singleton):
2020-09-01 23:32:55 +00:00
""" Control all created AccessToken
2019-05-02 16:50:59 +00:00
2020-09-01 23:32:55 +00:00
This Class create, delete, find and manage AccessToken.
2019-04-17 12:46:46 +00:00
Attributes:
lifetime: Variable for the Lifetime of one AccessToken in seconds.
"""
instance = None
2019-04-11 21:56:55 +00:00
tokenList = None
2019-12-30 08:22:43 +00:00
def __init__(self, lifetime=1800):
2019-04-17 12:46:46 +00:00
""" Initialize AccessTokenController
2019-05-02 16:50:59 +00:00
2019-04-17 12:46:46 +00:00
Initialize Thread and set tokenList empty.
"""
2020-09-01 23:32:55 +00:00
logger.debug("init access token controller")
self.lifetime = lifetime
2020-01-18 22:31:49 +00:00
2020-09-01 23:32:55 +00:00
def validate_token(self, token, roles):
""" Verify access token
2019-05-02 16:50:59 +00:00
Verify an AccessToken and Group so if the User has permission or not.
Retrieves the access token if valid else retrieves False
2019-04-17 12:46:46 +00:00
Args:
token: Token to verify.
roles: Roles needed to access restricted routes
2019-04-17 12:46:46 +00:00
Returns:
An the AccessToken for this given Token or False.
2019-04-17 12:46:46 +00:00
"""
logger.debug("check token {{ {} }} is valid".format(token))
2020-09-01 23:32:55 +00:00
for access_token in AccessToken.query.filter_by(token=token):
time_end = access_token.timestamp + timedelta(seconds=access_token.lifetime)
now = datetime.utcnow()
logger.debug("now is {{ {} }}, endtime is {{ {} }}".format(now, time_end))
if now <= time_end:
2020-09-01 23:32:55 +00:00
logger.debug("check if token {{ {} }} is same as {{ {} }}".format(token, access_token))
if not roles or (roles and self.userHasRole(access_token.user, roles)):
access_token.updateTimestamp()
db.session.commit()
2020-09-01 23:32:55 +00:00
return access_token
2020-03-07 13:56:44 +00:00
else:
2020-09-01 23:32:55 +00:00
logger.debug("access token is {{ {} }} out of date".format(access_token))
db.session.delete(access_token)
db.session.commit()
logger.debug("no valid access token with token: {{ {} }} and group: {{ {} }}".format(token, roles))
return False
2019-04-11 21:56:55 +00:00
def userHasRole(self, user, roles):
for group in user.groups:
for role in group.roles:
if role.name in roles:
return True
return False
2020-09-02 11:07:21 +00:00
def create(self, user, user_agent=None) -> AccessToken:
2019-04-17 12:46:46 +00:00
""" Create an AccessToken
Create an AccessToken for an User and add it to the tokenList.
Args:
user: For which User is to create an AccessToken
user_agent: User agent to identify session
2019-04-17 12:46:46 +00:00
Returns:
2020-09-02 11:07:21 +00:00
AccessToken: A created Token for User
2019-04-17 12:46:46 +00:00
"""
logger.debug("create access token")
token_str = secrets.token_hex(16)
2020-09-01 23:32:55 +00:00
token = AccessToken(token=token_str, user=user, lifetime=self.lifetime,
browser=user_agent.browser, platform=user_agent.platform)
db.session.add(token)
db.session.commit()
logger.debug("access token is {{ {} }}".format(token))
2019-04-11 21:56:55 +00:00
return token
def getAccessTokensFromUser(self, user):
return AccessToken.query.filter(AccessToken.user == user)
2020-09-01 23:32:55 +00:00
@staticmethod
def delete_token(token):
if token is isinstance(token, AccessToken):
db.session.delete(token)
else:
2020-09-01 23:32:55 +00:00
AccessToken.query.filter_by(token=token).delete()
db.session.commit()
@staticmethod
2020-09-01 23:32:55 +00:00
def update_token(token):
token.update_timestamp()
db.session.commit()
def clear_expired(self):
logger.debug("Clear expired AccessToken")
2020-09-01 23:32:55 +00:00
might_expired = datetime.utcnow() - timedelta(seconds=self.lifetime)
tokens = AccessToken.query.filter(AccessToken.timestamp < might_expired)
logger.debug(tokens)
for token in tokens:
if token.timestamp < datetime.utcnow() - timedelta(seconds=token.lifetime):
logger.debug("Delete token %s", token.token)
db.session.delete(token)
db.session.commit()