Source code for zemfrog.decorators

from functools import wraps
from typing import Callable

from flask import current_app, jsonify
from flask_smorest import Blueprint
from flask_smorest.arguments import ArgumentsMixin
from flask_smorest.response import ResponseMixin
from flask_smorest.pagination import PaginationMixin
from flask_smorest.etag import EtagMixin
from flask_jwt_extended import verify_jwt_in_request
from flask_jwt_extended.utils import get_jwt_claims


[docs]def http_code(func: Callable) -> Callable: """ Decorator to generate HTTP status response code automatically according to the key ``code`` in json. :param func: Your view function. """ @wraps(func) def wrapper(*args, **kwds): result = func(*args, **kwds) code = 200 if isinstance(result, dict): code = result.get("code", 200) if not isinstance(result, (tuple, list)): result = result, code return result return wrapper
[docs]def api_doc(*args, **kwds) -> Callable: """ See here https://flask-smorest.readthedocs.io/en/latest/api_reference.html#flask_smorest.Blueprint.doc """ wrapper = Blueprint.doc(*args, **kwds) return wrapper
[docs]def use_kwargs(*args, **kwds) -> Callable: """ See here https://flask-smorest.readthedocs.io/en/latest/arguments.html """ wrapper = ArgumentsMixin().arguments(*args, **kwds) return wrapper
[docs]def marshal_with(*args, **kwds) -> Callable: """ See here https://flask-smorest.readthedocs.io/en/latest/response.html# """ wrapper = ResponseMixin().alt_response(*args, **kwds) return wrapper
[docs]def paginate(*args, **kwds) -> Callable: """ See here https://flask-smorest.readthedocs.io/en/latest/pagination.html. """ wrapper = PaginationMixin().paginate(*args, **kwds) return wrapper
[docs]def etag(schema=None) -> Callable: """ See here https://flask-smorest.readthedocs.io/en/latest/etag.html """ wrapper = EtagMixin().etag(schema) return wrapper
[docs]def jwt_required(roles={}) -> Callable: """ Decorator to protect views with JWT & user roles. """ def decorated(func: Callable) -> Callable: @wraps(func) def wrapper(*args, **kwds): verify_jwt_in_request() claims = get_jwt_claims() jwt_roles = claims.get("roles", {}) for role, permissions in roles.items(): if not isinstance(permissions, (list, tuple)): permissions = [] if role in jwt_roles: valid_perms = jwt_roles.get(role, []) for perm in permissions: if perm not in valid_perms: return ( jsonify(message="You don't have permission!", code=403), 403, ) else: return (jsonify(message="Role not allowed!", code=403), 403) return func(*args, **kwds) return wrapper return decorated
[docs]def authenticate(roles={}) -> Callable: """ Decorator to add jwt view authentication to API Docs. Reference: https://github.com/tiangolo/full-stack-flask-couchdb/tree/master/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/api/api_v1. """ def decorated(func: Callable) -> Callable: func = api_doc(security=current_app.config.get("API_SECURITY_PARAMS", []))( jwt_required(roles)(func) ) return func return decorated