Use this decorator to enable granular security permissions
        to your API methods (BaseApi and child classes).
        Permissions will be associated to a role, and roles are associated to users.

        allow_browser_login will accept signed cookies obtained from the normal MVC app::

            class MyApi(BaseApi):
                @expose('/dosonmething', methods=['GET'])
                @protect(allow_browser_login=True)
                @safe
                def do_something(self):
                    ....

                @expose('/dosonmethingelse', methods=['GET'])
                @protect()
                @safe
                def do_something_else(self):
                    ....

        By default the permission's name is the methods name.

def protect(allow_browser_login=False):
    """
        Use this decorator to enable granular security permissions
        to your API methods (BaseApi and child classes).
        Permissions will be associated to a role, and roles are associated to users.

        allow_browser_login will accept signed cookies obtained from the normal MVC app::

            class MyApi(BaseApi):
                @expose('/dosonmething', methods=['GET'])
                @protect(allow_browser_login=True)
                @safe
                def do_something(self):
                    ....

                @expose('/dosonmethingelse', methods=['GET'])
                @protect()
                @safe
                def do_something_else(self):
                    ....

        By default the permission's name is the methods name.
    """
    def _protect(f):
        if hasattr(f, '_permission_name'):
            permission_str = f._permission_name
        else:
            permission_str = f.__name__

        def wraps(self, *args, **kwargs):
            permission_str = "{}{}".format(PERMISSION_PREFIX, f._permission_name)
            class_permission_name = self.__class__.__name__
            if current_app.appbuilder.sm.is_item_public(
                    permission_str,
                    class_permission_name
            ):
                return f(self, *args, **kwargs)
            if not (self.allow_browser_login or allow_browser_login):
                verify_jwt_in_request()
            if current_app.appbuilder.sm.has_access(
                    permission_str,
                    class_permission_name
            ):
                return f(self, *args, **kwargs)
            elif (self.allow_browser_login or allow_browser_login):
                verify_jwt_in_request()
                if current_app.appbuilder.sm.has_access(
                        permission_str,
                        class_permission_name
                ):
                    return f(self, *args, **kwargs)
            log.warning(
                LOGMSG_ERR_SEC_ACCESS_DENIED.format(
                    permission_str,
                    class_permission_name
                )
            )
            return self.response_401()
        f._permission_name = permission_str
        return functools.update_wrapper(wraps, f)
    return _protect