hecks-plugins-json-validator 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e5b20be7162ce46d038b8ef5c5551dfd7764a39a
4
+ data.tar.gz: 0ae13e35cab1100d8dd1c8ca4b46c9d6b9fc4548
5
+ SHA512:
6
+ metadata.gz: 8479f09a701a2ed7b19c6651790d641f6a2e4eeec40bcec5f12221632d84d48e51e7dbea77de0b1e3b4dec94a72868e5d9d846e75e8167cbdaf3c73c28c6d74c
7
+ data.tar.gz: 8dbfb5194d61bbb1e4139a7b688fc276f0899c85524dacab61657bdcd81574273b49324264938ec20ab319a1ac18e2bc53ba77212570641a803f28fd62aea84f
@@ -0,0 +1,58 @@
1
+ require 'json-schema'
2
+ require_relative 'matchers'
3
+ require_relative 'parsers/schema_parser'
4
+ require_relative 'parsers/message_parser'
5
+
6
+ module HecksPlugins
7
+ # A validator that is built on top of json-schema to provide more
8
+ # functionality than the basic hecks validator. Builds a json schema
9
+ # from a head spec and validates the user's input against it.
10
+ class JSONValidator
11
+ attr_reader :errors
12
+
13
+ def initialize(command:)
14
+ @args = command.args
15
+ @domain_module = command.domain_module
16
+ @errors = {}
17
+ @schema_parser = SchemaParser.new(
18
+ domain_module: domain_module,
19
+ object: command.domain_module.head
20
+ ).call
21
+
22
+ @validator = JSON::Validator
23
+ end
24
+
25
+ def call
26
+ parse_schema
27
+ validate
28
+ self
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :args, :domain_module, :schema, :schema_parser, :validator
34
+
35
+ def parse_schema
36
+ @schema = schema_parser.schema
37
+ end
38
+
39
+ def validate
40
+ MATCHERS.each do |matcher|
41
+ result = validator.fully_validate(schema, args, errors_as_objects: true)
42
+
43
+ result.each do |error|
44
+ parser = MessageParser.new(matcher: matcher, error: error).call
45
+ next unless parser.message
46
+ if parser.fragment && parser.fragment != parser.field_name
47
+ errors[parser.fragment] ||= {}
48
+ errors[parser.fragment][parser.field_name] ||= []
49
+ errors[parser.fragment][parser.field_name] << parser.message
50
+ else
51
+ errors[parser.field_name] ||= []
52
+ errors[parser.field_name] << parser.message
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,17 @@
1
+ #
2
+ module HecksPlugins
3
+ class JSONValidator
4
+ # These matchers create a cleaner, more user-friendly message out of the
5
+ # messages returned by json-schema
6
+ MATCHERS = [
7
+ {
8
+ regex: /did not contain a required property of '(.*)' in schema/,
9
+ message: 'Missing'
10
+ },
11
+ {
12
+ regex: /The property '#\/(.*)' of type (.*) did not match the following type: (.*) in schema/,
13
+ message: 'Type mismatch. Got \'%s\', should have been \'%s\''
14
+ }
15
+ ]
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ module HecksPlugins
2
+ class JSONValidator
3
+ # Turn the json-schema messages into easy to understand errors for the user
4
+ class MessageParser
5
+ attr_reader :message, :field_name, :fragment
6
+
7
+ def initialize(matcher:, error:)
8
+ @matcher = matcher
9
+ @error = error
10
+ @match = error[:message].match(matcher[:regex])
11
+ @fragment = error[:fragment].gsub('#/', '')
12
+ if fragment == ''
13
+ @fragment = nil
14
+ else
15
+ @fragment = fragment.to_sym
16
+ end
17
+
18
+ end
19
+
20
+ def call
21
+ parse_match
22
+ self
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :match, :matcher, :error
28
+
29
+ def parse_match
30
+ return unless match
31
+ @message = matcher[:message]
32
+ @message = message % match[2..-1] if match.length > 2
33
+ @field_name = match[1].to_sym
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,71 @@
1
+ module HecksPlugins
2
+ class JSONValidator
3
+ # Create a JSON Schema from an object
4
+ class SchemaParser
5
+ attr_reader :schema
6
+ JSON_TYPES = %w{string number object array boolean null}
7
+ HECKS_NUMBER_TYPES = %w{integer currency}
8
+
9
+ def initialize domain_module:, object:
10
+ @domain_module = domain_module
11
+ @object = object
12
+ @properties = {}
13
+ end
14
+
15
+ def call
16
+ parse_required_fields
17
+ object.attributes.each { |a| parse_property(a) }
18
+ build_schema
19
+ self
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :required_fields, :object, :properties, :domain_module
25
+
26
+ def build_schema
27
+ @schema = {
28
+ "type" => "object",
29
+ "required" => required_fields,
30
+ "properties" => properties
31
+ }
32
+ end
33
+
34
+ def parse_required_fields
35
+ @required_fields = object.attributes.map{ |a| a.name }
36
+ end
37
+
38
+ def get_json_type attribute
39
+ result = attribute.type.downcase
40
+ return 'array' if attribute.list?
41
+ return 'number' if HECKS_NUMBER_TYPES.include?(result)
42
+ return 'object' unless JSON_TYPES.include?(result)
43
+
44
+ result
45
+ end
46
+
47
+ def schema_for_attribute attribute
48
+ return {} if attribute.reference?
49
+ self.class.new(
50
+ domain_module: domain_module,
51
+ object: domain_module.find(attribute.type)
52
+ ).call.schema
53
+ end
54
+
55
+ def parse_property(attribute)
56
+ type = get_json_type(attribute)
57
+ name = attribute.name
58
+ properties[name] =
59
+ case type
60
+ when 'object' then schema_for_attribute(attribute)
61
+ when 'array'
62
+ {
63
+ "type" => 'array',
64
+ "items" => schema_for_attribute(attribute)
65
+ }
66
+ else { "type" => type }
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hecks-plugins-json-validator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Young
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-12-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json-schema
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.5'
27
+ description: Hecks JSON Schema Validations
28
+ email: chris@example.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/hecks-plugins-json-validator.rb
34
+ - lib/matchers.rb
35
+ - lib/parsers/message_parser.rb
36
+ - lib/parsers/schema_parser.rb
37
+ homepage: https://github.com/chrisyoung/hecks
38
+ licenses:
39
+ - MIT
40
+ metadata: {}
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 2.6.10
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Advanced Domain Validations Based on JSON Schema http://json-schema.org/
61
+ test_files: []