def validate_device_fields(device_fields_api, device_fields, device_type, app): message_prefix = 'Device type {0} for app {1}'.format(device_type, app) for field_api in device_fields_api: if field_api['name'] not in device_fields and 'default' in field_api: device_fields[field_api['name']] = field_api['default'] required_in_api = {field['name'] for field in device_fields_api if 'required' in field and field['required']} field_names = set(device_fields) if required_in_api - field_names: message = '{0} requires {1} field but only got {2}'.format(message_prefix, list(required_in_api), list(field_names)) logger.error(message) raise InvalidInput(message) device_fields_api_dict = {field['name']: field for field in device_fields_api} for field, value in device_fields.items(): if field in device_fields_api_dict: validate_device_field(device_fields_api_dict[field], value, message_prefix) else: message = '{0} was passed field {1} which is not defined in its API'.format(message_prefix, field['name']) logger.warning(message) raise InvalidInput(message) return device_fields
def validate_primitive_parameter(value, param, parameter_type, message_prefix, hide_input=False): try: converted_value = convert_primitive_type(value, parameter_type) except (ValueError, TypeError): message = '{0} has invalid input. ' \ 'Input {1} could not be converted to type {2}'.format(message_prefix, value, parameter_type) logger.error(message) raise InvalidInput(message) else: param = deepcopy(param) if 'required' in param: param.pop('required') try: Draft4Validator( param, format_checker=draft4_format_checker).validate(converted_value) except ValidationError as exception: if not hide_input: message = '{0} has invalid input. ' \ 'Input {1} with type {2} does not conform to ' \ 'validators: {3}'.format(message_prefix, value, parameter_type, format_exception_message(exception)) else: message = '{0} has invalid input. {1} does not conform to ' \ 'validators: {2}'.format(message_prefix, parameter_type, format_exception_message(exception)) logger.error(message) raise InvalidInput(message) return converted_value
def validate_parameters(api, inputs, message_prefix): api_dict = {} for param in api: api_dict[param['name']] = param converted = {} seen_params = set() input_set = set(inputs.keys()) for param_name, param_api in api_dict.items(): if param_name in inputs: if not isinstance(inputs[param_name], string_types): converted[param_name] = validate_parameter( inputs[param_name], param_api, message_prefix) else: if inputs[param_name].startswith('@'): converted[param_name] = inputs[param_name] elif inputs[param_name].startswith('\@'): inputs[param_name] = inputs[param_name][1:] converted[param_name] = validate_parameter( inputs[param_name], param_api, message_prefix) else: converted[param_name] = validate_parameter( inputs[param_name], param_api, message_prefix) elif 'default' in param_api: try: default_param = validate_parameter(param_api['default'], param_api, message_prefix) except InvalidInput as e: default_param = param_api['default'] logger.warning( 'For {0}: Default input {1} (value {2}) does not conform to schema. (Error: {3})' 'Using anyways'.format(message_prefix, param_name, param_api['default'], format_exception_message(e))) converted[param_name] = default_param input_set.add(param_name) elif 'required' in param_api: message = 'For {0}: Parameter {1} is not specified and has no default'.format( message_prefix, param_name) logger.error(message) raise InvalidInput(message) else: converted[param_name] = None input_set.add(param_name) seen_params.add(param_name) if seen_params != input_set: message = 'For {0}: Too many inputs. Extra inputs: {1}'.format( message_prefix, input_set - seen_params) logger.error(message) raise InvalidInput(message) return converted
def __convert_json(schema, param_in, message_prefix): if not isinstance(param_in, dict): raise InvalidInput( '{0} A JSON object was expected. ' 'Instead got "{1}" of type {2}.'.format(message_prefix, param_in, type(param_in).__name__)) if 'properties' not in schema: return param_in ret = {} for param_name, param_value in param_in.items(): if param_name in schema['properties']: ret[param_name] = convert_json(schema['properties'][param_name], param_value, message_prefix) else: raise InvalidInput('{0} Input has unknown parameter {1}'.format(message_prefix, param_name)) return ret
def validate_parameter(value, param, message_prefix): primitive_type = 'primitive' if 'type' in param else 'object' converted_value = None if value is not None: if primitive_type == 'primitive': primitive_type = param['type'] if primitive_type in TYPE_MAP: converted_value = validate_primitive_parameter( value, param, primitive_type, message_prefix) elif primitive_type == 'array': try: converted_value = convert_array(param, value, message_prefix) Draft4Validator( param, format_checker=draft4_format_checker).validate( converted_value) except ValidationError as exception: message = '{0} has invalid input. Input {1} does not conform to ' \ 'validators: {2}'.format(message_prefix, value, format_exception_message(exception)) logger.error(message) raise InvalidInput(message) else: raise InvalidInput('In {0}: Unknown parameter type {1}'.format( message_prefix, primitive_type)) else: try: converted_value = convert_json(param, value, message_prefix) Draft4Validator(param['schema'], format_checker=draft4_format_checker).validate( converted_value) except ValidationError as exception: message = '{0} has invalid input. Input {1} does not conform to ' \ 'validators: {2}'.format(message_prefix, value, format_exception_message(exception)) logger.error(message) raise InvalidInput(message) elif param.get('required'): message = "In {0}: Missing {1} parameter '{2}'".format( message_prefix, primitive_type, param['name']) logger.error(message) raise InvalidInput(message) return converted_value
def convert_array(schema, param_in, message_prefix): if 'items' not in schema: return param_in item_type = schema['items']['type'] if item_type in TYPE_MAP: try: return convert_primitive_array(param_in, item_type) except ValueError: items = str(param_in) items = items if len(items) < 30 else '{0}...]'.format(items[:30]) message = '{0} has invalid input. Input {1} could not be converted to array ' \ 'with type "object"'.format(message_prefix, items) logger.error(message) raise InvalidInput(message) else: return [convert_json(schema['items'], param, message_prefix) for param in param_in]
def convert_json(spec, param_in, message_prefix): if 'type' in spec: parameter_type = spec['type'] if parameter_type in TYPE_MAP: try: return convert_primitive_type(param_in, parameter_type) except ValueError: message = ( '{0} has invalid input. ' 'Input {1} could not be converted to type {2}'.format(message_prefix, param_in, parameter_type)) logger.error(message) raise InvalidInput(message) elif parameter_type == 'array': return convert_array(spec, param_in, message_prefix) elif parameter_type == 'object': return __convert_json(spec, param_in, message_prefix) else: raise InvalidApi('{0} has invalid api'.format(message_prefix)) elif 'schema' in spec: return convert_json(spec['schema'], param_in, message_prefix) else: raise InvalidApi('{0} has invalid api'.format(message_prefix))