fun_with_json_api 0.0.5 → 0.0.6.pre.alpha.1
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 +4 -4
- data/config/locales/fun_with_json_api.en.yml +3 -0
- data/lib/fun_with_json_api/attributes/relationship.rb +11 -3
- data/lib/fun_with_json_api/attributes/relationship_collection.rb +21 -6
- data/lib/fun_with_json_api/deserializer.rb +12 -1
- data/lib/fun_with_json_api/deserializer_class_methods.rb +27 -17
- data/lib/fun_with_json_api/exceptions/unauthorized_resource.rb +16 -0
- data/lib/fun_with_json_api/find_collection_from_document.rb +9 -33
- data/lib/fun_with_json_api/find_resource_from_document.rb +10 -3
- data/lib/fun_with_json_api/schema_validators/check_collection_has_all_members.rb +67 -0
- data/lib/fun_with_json_api/schema_validators/check_collection_is_authorized.rb +63 -0
- data/lib/fun_with_json_api/schema_validators/check_relationships.rb +2 -2
- data/lib/fun_with_json_api/schema_validators/check_resource_is_authorized.rb +50 -0
- data/lib/fun_with_json_api/version.rb +1 -1
- data/spec/dummy/log/test.log +34269 -0
- data/spec/fun_with_json_api/deserializer_spec.rb +52 -10
- data/spec/fun_with_json_api/find_collection_from_document_spec.rb +82 -4
- data/spec/fun_with_json_api/find_resource_from_document_spec.rb +36 -2
- data/spec/fun_with_json_api/schema_validators/check_relationships_spec.rb +2 -2
- data/spec/fun_with_json_api_spec.rb +68 -0
- metadata +8 -4
@@ -458,7 +458,7 @@ describe FunWithJsonApi::Deserializer do
|
|
458
458
|
expect(payload.status).to eq '404'
|
459
459
|
expect(payload.code).to eq 'missing_relationship'
|
460
460
|
expect(payload.title).to eq 'Unable to find the requested relationship'
|
461
|
-
expect(payload.pointer).to eq '/data/relationships/example/id'
|
461
|
+
expect(payload.pointer).to eq '/data/relationships/example/data/id'
|
462
462
|
expect(payload.detail).to eq "Unable to find 'persons' with matching id: \"foobar\""
|
463
463
|
end
|
464
464
|
end
|
@@ -495,12 +495,54 @@ describe FunWithJsonApi::Deserializer do
|
|
495
495
|
end.create
|
496
496
|
end
|
497
497
|
|
498
|
-
|
499
|
-
author_a
|
500
|
-
author_b
|
501
|
-
|
502
|
-
|
503
|
-
|
498
|
+
context 'with multiple resources' do
|
499
|
+
let!(:author_a) { ARModels::Author.create(id: 1, code: 'foobar') }
|
500
|
+
let!(:author_b) { ARModels::Author.create(id: 2, code: 'blargh') }
|
501
|
+
|
502
|
+
context 'when all resources are authorised' do
|
503
|
+
before do
|
504
|
+
resource_authorizer = double(:resource_authorizer)
|
505
|
+
allow(resource_authorizer).to receive(:call).and_return(true)
|
506
|
+
allow(deserializer.relationship_for(:examples).deserializer).to(
|
507
|
+
receive(:resource_authorizer).and_return(resource_authorizer)
|
508
|
+
)
|
509
|
+
end
|
510
|
+
|
511
|
+
it 'finds a resource by the defined id_param and returns the resource id' do
|
512
|
+
expect(deserializer.parse_example_ids(%w(foobar blargh))).to eq(
|
513
|
+
[author_a.id, author_b.id]
|
514
|
+
)
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
context 'when a resource is not authorised' do
|
519
|
+
before do
|
520
|
+
resource_authorizer = double(:resource_authorizer)
|
521
|
+
allow(resource_authorizer).to receive(:call).and_return(false)
|
522
|
+
allow(resource_authorizer).to receive(:call).with(author_b).and_return(false)
|
523
|
+
allow(resource_authorizer).to receive(:call).with(author_a).and_return(true)
|
524
|
+
allow(deserializer.relationship_for(:examples).deserializer).to(
|
525
|
+
receive(:resource_authorizer).and_return(resource_authorizer)
|
526
|
+
)
|
527
|
+
end
|
528
|
+
|
529
|
+
it 'raises a UnauthorisedResource when unable to find a single resource' do
|
530
|
+
expect do
|
531
|
+
deserializer.parse_example_ids %w(foobar blargh)
|
532
|
+
end.to raise_error(FunWithJsonApi::Exceptions::UnauthorisedResource) do |e|
|
533
|
+
expect(e.payload.size).to eq 1
|
534
|
+
|
535
|
+
payload = e.payload.first
|
536
|
+
expect(payload.status).to eq '403'
|
537
|
+
expect(payload.code).to eq 'unauthorized_resource'
|
538
|
+
expect(payload.title).to eq 'Unable to access the requested resource'
|
539
|
+
expect(payload.pointer).to eq '/data/relationships/examples/data/1/id'
|
540
|
+
expect(payload.detail).to eq(
|
541
|
+
"Unable to assign the requested 'persons' (blargh) to the current resource"
|
542
|
+
)
|
543
|
+
end
|
544
|
+
end
|
545
|
+
end
|
504
546
|
end
|
505
547
|
|
506
548
|
it 'raises a MissingRelationship when unable to find a single resource' do
|
@@ -516,7 +558,7 @@ describe FunWithJsonApi::Deserializer do
|
|
516
558
|
expect(payload.status).to eq '404'
|
517
559
|
expect(payload.code).to eq 'missing_relationship'
|
518
560
|
expect(payload.title).to eq 'Unable to find the requested relationship'
|
519
|
-
expect(payload.pointer).to eq '/data/relationships/examples/1/id'
|
561
|
+
expect(payload.pointer).to eq '/data/relationships/examples/data/1/id'
|
520
562
|
expect(payload.detail).to eq "Unable to find 'persons' with matching id: \"blargh\""
|
521
563
|
end
|
522
564
|
end
|
@@ -534,14 +576,14 @@ describe FunWithJsonApi::Deserializer do
|
|
534
576
|
expect(payload_a.status).to eq '404'
|
535
577
|
expect(payload_a.code).to eq 'missing_relationship'
|
536
578
|
expect(payload_a.title).to eq 'Unable to find the requested relationship'
|
537
|
-
expect(payload_a.pointer).to eq '/data/relationships/examples/0/id'
|
579
|
+
expect(payload_a.pointer).to eq '/data/relationships/examples/data/0/id'
|
538
580
|
expect(payload_a.detail).to eq "Unable to find 'persons' with matching id: \"foobar\""
|
539
581
|
|
540
582
|
payload_b = e.payload.last
|
541
583
|
expect(payload_b.status).to eq '404'
|
542
584
|
expect(payload_b.code).to eq 'missing_relationship'
|
543
585
|
expect(payload_b.title).to eq 'Unable to find the requested relationship'
|
544
|
-
expect(payload_b.pointer).to eq '/data/relationships/examples/1/id'
|
586
|
+
expect(payload_b.pointer).to eq '/data/relationships/examples/data/1/id'
|
545
587
|
expect(payload_b.detail).to eq "Unable to find 'persons' with matching id: \"blargh\""
|
546
588
|
end
|
547
589
|
end
|
@@ -19,8 +19,41 @@ describe FunWithJsonApi::FindCollectionFromDocument do
|
|
19
19
|
.and_return([resource])
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
context 'when the resource is authorised' do
|
23
|
+
before do
|
24
|
+
resource_authorizer = double(:resource_authorizer)
|
25
|
+
allow(resource_authorizer).to receive(:call).with(resource).and_return(true)
|
26
|
+
allow(deserializer).to receive(:resource_authorizer).and_return(resource_authorizer)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns the resource in a array' do
|
30
|
+
expect(subject).to eq [resource]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when the resource is unauthorised' do
|
35
|
+
before do
|
36
|
+
resource_authorizer = double(:resource_authorizer)
|
37
|
+
allow(resource_authorizer).to receive(:call).with(resource).and_return(false)
|
38
|
+
allow(deserializer).to receive(:resource_authorizer).and_return(resource_authorizer)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'raises a UnauthorisedResource error' do
|
42
|
+
expect do
|
43
|
+
subject
|
44
|
+
end.to raise_error(FunWithJsonApi::Exceptions::UnauthorisedResource) do |e|
|
45
|
+
expect(e.payload.size).to eq 1
|
46
|
+
|
47
|
+
payload = e.payload.first
|
48
|
+
expect(payload.status).to eq '403'
|
49
|
+
expect(payload.code).to eq 'unauthorized_resource'
|
50
|
+
expect(payload.title).to eq 'Unable to access the requested resource'
|
51
|
+
expect(payload.detail).to eq(
|
52
|
+
"Unable to assign the requested 'person' (42) to the current resource"
|
53
|
+
)
|
54
|
+
expect(payload.pointer).to eq '/data/0/id'
|
55
|
+
end
|
56
|
+
end
|
24
57
|
end
|
25
58
|
end
|
26
59
|
|
@@ -74,8 +107,53 @@ describe FunWithJsonApi::FindCollectionFromDocument do
|
|
74
107
|
.and_return([resource_a, resource_b, resource_c])
|
75
108
|
end
|
76
109
|
|
77
|
-
|
78
|
-
|
110
|
+
context 'when all resources are authorised' do
|
111
|
+
before do
|
112
|
+
resource_authorizer = double(:resource_authorizer)
|
113
|
+
[resource_a, resource_b, resource_c].each do |resource|
|
114
|
+
allow(resource_authorizer).to receive(:call).with(resource).and_return(true)
|
115
|
+
end
|
116
|
+
allow(deserializer).to receive(:resource_authorizer).and_return(resource_authorizer)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'returns all resources in a array' do
|
120
|
+
expect(subject).to eq [resource_a, resource_b, resource_c]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'when there are unauthorised resources' do
|
125
|
+
before do
|
126
|
+
resource_authorizer = double(:resource_authorizer)
|
127
|
+
allow(resource_authorizer).to receive(:call).and_return(false)
|
128
|
+
allow(resource_authorizer).to receive(:call).with(resource_b).and_return(true)
|
129
|
+
allow(deserializer).to receive(:resource_authorizer).and_return(resource_authorizer)
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'raises a UnauthorisedResource error' do
|
133
|
+
expect do
|
134
|
+
subject
|
135
|
+
end.to raise_error(FunWithJsonApi::Exceptions::UnauthorisedResource) do |e|
|
136
|
+
expect(e.payload.size).to eq 2
|
137
|
+
|
138
|
+
payload = e.payload.first
|
139
|
+
expect(payload.status).to eq '403'
|
140
|
+
expect(payload.code).to eq 'unauthorized_resource'
|
141
|
+
expect(payload.title).to eq 'Unable to access the requested resource'
|
142
|
+
expect(payload.detail).to eq(
|
143
|
+
"Unable to assign the requested 'person' (42) to the current resource"
|
144
|
+
)
|
145
|
+
expect(payload.pointer).to eq '/data/0/id'
|
146
|
+
|
147
|
+
payload = e.payload.second
|
148
|
+
expect(payload.status).to eq '403'
|
149
|
+
expect(payload.code).to eq 'unauthorized_resource'
|
150
|
+
expect(payload.title).to eq 'Unable to access the requested resource'
|
151
|
+
expect(payload.detail).to eq(
|
152
|
+
"Unable to assign the requested 'person' (44) to the current resource"
|
153
|
+
)
|
154
|
+
expect(payload.pointer).to eq '/data/2/id'
|
155
|
+
end
|
156
|
+
end
|
79
157
|
end
|
80
158
|
end
|
81
159
|
|
@@ -19,10 +19,44 @@ describe FunWithJsonApi::FindResourceFromDocument do
|
|
19
19
|
.and_return(resource)
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
context 'when the resource is authorised' do
|
23
|
+
before do
|
24
|
+
resource_authorizer = double(:resource_authorizer)
|
25
|
+
allow(resource_authorizer).to receive(:call).with(resource).and_return(true)
|
26
|
+
allow(deserializer).to receive(:resource_authorizer).and_return(resource_authorizer)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns the resource' do
|
30
|
+
expect(subject).to eq resource
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when the resource is unauthorised' do
|
35
|
+
before do
|
36
|
+
resource_authorizer = double(:resource_authorizer)
|
37
|
+
allow(resource_authorizer).to receive(:call).with(resource).and_return(false)
|
38
|
+
allow(deserializer).to receive(:resource_authorizer).and_return(resource_authorizer)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'raises a UnauthorisedResource error' do
|
42
|
+
expect do
|
43
|
+
subject
|
44
|
+
end.to raise_error(FunWithJsonApi::Exceptions::UnauthorisedResource) do |e|
|
45
|
+
expect(e.payload.size).to eq 1
|
46
|
+
|
47
|
+
payload = e.payload.first
|
48
|
+
expect(payload.status).to eq '403'
|
49
|
+
expect(payload.code).to eq 'unauthorized_resource'
|
50
|
+
expect(payload.title).to eq 'Unable to access the requested resource'
|
51
|
+
expect(payload.detail).to eq(
|
52
|
+
"Unable to assign the requested 'person' (42) to the current resource"
|
53
|
+
)
|
54
|
+
expect(payload.pointer).to eq '/data/id'
|
55
|
+
end
|
56
|
+
end
|
24
57
|
end
|
25
58
|
end
|
59
|
+
|
26
60
|
context 'when a resource cannot be found' do
|
27
61
|
let!(:resource) { double('resource') }
|
28
62
|
before do
|
@@ -45,7 +45,7 @@ describe FunWithJsonApi::SchemaValidators::CheckRelationships do
|
|
45
45
|
|
46
46
|
payload = e.payload.first
|
47
47
|
expect(payload.code).to eq 'invalid_relationship_type'
|
48
|
-
expect(payload.pointer).to eq '/data/relationships/foobar/type'
|
48
|
+
expect(payload.pointer).to eq '/data/relationships/foobar/data/type'
|
49
49
|
expect(payload.title).to eq(
|
50
50
|
'Request json_api relationship type does not match expected resource'
|
51
51
|
)
|
@@ -97,7 +97,7 @@ describe FunWithJsonApi::SchemaValidators::CheckRelationships do
|
|
97
97
|
|
98
98
|
payload = e.payload.first
|
99
99
|
expect(payload.code).to eq 'invalid_relationship_type'
|
100
|
-
expect(payload.pointer).to eq '/data/relationships/foobar/0/type'
|
100
|
+
expect(payload.pointer).to eq '/data/relationships/foobar/data/0/type'
|
101
101
|
expect(payload.title).to eq(
|
102
102
|
'Request json_api relationship type does not match expected resource'
|
103
103
|
)
|
@@ -127,6 +127,74 @@ describe FunWithJsonApi do
|
|
127
127
|
comment_ids: [5, 12]
|
128
128
|
)
|
129
129
|
end
|
130
|
+
it 'allows for a relationship resource to be authorized' do
|
131
|
+
post = ARModels::Post.create(id: 1)
|
132
|
+
ARModels::Author.create(id: 9)
|
133
|
+
|
134
|
+
post_json = {
|
135
|
+
'data': {
|
136
|
+
'type': 'posts',
|
137
|
+
'id': '1',
|
138
|
+
'relationships': {
|
139
|
+
'author': {
|
140
|
+
'data': { 'type': 'person', 'id': '9' }
|
141
|
+
}
|
142
|
+
}
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
expect do
|
147
|
+
described_class.deserialize(
|
148
|
+
post_json,
|
149
|
+
ARModels::PostDeserializer,
|
150
|
+
post,
|
151
|
+
author: { resource_authorizer: ->(author) { author.id != 9 } }
|
152
|
+
)
|
153
|
+
end.to raise_error(FunWithJsonApi::Exceptions::UnauthorisedResource) do |e|
|
154
|
+
expect(e.payload.size).to eq 1
|
155
|
+
expect(e.payload.first.pointer).to eq '/data/relationships/author/data/id'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
it 'allows for relationship collections to be authorized' do
|
159
|
+
post = ARModels::Post.create(id: 1)
|
160
|
+
ARModels::Author.create(id: 9)
|
161
|
+
ARModels::Comment.create(id: 5, contents: 'Blargh')
|
162
|
+
ARModels::Comment.create(id: 12, contents: 'Foobar')
|
163
|
+
|
164
|
+
post_json = {
|
165
|
+
'data': {
|
166
|
+
'type': 'posts',
|
167
|
+
'id': '1',
|
168
|
+
'attributes': {
|
169
|
+
'title': 'Rails is Omakase',
|
170
|
+
'body': 'This is my post body'
|
171
|
+
},
|
172
|
+
'relationships': {
|
173
|
+
'author': {
|
174
|
+
'data': { 'type': 'person', 'id': '9' }
|
175
|
+
},
|
176
|
+
'comments': {
|
177
|
+
'data': [
|
178
|
+
{ 'type': 'comments', 'id': '5' },
|
179
|
+
{ 'type': 'comments', 'id': '12' }
|
180
|
+
]
|
181
|
+
}
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
expect do
|
187
|
+
described_class.deserialize(
|
188
|
+
post_json,
|
189
|
+
ARModels::PostDeserializer,
|
190
|
+
post,
|
191
|
+
comments: { resource_authorizer: ->(comment) { comment.contents == 'Foobar' } }
|
192
|
+
)
|
193
|
+
end.to raise_error(FunWithJsonApi::Exceptions::UnauthorisedResource) do |e|
|
194
|
+
expect(e.payload.size).to eq 1
|
195
|
+
expect(e.payload.first.pointer).to eq '/data/relationships/comments/data/0/id'
|
196
|
+
end
|
197
|
+
end
|
130
198
|
end
|
131
199
|
end
|
132
200
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fun_with_json_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6.pre.alpha.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Morrall
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -178,6 +178,7 @@ files:
|
|
178
178
|
- lib/fun_with_json_api/exceptions/invalid_relationship_type.rb
|
179
179
|
- lib/fun_with_json_api/exceptions/missing_relationship.rb
|
180
180
|
- lib/fun_with_json_api/exceptions/missing_resource.rb
|
181
|
+
- lib/fun_with_json_api/exceptions/unauthorized_resource.rb
|
181
182
|
- lib/fun_with_json_api/exceptions/unknown_attribute.rb
|
182
183
|
- lib/fun_with_json_api/exceptions/unknown_relationship.rb
|
183
184
|
- lib/fun_with_json_api/find_collection_from_document.rb
|
@@ -186,9 +187,12 @@ files:
|
|
186
187
|
- lib/fun_with_json_api/railtie.rb
|
187
188
|
- lib/fun_with_json_api/schema_validator.rb
|
188
189
|
- lib/fun_with_json_api/schema_validators/check_attributes.rb
|
190
|
+
- lib/fun_with_json_api/schema_validators/check_collection_has_all_members.rb
|
191
|
+
- lib/fun_with_json_api/schema_validators/check_collection_is_authorized.rb
|
189
192
|
- lib/fun_with_json_api/schema_validators/check_document_id_matches_resource.rb
|
190
193
|
- lib/fun_with_json_api/schema_validators/check_document_type_matches_resource.rb
|
191
194
|
- lib/fun_with_json_api/schema_validators/check_relationships.rb
|
195
|
+
- lib/fun_with_json_api/schema_validators/check_resource_is_authorized.rb
|
192
196
|
- lib/fun_with_json_api/version.rb
|
193
197
|
- lib/tasks/fun_with_json_api_tasks.rake
|
194
198
|
- spec/dummy/README.rdoc
|
@@ -257,9 +261,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
257
261
|
version: '0'
|
258
262
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
259
263
|
requirements:
|
260
|
-
- - "
|
264
|
+
- - ">"
|
261
265
|
- !ruby/object:Gem::Version
|
262
|
-
version:
|
266
|
+
version: 1.3.1
|
263
267
|
requirements: []
|
264
268
|
rubyforge_project:
|
265
269
|
rubygems_version: 2.5.2
|