Add permissions when plugins are loaded

This commit is contained in:
Ferdinand Thiessen 2020-10-04 01:27:05 +02:00
parent 4cd68d7e81
commit f495829fc7
7 changed files with 28 additions and 25 deletions

View File

@ -7,6 +7,7 @@ from werkzeug.exceptions import HTTPException
from . import logger
from .system.config import config, configure_app
from .system.controller import roleController
class CustomJSONEncoder(JSONEncoder):
@ -48,9 +49,11 @@ def __load_plugins(app):
for entry_point in pkg_resources.iter_entry_points('flaschengeist.plugin'):
logger.debug("Found plugin: >{}<".format(entry_point.name))
if config.get(entry_point.name, 'enabled', fallback=False):
logger.info("Loaded plugin >{}<".format(entry_point.name))
blueprint, permissions = entry_point.load()()
app.config["FG_PLUGINS"][entry_point.name] = True
app.register_blueprint(entry_point.load()())
app.register_blueprint(blueprint)
roleController.create_permissions(permissions.values())
logger.info("Loaded plugin >{}<".format(entry_point.name))
else:
app.config["FG_PLUGINS"][entry_point.name] = False

View File

@ -18,7 +18,7 @@ auth_bp = Blueprint('auth', __name__)
def register():
return auth_bp
return auth_bp, {}
#################################################
# Routes #

View File

@ -9,10 +9,11 @@ from flaschengeist.system.decorator import login_required
from flaschengeist.system.models.event import EventKind
schedule_bp = Blueprint("schedule", __name__, url_prefix="/schedule")
permissions = {}
def register():
return schedule_bp
return schedule_bp, permissions
####################################################################################
@ -69,6 +70,9 @@ def __get_events(year=datetime.now().year, month=datetime.now().month, day=None,
if day:
begin += timedelta(days=day - 1)
end = begin + timedelta(days=1)
else:
if month == 12:
end = datetime(year=year + 1, month=1, day=1)
else:
end = datetime(year=year, month=month+1, day=1)

View File

@ -1,5 +1,5 @@
from flask import Blueprint, request, jsonify
from werkzeug.exceptions import NotFound, BadRequest
from werkzeug.exceptions import NotFound, BadRequest, Forbidden
from flaschengeist import logger
from flaschengeist.system.decorator import login_required
@ -7,9 +7,10 @@ from flaschengeist.system.controller import userController
users_bp = Blueprint("users", __name__)
permissions = {'EDIT_USER': 'edit_user'}
def register():
return users_bp
return users_bp, permissions
#################################################
# Routes #
@ -47,13 +48,16 @@ def __get_user(uid, **kwargs):
@users_bp.route("/users/<uid>", methods=['PUT'])
@login_required()#roles=['edit_users'])
@login_required()
def __edit_user(uid, **kwargs):
logger.debug("Modify information of user {{ {} }}".format(uid))
user = userController.get_user(uid)
if not user:
raise NotFound
if uid != kwargs['access_token'].user.uid and user.has_permissions(permissions['EDIT_USER']):
return Forbidden
data = request.get_json()
if 'password' not in data:
raise BadRequest("Password is missing")

View File

@ -19,7 +19,7 @@ class AccessTokenController(metaclass=Singleton):
def __init__(self, lifetime=1800):
self.lifetime = lifetime
def validate_token(self, token, user_agent, roles):
def validate_token(self, token, user_agent, permissions):
""" Verify access token
Verify an AccessToken and Roles so if the User has permission or not.
@ -28,7 +28,7 @@ class AccessTokenController(metaclass=Singleton):
Args:
token: Token to verify.
user_agent: User agent of browser to check
roles: Roles needed to access restricted routes
permissions: Permissions needed to access restricted routes
Returns:
An the AccessToken for this given Token or False.
"""
@ -39,14 +39,14 @@ class AccessTokenController(metaclass=Singleton):
if access_token.expires >= datetime.utcnow() and (
access_token.browser == user_agent.browser and
access_token.platform == user_agent.platform):
if not roles or (roles and self.user_has_role(access_token.user, roles)):
if not permissions or access_token.user.has_permissions(permissions):
access_token.refresh()
db.session.commit()
return access_token
else:
logger.debug("access token is out of date or invalid client used")
self.delete_token(access_token)
logger.debug("no valid access token with token: {{ {} }} and roles: {{ {} }}".format(token, roles))
logger.debug("no valid access token with token: {{ {} }} and permissions: {{ {} }}".format(token, permissions))
return False
def create(self, user, user_agent=None) -> AccessToken:
@ -115,11 +115,3 @@ class AccessTokenController(metaclass=Singleton):
deleted = AccessToken.query.filter(AccessToken.expires < datetime.utcnow()).delete()
logger.debug("{} tokens have been removed".format(deleted))
db.session.commit()
# TODO: is this needed?
def user_has_role(self, user, roles):
for group in user.groups:
for role in group.roles:
if role.name in roles:
return True
return False

View File

@ -8,15 +8,15 @@ from flaschengeist import logger
def login_required(**kwargs):
from .controller.accessTokenController import AccessTokenController
ac_controller = AccessTokenController()
roles = None
if "roles" in kwargs:
roles = kwargs["roles"]
permissions = None
if "permissions" in kwargs:
permissions = kwargs["roles"]
def real_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
token = request.headers.get('Token')
access_token = ac_controller.validate_token(token, request.user_agent, roles)
access_token = ac_controller.validate_token(token, request.user_agent, permissions)
if access_token:
kwargs['access_token'] = access_token
logger.debug("token {{ {} }} is valid".format(token))

View File

@ -18,7 +18,7 @@ class AccessToken(db.Model):
user = db.relationship("User", back_populates="sessions")
expires = db.Column(db.DateTime)
token = db.Column(db.String(30), unique=True)
token = db.Column(db.String(32), unique=True)
lifetime = db.Column(db.Integer)
browser = db.Column(db.String(30))
platform = db.Column(db.String(30))