fun_with_json_api 0.0.5 → 0.0.6.pre.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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