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 +7 -0
- data/README.md +60 -0
- data/lib/jsonapi/validations.rb +11 -0
- data/lib/jsonapi/validations/relationship.rb +45 -0
- data/lib/jsonapi/validations/resource.rb +118 -0
- metadata +62 -0
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: []
|