Module: FakeDynamo::Validation
- Included in:
- DB, Filter, Item, Key, LocalSecondaryIndex, Projection, Table
- Defined in:
- lib/fake_dynamo/validation.rb
Instance Method Summary collapse
- #add_errors(message) ⇒ Object
- #api_config ⇒ Object
- #api_config_path ⇒ Object
- #api_input_spec(operation) ⇒ Object
- #available_operations ⇒ Object
- #key_schema_mismatch ⇒ Object
- #param(attribute, parents) ⇒ Object
- #validate!(&block) ⇒ Object
- #validate_hash_condition(condition) ⇒ Object
- #validate_hash_key(index, table) ⇒ Object
- #validate_index_names(indexes) ⇒ Object
- #validate_input(operation, data) ⇒ Object
- #validate_key_data(data, key_schema) ⇒ Object
- #validate_key_schema(data, key_schema) ⇒ Object
- #validate_operation(operation) ⇒ Object
- #validate_payload(operation, data) ⇒ Object
- #validate_projection(projection) ⇒ Object
- #validate_range_condition(condition, schema) ⇒ Object
- #validate_range_key(key_schema) ⇒ Object
- #validate_request_size(data) ⇒ Object
- #validate_spec(attribute, data, spec, parents) ⇒ Object
- #validate_type(value, attribute) ⇒ Object
Instance Method Details
#add_errors(message) ⇒ Object
17 18 19 |
# File 'lib/fake_dynamo/validation.rb', line 17 def add_errors() @api_errors << end |
#api_config ⇒ Object
117 118 119 |
# File 'lib/fake_dynamo/validation.rb', line 117 def api_config @api_config ||= YAML.load_file(api_config_path) end |
#api_config_path ⇒ Object
121 122 123 |
# File 'lib/fake_dynamo/validation.rb', line 121 def api_config_path File.join File.(File.dirname(__FILE__)), 'api_2012-08-10.yml' end |
#api_input_spec(operation) ⇒ Object
109 110 111 |
# File 'lib/fake_dynamo/validation.rb', line 109 def api_input_spec(operation) api_config[:operations].find { |spec| spec[:name] == operation }[:inputs] end |
#available_operations ⇒ Object
113 114 115 |
# File 'lib/fake_dynamo/validation.rb', line 113 def available_operations @available_operations ||= api_config[:operations].map { |spec| spec[:name] } end |
#key_schema_mismatch ⇒ Object
159 160 161 |
# File 'lib/fake_dynamo/validation.rb', line 159 def key_schema_mismatch raise ValidationException, "The provided key element does not match the schema" end |
#param(attribute, parents) ⇒ Object
105 106 107 |
# File 'lib/fake_dynamo/validation.rb', line 105 def param(attribute, parents) (parents + [attribute]).join('.') end |
#validate!(&block) ⇒ Object
6 7 8 9 10 11 12 13 14 |
# File 'lib/fake_dynamo/validation.rb', line 6 def validate!(&block) @api_errors = [] yield unless @api_errors.empty? plural = @api_errors.size == 1 ? '' : 's' = "#{@api_errors.size} error#{plural} detected: #{@api_errors.join('; ')}" raise ValidationException, end end |
#validate_hash_condition(condition) ⇒ Object
200 201 202 203 204 205 206 207 208 |
# File 'lib/fake_dynamo/validation.rb', line 200 def validate_hash_condition(condition) unless condition raise ValidationException, "Query condition missed key schema element #{key_schema.hash_key.name}" end if condition['ComparisonOperator'] != 'EQ' raise ValidationException, "Query key condition not supported" end end |
#validate_hash_key(index, table) ⇒ Object
175 176 177 178 179 |
# File 'lib/fake_dynamo/validation.rb', line 175 def validate_hash_key(index, table) if index.hash_key != table.hash_key raise ValidationException, "Index KeySchema does not have the same leading hash key as table KeySchema for index" end end |
#validate_index_names(indexes) ⇒ Object
193 194 195 196 197 198 |
# File 'lib/fake_dynamo/validation.rb', line 193 def validate_index_names(indexes) names = indexes.map(&:name) if names.uniq.size != names.size raise ValidationException, "Duplicate index name: #{names.find { |n| names.count(n) > 1 }}" end end |
#validate_input(operation, data) ⇒ Object
33 34 35 36 37 |
# File 'lib/fake_dynamo/validation.rb', line 33 def validate_input(operation, data) api_input_spec(operation).each do |attribute, spec| validate_spec(attribute, data[attribute], spec, []) end end |
#validate_key_data(data, key_schema) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/fake_dynamo/validation.rb', line 146 def validate_key_data(data, key_schema) hash_key = data[key_schema.hash_key.name] or key_schema_mismatch validate_type(hash_key, key_schema.hash_key) if key_schema.range_key range_key = data[key_schema.range_key.name] or key_schema_mismatch validate_type(range_key, key_schema.range_key) key_schema_mismatch if data.size != 2 else key_schema_mismatch if data.size != 1 end end |
#validate_key_schema(data, key_schema) ⇒ Object
136 137 138 139 140 141 142 143 144 |
# File 'lib/fake_dynamo/validation.rb', line 136 def validate_key_schema(data, key_schema) key = data[key_schema.hash_key.name] or raise ValidationException, "Missing the key #{key_schema.hash_key.name} in the item" validate_type(key, key_schema.hash_key) if key_schema.range_key range_key = data[key_schema.range_key.name] or raise ValidationException, "Missing the key #{key_schema.range_key.name} in the item" validate_type(range_key, key_schema.range_key) end end |
#validate_operation(operation) ⇒ Object
29 30 31 |
# File 'lib/fake_dynamo/validation.rb', line 29 def validate_operation(operation) raise UnknownOperationException, "Unknown operation: #{operation}" unless available_operations.include? operation end |
#validate_payload(operation, data) ⇒ Object
21 22 23 24 25 26 27 |
# File 'lib/fake_dynamo/validation.rb', line 21 def validate_payload(operation, data) validate! do validate_request_size(data) validate_operation(operation) validate_input(operation, data) end end |
#validate_projection(projection) ⇒ Object
181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/fake_dynamo/validation.rb', line 181 def validate_projection(projection) if projection.type == 'INCLUDE' unless projection.non_key_attributes raise ValidationException, "ProjectionType is #{projection.type}, but NonKeyAttributes is not specified" end else if projection.non_key_attributes raise ValidationException, "ProjectionType is #{projection.type}, but NonKeyAttributes is specified" end end end |
#validate_range_condition(condition, schema) ⇒ Object
210 211 212 213 214 |
# File 'lib/fake_dynamo/validation.rb', line 210 def validate_range_condition(condition, schema) unless condition.has_key?(schema.range_key.name) raise ValidationException, "Query condition missed key schema element #{schema.range_key.name}" end end |
#validate_range_key(key_schema) ⇒ Object
169 170 171 172 173 |
# File 'lib/fake_dynamo/validation.rb', line 169 def validate_range_key(key_schema) unless key_schema.range_key raise ValidationException, 'Table KeySchema does not have a range key' end end |
#validate_request_size(data) ⇒ Object
163 164 165 166 167 |
# File 'lib/fake_dynamo/validation.rb', line 163 def validate_request_size(data) if data.to_s.bytesize > 1 * 1024 * 1024 raise ValidationException, "Request size can't exceed 1 mb" end end |
#validate_spec(attribute, data, spec, parents) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/fake_dynamo/validation.rb', line 39 def validate_spec(attribute, data, spec, parents) if not data if spec.include?(:required) add_errors("value null at '#{param(attribute, parents)}' failed to satisfy the constraint: Member must not be null") end return end spec.each do |constrain| case constrain when :string add_errors("The parameter '#{param(attribute, parents)}' must be a string") unless data.kind_of? String when :blob add_errors("The parameter '#{param(attribute, parents)}' must be a binary") unless data.kind_of? String when :long add_errors("The parameter '#{param(attribute, parents)}' must be a long") unless data.kind_of? Integer when :integer add_errors("The parameter '#{param(attribute, parents)}' must be a integer") unless data.kind_of? Integer when :boolean add_errors("The parameter '#{param(attribute, parents)}' must be a boolean") unless (data.kind_of? TrueClass or data.kind_of? FalseClass) when Hash new_parents = parents + [attribute] case constrain.keys.first when :pattern pattern = constrain[:pattern] unless data =~ pattern add_errors("The parameter '#{param(attribute, parents)}' should match the pattern #{pattern}") end when :within range = constrain[:within] unless range.include?(Numeric === data ? data : data.size) add_errors("The parameter '#{param(attribute, parents)}' value '#{data}' should be within #{range}") end when :enum enum = constrain[:enum] unless enum.include? data add_errors("Value '#{data}' at '#{param(attribute, parents)}' failed to satisfy the constraint: Member must satisfy enum values set: #{enum}") end when :structure structure = constrain[:structure] structure.each do |attribute, spec| validate_spec(attribute, data[attribute], spec, parents + ["member"]) end when :map map = constrain[:map] raise ValidationException, "#{param(attribute, parents)} must be a Hash" unless data.kind_of? Hash data.each do |key, value| validate_spec(key, key, map[:key], new_parents) validate_spec(key, value, map[:value], new_parents) end when :list raise ValidationException, "#{param(attribute, parents)} must be a Array" unless data.kind_of? Array data.each_with_index do |element, i| validate_spec(element, element, constrain[:list], new_parents + [(i+1).to_s]) end else raise "Unhandled constraint #{constrain}" end when :required # handled earlier else raise "Unhandled constraint #{constrain}" end end end |
#validate_type(value, attribute) ⇒ Object
125 126 127 128 129 130 131 132 133 134 |
# File 'lib/fake_dynamo/validation.rb', line 125 def validate_type(value, attribute) if attribute.kind_of?(Attribute) expected_type = value.keys.first if expected_type != attribute.type raise ValidationException, "Type mismatch for key #{attribute.name}" end else raise 'Unknown attribute' end end |