"""JSON Draft3 Schema Validator Wrapper. A wrapper module for a JSON Draft3 Schema validator. JSON Draft3 Schema: https://tools.ietf.org/html/draft-zyp-json-schema-03. This wrapper module allows: - fail_fast=False: do not exit on first validation error. - validating any data dict against any JSON Draft 3 validation schema. - error response returns with body containing: | errors: { field_name1: error_message, field_name2: error_message } """ from oto import response from project_manager.constant import error_const def raml_header_to_json_schema(raml_headers): """Take RAML specs for headers for an endpoint. Converts to JSON Draft 3 schema to use with our validator. NOTE: we have to filter out props with None as the value. Args: raml_headers (collections.OrderedDict): the headers part of a RAML endpoint descriptor. Returns: dict: the dict representing JSON validation schema snippet. """ properties = {} for item in raml_headers: _props = raml_headers[item] props = {} for prop in _props.__dict__: if _props.__dict__[prop] is not None: props[prop] = _props.__dict__[prop] properties[item] = props schema = { '$schema': 'http://json-schema.org/draft-03/schema', 'type': 'object', 'required': True, 'properties': properties } return schema def filter_input(data): """A filter function that cleans the input data from the user. All empty and whitespace-only strings become None. Args: data (dict): the user input to be filtered. Returns: (dict): the filtered dict """ for key, value in data.items(): if isinstance(value, str): data[key] = value.strip() if data[key] == '': data[key] = None return data def validate(data, validator): """Generic JSON Draft3 Schema Validation. Args: data (dict): the JSON to be validated. validator (Draft3Validator): the JSON Draft3 Schema to validate against Returns: Response: the response of the create operation. """ errors = {} data = filter_input(data) for e in sorted(validator.iter_errors(data), key=str): if e.relative_path: errors[e.relative_path.pop()] = e.message elif e.absolute_schema_path: errors[e.absolute_schema_path.pop()] = e.message if len(errors) > 0: return response.create_error_response( code=error_const.VALIDATION_ERROR, message=errors, status=400) return response.Response(message={'status': 'ok'}, status=200)