def wrapper(*args, **kwargs): min_ver = api_version.APIVersionRequest(min_version) max_ver = api_version.APIVersionRequest(max_version) # The request object is always the second argument. # However numerous unittests pass in the request object # via kwargs instead so we handle that as well. # TODO(cyeoh): cleanup unittests so we don't have to # to do this if 'req' in kwargs: ver = kwargs['req'].api_version_request legacy_v2 = kwargs['req'].is_legacy_v2() else: ver = args[1].api_version_request legacy_v2 = args[1].is_legacy_v2() if ver.matches(min_ver, max_ver): # Only validate against the schema if it lies within # the version range specified. Note that if both min # and max are not specified the validator will always # be run. schema_validator = validators._SchemaValidator( request_body_schema, legacy_v2) schema_validator.validate(kwargs['body']) return func(*args, **kwargs)
def test_strip_extra_properties_out_without_extra_props(self): validator = validators._SchemaValidator(self.schema).validator instance = {'foo': '1'} gen = validators._soft_validate_additional_properties( validator, False, instance, self.schema) self.assertRaises(StopIteration, next, gen) self.assertEqual({'foo': '1'}, instance)
def test_pattern_properties(self): validator = validators._SchemaValidator( self.schema_with_pattern).validator instance = {'foo': '1'} gen = validators._soft_validate_additional_properties( validator, False, instance, self.schema_with_pattern) self.assertRaises(StopIteration, next, gen)
def test_not_strip_extra_properties_out_with_allow_extra_props(self): validator = validators._SchemaValidator(self.schema_allow).validator instance = {'foo': '1', 'extra_foo': 'extra'} gen = validators._soft_validate_additional_properties( validator, True, instance, self.schema_allow) self.assertRaises(StopIteration, next, gen) self.assertEqual({'foo': '1', 'extra_foo': 'extra'}, instance)
def test_pattern_properties_with_multiple_invalid_properties(self): validator = validators._SchemaValidator(self.schema_with_pattern).validator instance = {"foo": "1", "b" * 300: "extra", "c" * 300: "extra"} gen = validators._soft_validate_additional_properties(validator, False, instance, self.schema_with_pattern) exc = next(gen) self.assertIsInstance(exc, jsonschema_exc.ValidationError) self.assertIn("were", exc.message)
def test_pattern_properties_with_invalid_property_and_allow_extra_props( self): validator = validators._SchemaValidator( self.schema_with_pattern).validator instance = {'foo': '1', 'b' * 300: 'extra'} gen = validators._soft_validate_additional_properties( validator, True, instance, self.schema_with_pattern) self.assertRaises(StopIteration, next, gen)
def test_pattern_properties_with_multiple_invalid_properties(self): validator = validators._SchemaValidator( self.schema_with_pattern).validator instance = {'foo': '1', 'b' * 300: 'extra', 'c' * 300: 'extra'} gen = validators._soft_validate_additional_properties( validator, False, instance, self.schema_with_pattern) exc = next(gen) self.assertIsInstance(exc, jsonschema_exc.ValidationError) self.assertIn('were', exc.message)
def wrapper(*args, **kwargs): min_ver = api_version.APIVersionRequest(min_version) max_ver = api_version.APIVersionRequest(max_version) # The request object is always the second argument. # However numerous unittests pass in the request object # via kwargs instead so we handle that as well. # TODO(cyeoh): cleanup unittests so we don't have to # to do this if 'req' in kwargs: ver = kwargs['req'].api_version_request legacy_v2 = kwargs['req'].is_legacy_v2() else: ver = args[1].api_version_request legacy_v2 = args[1].is_legacy_v2() if legacy_v2: # NOTE: For v2.0 compatible API, here should work like # client | schema min_version | schema # -----------+--------------------+-------- # legacy_v2 | None | work # legacy_v2 | 2.0 | work # legacy_v2 | 2.1+ | don't if min_version is None or min_version == '2.0': schema_validator = validators._SchemaValidator( request_body_schema, legacy_v2) schema_validator.validate(kwargs['body']) elif ver.matches(min_ver, max_ver): # Only validate against the schema if it lies within # the version range specified. Note that if both min # and max are not specified the validator will always # be run. schema_validator = validators._SchemaValidator( request_body_schema, legacy_v2) schema_validator.validate(kwargs['body']) return func(*args, **kwargs)
def schema(request_body_schema, min_version=None, max_version=None): """Register a schema to validate request body. Registered schema will be used for validating request body just before API method executing. :argument dict request_body_schema: a schema to validate request body """ schema_validator = validators._SchemaValidator(request_body_schema) def add_validator(func): @functools.wraps(func) def wrapper(*args, **kwargs): min_ver = api_version.APIVersionRequest(min_version) max_ver = api_version.APIVersionRequest(max_version) # The request object is always the second argument. # However numerous unittests pass in the request object # via kwargs instead so we handle that as well. # TODO(cyeoh): cleanup unittests so we don't have to # to do this if 'req' in kwargs: ver = kwargs['req'].api_version_request else: ver = args[1].api_version_request if ver.matches(min_ver, max_ver): # Only validate against the schema if it lies within # the version range specified. Note that if both min # and max are not specified the validator will always # be run. schema_validator.validate(kwargs['body']) return func(*args, **kwargs) return wrapper return add_validator
def _schema_validation_helper(schema, target, min_version, max_version, args, kwargs, is_body=True): """A helper method to execute JSON-Schema Validation. This method checks the request version whether matches the specified max version and min_version. It also takes a care of legacy v2 request. If the version range matches the request, we validate the schema against the target and a failure will result in a ValidationError being raised. :param schema: A dict, the JSON-Schema is used to validate the target. :param target: A dict, the target is validated by the JSON-Schema. :param min_version: A string of two numerals. X.Y indicating the minimum version of the JSON-Schema to validate against. :param max_version: A string of two numerals. X.Y indicating the maximum version of the JSON-Schema to validate against. :param args: Positional arguments which passed into original method. :param kwargs: Keyword arguments which passed into original method. :param is_body: A boolean. Indicating whether the target is HTTP request body or not. :returns: A boolean. `True` if and only if the version range matches the request AND the schema is successfully validated. `False` if the version range does not match the request and no validation is performed. :raises: ValidationError, when the validation fails. """ min_ver = api_version.APIVersionRequest(min_version) max_ver = api_version.APIVersionRequest(max_version) # The request object is always the second argument. # However numerous unittests pass in the request object # via kwargs instead so we handle that as well. # TODO(cyeoh): cleanup unittests so we don't have to # to do this if 'req' in kwargs: ver = kwargs['req'].api_version_request legacy_v2 = kwargs['req'].is_legacy_v2() else: ver = args[1].api_version_request legacy_v2 = args[1].is_legacy_v2() if legacy_v2: # NOTE: For v2.0 compatible API, here should work like # client | schema min_version | schema # -----------+--------------------+-------- # legacy_v2 | None | work # legacy_v2 | 2.0 | work # legacy_v2 | 2.1+ | don't if min_version is None or min_version == '2.0': schema_validator = validators._SchemaValidator( schema, legacy_v2, is_body) schema_validator.validate(target) return True elif ver.matches(min_ver, max_ver): # Only validate against the schema if it lies within # the version range specified. Note that if both min # and max are not specified the validator will always # be run. schema_validator = validators._SchemaValidator(schema, legacy_v2, is_body) schema_validator.validate(target) return True return False
def _schema_validation_helper(schema, target, min_version, max_version, args, kwargs, is_body=True): """A helper method to execute JSON-Schema Validation. This method checks the request version whether matches the specified max version and min_version. It also takes a care of legacy v2 request. If the version range matches the request, we validate the schema against the target and a failure will result in a ValidationError being raised. :param schema: A dict, the JSON-Schema is used to validate the target. :param target: A dict, the target is validated by the JSON-Schema. :param min_version: A string of two numerals. X.Y indicating the minimum version of the JSON-Schema to validate against. :param max_version: A string of two numerals. X.Y indicating the maximum version of the JSON-Schema to validate against. :param args: Positional arguments which passed into original method. :param kwargs: Keyword arguments which passed into original method. :param is_body: A boolean. Indicating whether the target is HTTP request body or not. :returns: A boolean. `True` if and only if the version range matches the request AND the schema is successfully validated. `False` if the version range does not match the request and no validation is performed. :raises: ValidationError, when the validation fails. """ min_ver = api_version.APIVersionRequest(min_version) max_ver = api_version.APIVersionRequest(max_version) # The request object is always the second argument. # However numerous unittests pass in the request object # via kwargs instead so we handle that as well. # TODO(cyeoh): cleanup unittests so we don't have to # to do this if 'req' in kwargs: ver = kwargs['req'].api_version_request legacy_v2 = kwargs['req'].is_legacy_v2() else: ver = args[1].api_version_request legacy_v2 = args[1].is_legacy_v2() if legacy_v2: # NOTE: For v2.0 compatible API, here should work like # client | schema min_version | schema # -----------+--------------------+-------- # legacy_v2 | None | work # legacy_v2 | 2.0 | work # legacy_v2 | 2.1+ | don't if min_version is None or min_version == '2.0': schema_validator = validators._SchemaValidator( schema, legacy_v2, is_body) schema_validator.validate(target) return True elif ver.matches(min_ver, max_ver): # Only validate against the schema if it lies within # the version range specified. Note that if both min # and max are not specified the validator will always # be run. schema_validator = validators._SchemaValidator( schema, legacy_v2, is_body) schema_validator.validate(target) return True return False