from functools import wraps
from flask import redirect, url_for, request, flash, abort
from flask_login import current_user
from flask_login.config import EXEMPT_METHODS
from app import app

def priv_required(*perms):
    """
    If you decorate a view with this, it will ensure that the current user is
    authenticated and has required permissions before calling the actual view.
    (If they are not, it calls the :attr:`LoginManager.unauthorized` callback.)
    For example::

        @app.route('/admin')
        @priv_required('access-admin-board')
        def admin_board():
            pass

    It can be convenient to globally turn off authentication when unit testing.
    To enable this, if the application configuration variable `LOGIN_DISABLED`
    is set to `True`, this decorator will be ignored.
    """
    def decorated_view(func):
        @wraps(func)
        def wrapped(*args, **kwargs):
            if request.method in EXEMPT_METHODS:
                return func(*args, **kwargs)
            elif app.config.get('LOGIN_DISABLED'):
                return func(*args, **kwargs)
            elif not current_user.is_authenticated:
                return app.login_manager.unauthorized()
            else:
                for p in perms:
                    if not current_user.priv(p):
                        abort(403)
            return func(*args, **kwargs)
        return wrapped
    return decorated_view
