def decorator(func): from functools import wraps @wraps(func) def inner(*args, **kwargs): from flask import request user = None if authorization: bearer_token = request.headers.get('Authorization') if bearer_token and len(bearer_token.split(' ')) == 2: token = bearer_token.split(' ')[1] user = AuthorizationUtils.get_user_info(token) request.user_extra = user else: raise ErrorTokenException if permissions is not None and isinstance(permissions, List): if user and user.role and user.role.has_all_permissions: return func(*args, **kwargs) user_permissions = [] if user and user.permissions: user_permissions = user.permissions accept = all([(item in user_permissions) for item in permissions]) if not accept: raise NotPermissionException if schema: if has_request_params: try: obj = schema.load(request.args) request.parse_args = obj except ValidationError: raise PhysicalValidationException( message='The query param is not valid') else: try: obj = schema.load(request.get_json()) request.parse_obj = obj except ValidationError as err: raise PhysicalValidationException(extra=err.messages) return func(*args, **kwargs) if api and use_swagger: if schema: inner = api.doc( params={qp["name"]: qp for qp in query_params}, body=for_swagger( schema=schema, model_name=get_default_model_name(schema), api=api, operation="load", ), )(inner) elif _parser: inner = api.expect(_parser)(inner) return inner
def decorator(func): from functools import wraps # Check if we are decorating a class method _IS_METHOD = _is_method(func) @wraps(func) def inner(*args, **kwargs): from flask import request error = schema_error = None # Handle arguments try: request.parsed_args = _parser.parse_args() except Exception as e: error = e # Handle Marshmallow schema if schema: try: obj = schema.load(request.get_json()) request.parsed_obj = obj except ValidationError as ex: schema_error = ex.messages if schema_error: error = error or BadRequest( f"Invalid parsing error: {schema_error}") if hasattr(error, "data"): error.data["errors"].update( {"schema_errors": schema_error}) else: error.data = {"schema_errors": schema_error} # If any parsing produced an error, combine them and re-raise if error: raise error return func(*args, **kwargs) # Add Swagger if api and use_swagger and _IS_METHOD: if schema: inner = api.doc( params={qp["name"]: qp for qp in query_params}, body=for_swagger( schema=schema, model_name=model_name or get_default_model_name(schema), api=api, operation="load", ), )(inner) elif _parser: inner = api.expect(_parser)(inner) return inner
def responds( *args, model_name: str = None, schema=None, many: bool = False, api=None, envelope=None, status_code: int = 200, validate: bool = False, description: str = None, use_swagger: bool = True, ): """ Serialize the output of a function using the Marshmallow schema to dump the results. Note that `schema` should be the type, not an instance -- the `responds` decorator will internally handle creation of the schema. If the outputted value is already of type flask.Response, it will be passed along without further modification. Args: schema (bool, optional): Marshmallow schema with which to serialize the output of the wrapped function. many (bool, optional): (DEPRECATED) The Marshmallow schema `many` parameter, which will return a list of the corresponding schema objects when set to True. Returns: The output of schema(many=many).dumps(<return value>) of the wrapped function """ from functools import wraps from flask_restx import reqparse _check_deprecate_many(many) # If an api was passed in, we need to use its parser so Swagger is aware if api: _parser = api.parser() else: _parser = reqparse.RequestParser(bundle_errors=True) query_params = [arg for arg in args if isinstance(arg, dict)] for arg in args: # check for positional string-arg, which is the model name if isinstance(arg, str): model_name = arg break for qp in query_params: _parser.add_argument(**qp, location="values") ordered = None if schema: schema = _get_or_create_schema(schema, many=many) ordered = schema.ordered model_name = model_name or get_default_model_name(schema) model_from_parser = _model_from_parser(model_name=model_name, parser=_parser) def decorator(func): # Check if we are decorating a class method _IS_METHOD = _is_method(func) @wraps(func) def inner(*args, **kwargs): rv = func(*args, **kwargs) # If a Flask response has been made already, it is passed through unchanged if isinstance(rv, Response): return rv if schema: serialized = schema.dump(rv) # Validate data if asked to (throws) if validate: errs = schema.validate(serialized) if errs: raise InternalServerError( description= "Server attempted to return invalid data") # Apply the flask-restx mask after validation serialized = _apply_restx_mask(serialized) else: from flask_restx import marshal serialized = marshal(rv, model_from_parser) if envelope: serialized = OrderedDict([(envelope, serialized)]) if ordered else { envelope: serialized } if not _is_method(func): # Regular route, need to manually create Response return jsonify(serialized), status_code return serialized, status_code # Add Swagger if api and use_swagger and _IS_METHOD: if schema: api_model = for_swagger(schema=schema, model_name=model_name, api=api, operation="dump") if schema.many is True: api_model = [api_model] inner = _document_like_marshal_with( api_model, status_code=status_code, description=description, )(inner) elif _parser: api.add_model(model_name, model_from_parser) inner = _document_like_marshal_with( model_from_parser, status_code=status_code)(inner) return inner return decorator
def decorator(func): from functools import wraps # Check if we are decorating a class method _IS_METHOD = _is_method(func) @wraps(func) def inner(*args, **kwargs): from flask import request error = schema_error = None # Handle arguments try: request.parsed_args = _parser.parse_args() except Exception as e: error = e # Handle Marshmallow schema for request body if schema: try: obj = schema.load(request.get_json()) request.parsed_obj = obj except ValidationError as ex: schema_error = ex.messages if schema_error: error = error or BadRequest( f"Error parsing request body: {schema_error}") if hasattr(error, "data"): error.data["errors"].update( {"schema_errors": schema_error}) else: error.data = {"schema_errors": schema_error} # Handle Marshmallow schema for query params if query_params_schema: request_args = _convert_multidict_values_to_schema( request.args, query_params_schema) try: obj = query_params_schema.load(request_args) request.parsed_query_params = obj except ValidationError as ex: schema_error = ex.messages if schema_error: error = error or BadRequest( f"Error parsing query params: {schema_error}") if hasattr(error, "data"): error.data["errors"].update( {"schema_errors": schema_error}) else: error.data = {"schema_errors": schema_error} # Handle Marshmallow schema for headers if headers_schema: request_headers = _convert_multidict_values_to_schema( request.headers, headers_schema) try: obj = headers_schema.load(request_headers) request.parsed_headers = obj except ValidationError as ex: schema_error = ex.messages if schema_error: error = error or BadRequest( f"Error parsing headers: {schema_error}") if hasattr(error, "data"): error.data["errors"].update( {"schema_errors": schema_error}) else: error.data = {"schema_errors": schema_error} # If any parsing produced an error, combine them and re-raise if error: raise error return func(*args, **kwargs) # Add Swagger if api and use_swagger and _IS_METHOD: if schema: body = for_swagger( schema=schema, model_name=model_name or get_default_model_name(schema), api=api, operation="load", ) params = { "expect": [body, _parser], } inner = api.doc(**params)(inner) elif _parser: inner = api.expect(_parser)(inner) return inner
def decorator(func): from functools import wraps # Check if we are decorating a class method _IS_METHOD = _is_method(func) @wraps(func) def inner(*args, **kwargs): from flask import request error = schema_error = None # Handle arguments try: request.parsed_args = _parser.parse_args() except Exception as e: error = e # Handle Marshmallow schema for request body if schema: try: headers = request.headers.get('content-type', '') # allow parsing multipart/form-data and x-www-form-urlencoded if 'form' in headers: data = {**request.form} # convert form data with value string of dict/list to object dict/list for key, value in data.items(): if isinstance(value, str) and value.strip(): try: data[key] = literal_eval(value) except (ValueError, SyntaxError): pass # add files to data data.update(request.files) else: data = request.get_json(force=True) obj = schema.load(data) request.parsed_obj = obj except ValidationError as ex: schema_error = ex.messages if schema_error: error = error or BadRequest( f"Error parsing request body: {schema_error}") if hasattr(error, "data"): error.data["errors"].update( {"schema_errors": schema_error}) else: error.data = {"schema_errors": schema_error} # Handle Marshmallow schema for query params if query_params_schema: request_args = _convert_multidict_values_to_schema( request.args, query_params_schema) try: obj = query_params_schema.load(request_args) request.parsed_query_params = obj except ValidationError as ex: schema_error = ex.messages if schema_error: error = error or BadRequest( f"Error parsing query params: {schema_error}") if hasattr(error, "data"): error.data["errors"].update( {"schema_errors": schema_error}) else: error.data = {"schema_errors": schema_error} # Handle Marshmallow schema for headers if headers_schema: request_headers = _convert_multidict_values_to_schema( request.headers, headers_schema) try: obj = headers_schema.load(request_headers) request.parsed_headers = obj except ValidationError as ex: schema_error = ex.messages if schema_error: error = error or BadRequest( f"Error parsing headers: {schema_error}") if hasattr(error, "data"): error.data["errors"].update( {"schema_errors": schema_error}) else: error.data = {"schema_errors": schema_error} # If any parsing produced an error, combine them and re-raise if error: raise error return func(*args, **kwargs) # Add Swagger if api and use_swagger and _IS_METHOD: if schema: body = for_swagger( schema=schema, model_name=model_name or get_default_model_name(schema), api=api, operation="load", ) if schema.many is True: body = [body] params = { "expect": [body, _parser], } inner = api.doc(**params)(inner) elif _parser: inner = api.expect(_parser)(inner) return inner