jsonapi-validations 0.1.1.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|