jsonapi-validations 0.1.1.beta1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 51f6ad7a9024b404c821d08302c1211fc8ab6d84
4
+ data.tar.gz: 814b58de2920226fbd45d6368a872e603b1c88d1
5
+ SHA512:
6
+ metadata.gz: c7155434543ebdc5165d090d236940fb6a07cecb384744fef8ececdecf48dd92c3a2a09bd8b09c3ba2376589aff88dc888c1a9dba6405b11f41b7a9191bba75a
7
+ data.tar.gz: 03fa3a140f3ea5ef289957542d15df92e2aabc74e861db885170bf42e95284a609ff6a4ec00b5709a36b2b11ca711acc3640bb7e7260766f117fa3ddcfb14d91
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # jsonapi-validations
2
+ Ruby gem for validating [JSON API](http://jsonapi.org) payloads.
3
+
4
+ ## Installation
5
+ ```ruby
6
+ # In Gemfile
7
+ gem 'jsonapi-validations'
8
+ ```
9
+ then
10
+ ```
11
+ $ bundle
12
+ ```
13
+ or manually via
14
+ ```
15
+ $ gem install jsonapi-validations
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ First, require the gem:
21
+ ```ruby
22
+ require 'jsonapi/validations'
23
+ ```
24
+ Then validate a resource creation/update payload:
25
+ ```ruby
26
+ params = {
27
+ permitted: {
28
+ id: true,
29
+ attributes: [:name, :address, :birthdate],
30
+ relationships: [:posts, :sponsor]
31
+ },
32
+ required: {
33
+ id: true,
34
+ attributes: [:name, :address],
35
+ relationships: [:sponsor]
36
+ },
37
+ types: {
38
+ primary: [:users, :admins],
39
+ relationships: {
40
+ posts: {
41
+ kind: :has_many,
42
+ types: [:blogs, :posts]
43
+ }
44
+ }
45
+ }
46
+ }
47
+ JSONAPI.validate_resource!(document_hash, params)
48
+ ```
49
+ or a relationship update payload:
50
+ ```ruby
51
+ params = {
52
+ kind: :has_many,
53
+ types: [:users, :admins]
54
+ }
55
+ JSONAPI.validate_relationship!(document_hash, params)
56
+ ```
57
+
58
+ ## License
59
+
60
+ jsonapi-validations is released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -0,0 +1,11 @@
1
+ module JSONAPI
2
+ module_function
3
+
4
+ def validate_resource!(document, params = {})
5
+ Validations::Resource.validate!(document, params)
6
+ end
7
+
8
+ def validate_relationship!(document, params = {})
9
+ Validations::Relationship.validate!(document, params)
10
+ end
11
+ end
@@ -0,0 +1,45 @@
1
+ require 'jsonapi/parser'
2
+
3
+ module JSONAPI
4
+ module Validations
5
+ module Relationship
6
+ module_function
7
+
8
+ # Validate the types of related objects in a relationship update payload.
9
+ #
10
+ # @param [Hash] document The input JSONAPI document.
11
+ # @param [Hash] params Validation parameters.
12
+ # @option [Symbol] kind Whether it is a :has_many or :has_one.
13
+ # @option [Array<Symbol>] types Permitted types for the relationship.
14
+ # @raise [JSONAPI::Validator::InvalidDocument] if document is invalid.
15
+ def validate_relationship!(document, params = {})
16
+ JSONAPI.parse_relationship!(document)
17
+ validate_types!(document['data'], params[:types])
18
+ end
19
+
20
+ # @api private
21
+ def validate_types!(rel, rel_types, key = nil)
22
+ rel_name = key ? " #{key}" : ''
23
+ if rel_types[:kind] == :has_many
24
+ Document.ensure!(rel['data'].is_a?(Array),
25
+ "Expected relationship#{rel_name} to be has_many.")
26
+ return unless rel_types[:types]
27
+ rel['data'].each do |ri|
28
+ Document.ensure!(rel_types[:types].include?(ri['type'].to_sym),
29
+ "Type mismatch for relationship#{rel_name}: " \
30
+ "#{ri['type']} should be one of #{rel_types}")
31
+ end
32
+ else
33
+ return if rel['data'].nil?
34
+ Document.ensure!(rel['data'].is_a?(Hash),
35
+ "Expected relationship#{rel_name} to be has_one.")
36
+ return unless rel_types[:types]
37
+ ri = rel['data']
38
+ Document.ensure!(rel_types[:types].include?(ri['type'].to_sym),
39
+ "Type mismatch for relationship#{rel_name}: " \
40
+ "#{ri['type']} should be one of #{rel_types}")
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,118 @@
1
+ require 'jsonapi/parser'
2
+
3
+ module JSONAPI
4
+ module Validations
5
+ module Resource
6
+ module_function
7
+
8
+ # Validate the structure of a resource create/update payload. Optionally
9
+ # validate whitelisted/required id/attributes/relationships, as well as
10
+ # primary type and relationship types.
11
+ #
12
+ # @param [Hash] document The input JSONAPI document.
13
+ # @param [Hash] params Validation parameters.
14
+ # @option [Hash] permitted Permitted attributes/relationships/primary
15
+ # id. Optional. If not supplied, all legitimate fields are permitted.
16
+ # @option [Hash] required Required attributes/relationships/primary id.
17
+ # Optional. The fields must be explicitly permitted, or permitted
18
+ # should not be provided.
19
+ # @option [Hash] types Permitted primary/relationships types. Optional.
20
+ # The relationships must be explicitly permitted. Not all
21
+ # relationships' types have to be specified.
22
+ # @raise [JSONAPI::Validator::InvalidDocument] if document is invalid.
23
+ #
24
+ # @example
25
+ # params = {
26
+ # permitted: {
27
+ # id: true, # Simply ommit it to forbid it.
28
+ # attributes: [:title, :date],
29
+ # relationships: [:comments, :author]
30
+ # },
31
+ # required: {
32
+ # id: true,
33
+ # attributes: [:title],
34
+ # relationships: [:comments, :author]
35
+ # },
36
+ # types: {
37
+ # primary: [:posts],
38
+ # relationships: {
39
+ # comments: {
40
+ # kind: :has_many,
41
+ # types: [:comments]
42
+ # },
43
+ # author: {
44
+ # kind: :has_one,
45
+ # types: [:users, :superusers]
46
+ # }
47
+ # }
48
+ # }
49
+ # }
50
+ def validate!(document, params = {})
51
+ JSONAPI.parse_resource!(document)
52
+
53
+ validate_permitted!(document['data'], params[:permitted])
54
+ validate_required!(document['data'], params[:required])
55
+ validate_types!(document['data'], params[:types])
56
+ end
57
+
58
+ # @api private
59
+ def validate_permitted!(data, permitted)
60
+ return if permitted.nil?
61
+ Document.ensure!(permitted[:id] || !data.key?('id'),
62
+ 'Unpermitted id.')
63
+ # TODO(beauby): Handle meta (and possibly links) once the spec has
64
+ # been clarified.
65
+ permitted_attrs = permitted[:attributes] || []
66
+ if data.key?('attributes')
67
+ data['attributes'].keys.each do |attr|
68
+ Document.ensure!(permitted_attrs.include?(attr.to_sym),
69
+ "Unpermitted attribute #{attr}")
70
+ end
71
+ end
72
+ permitted_rels = permitted[:relationships] || []
73
+ if data.key?('relationships')
74
+ data['relationships'].keys.each do |rel|
75
+ Document.ensure!(permitted_rels.include?(rel.to_sym))
76
+ end
77
+ end
78
+ end
79
+
80
+ # @api private
81
+ def validate_required!(data, required)
82
+ return if required.nil?
83
+ Document.ensure!(data.key?('id') || !required[:id],
84
+ 'Missing required id.')
85
+ # TODO(beauby): Same as for permitted.
86
+
87
+ Document.ensure!(data.key?('attributes') || !required[:attributes],
88
+ 'Missing required attributes.')
89
+ required[:attributes].each do |attr|
90
+ Document.ensure!(data['attributes'][attr.to_s],
91
+ "Missing required attribute #{attr}.")
92
+ end
93
+ Document.ensure!(data.key?('relationships') ||
94
+ !required[:relationships],
95
+ 'Missing required relationships.')
96
+ required[:relationships].each do |rel|
97
+ Document.ensure!(data['relationships'][rel.to_s],
98
+ "Missing required relationship #{rel}.")
99
+ end
100
+ end
101
+
102
+ # @api private
103
+ def validate_types!(data, types)
104
+ return if types.nil?
105
+ Document.ensure!(!types[:primary] ||
106
+ types[:primary].include?(data['type'].to_sym),
107
+ "Type mismatch for resource: #{data['type']} " \
108
+ "should be one of #{types[:primary]}")
109
+ return unless data.key?('relationships') && types.key?(:relationships)
110
+ types[:relationships].each do |key, rel_types|
111
+ rel = data['relationships'][key.to_s]
112
+ next unless rel
113
+ Relationship.validate_types!(rel, rel_types, key)
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jsonapi-validations
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1.beta1
5
+ platform: ruby
6
+ authors:
7
+ - Lucas Hosseini
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jsonapi-parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.1'
27
+ description: Validate presence/absence of resource creation/update and relationship
28
+ update payloads, as well as types related resources
29
+ email: lucas.hosseini@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - README.md
35
+ - lib/jsonapi/validations.rb
36
+ - lib/jsonapi/validations/relationship.rb
37
+ - lib/jsonapi/validations/resource.rb
38
+ homepage: https://github.com/beauby/jsonapi-validations
39
+ licenses:
40
+ - MIT
41
+ metadata: {}
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">"
54
+ - !ruby/object:Gem::Version
55
+ version: 1.3.1
56
+ requirements: []
57
+ rubyforge_project:
58
+ rubygems_version: 2.5.1
59
+ signing_key:
60
+ specification_version: 4
61
+ summary: Validate JSONAPI payloads.
62
+ test_files: []