# -*- coding: utf-8 -*-
"""
app.decorators
~~~~~~~~~~~~~~
This module defines some useful decorators.
:copyright: (c) 2017 European Spallation Source ERIC
:license: BSD 2-Clause, see LICENSE for more details.
"""
from functools import wraps
from flask import current_app, abort, g
from flask_login import current_user
from .utils import CSEntryError
[docs]def login_groups_accepted(*groups):
"""Decorator which specifies that a user must have at least one of the specified groups.
This can be used for users logged in using a cookie (web UI) or JWT (API).
Example::
@bp.route('/models', methods=['POST'])
@login_groups_accepted('admin', 'inventory')
def create_model():
return create()
The current user must be in either 'admin' or 'create' group
to access the /models route.
This checks that the user is logged in. There is no need to
use the @login_required decorator.
:param groups: accepted groups
"""
def wrapper(fn):
@wraps(fn)
def decorated_view(*args, **kwargs):
# LOGIN_DISABLED can be set to True to turn off authentication check when testing.
# This variable is also used by flask-login
if current_app.config.get("LOGIN_DISABLED"):
return fn(*args, **kwargs)
if not current_user.is_authenticated:
return current_app.login_manager.unauthorized()
if not current_user.is_member_of_one_group(groups):
if g.get("login_via_request"):
raise CSEntryError(
"User doesn't have the required group", status_code=403
)
else:
abort(403)
return fn(*args, **kwargs)
return decorated_view
return wrapper