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.
@@ -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
- it 'finds a resource by the defined id_param and returns the resource id' do
499
- author_a = ARModels::Author.create(id: 1, code: 'foobar')
500
- author_b = ARModels::Author.create(id: 2, code: 'blargh')
501
- expect(deserializer.parse_example_ids(%w(foobar blargh))).to eq(
502
- [author_a.id, author_b.id]
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
- it 'returns the resource in a array' do
23
- expect(subject).to eq [resource]
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
- it 'returns all resources in a array' do
78
- expect(subject).to eq [resource_a, resource_b, resource_c]
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
- it 'returns the resource' do
23
- expect(subject).to eq resource
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.5
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-29 00:00:00.000000000 Z
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: '0'
266
+ version: 1.3.1
263
267
  requirements: []
264
268
  rubyforge_project:
265
269
  rubygems_version: 2.5.2