jsonapi-authorization 0.5.0 → 0.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 29b3ceafd8c61b2dfe1d2ac684714569d8cb70a2
4
- data.tar.gz: 5fc76942b71575e6cfd4b0700c0d26572d681c65
3
+ metadata.gz: 47495edb7695129cd3ddd577ce547db63df70b4f
4
+ data.tar.gz: 68f2686dfa2143ec831816e39b02a1c2170ec3a0
5
5
  SHA512:
6
- metadata.gz: 037b2a7cb5a7418d18c848a0044ca1c93d81386c897253713137323221ebdfdedc9b69609d0e177299939ce0b83ce2ab541bad9a53ffa29a3a72750483ce19e8
7
- data.tar.gz: 51fb54f0056bfedd6caf847cd00012cf1c45cc04897004c4e6546c78d25fa38177fcfbf1e7e02f0ff17b293679bfea85f88d9b67e490f2883c9f35a1db0b04ae
6
+ metadata.gz: 79314420e9e62352436beca771f31823a9fc2bfb72122deada6a4bac09941ee4593b9f468747392ddfbe0169a6737f1d7b93a3b17c486000fcf223ca8faf1f19
7
+ data.tar.gz: 87389fd2aa637d0233666f747fab5c8aaded2371594d09915879d70d6d6e0120327b9a2cf3bd00bea35d17036cb34705aeeea7a7338f98024a9fecb8f5d2fcc5
data/bin/console CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "bundler/setup"
4
+ require "rails/all"
4
5
  require "jsonapi/authorization"
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
@@ -10,5 +11,5 @@ require "jsonapi/authorization"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
- IRB.start
14
+ require "pry"
15
+ Pry.start
@@ -17,6 +17,32 @@ module JSONAPI
17
17
  set_callback :remove_to_many_relationship_operation, :before, :authorize_remove_to_many_relationship
18
18
  set_callback :remove_to_one_relationship_operation, :before, :authorize_remove_to_one_relationship
19
19
 
20
+ [
21
+ :find_operation,
22
+ :show_operation,
23
+ :show_related_resource_operation,
24
+ :show_related_resources_operation,
25
+ :create_resource_operation,
26
+ :replace_fields_operation
27
+ ].each do |op_name|
28
+ set_callback op_name, :after, :authorize_include_directive
29
+ end
30
+
31
+ def authorize_include_directive
32
+ return if @result.is_a?(::JSONAPI::ErrorsOperationResult)
33
+ resources = Array.wrap(
34
+ if @result.respond_to?(:resources)
35
+ @result.resources
36
+ elsif @result.respond_to?(:resource)
37
+ @result.resource
38
+ end
39
+ )
40
+
41
+ resources.each do |resource|
42
+ authorize_model_includes(resource._model)
43
+ end
44
+ end
45
+
20
46
  def authorize_find
21
47
  authorizer.find(@operation.resource_klass._model_class)
22
48
  end
@@ -209,8 +235,12 @@ module JSONAPI
209
235
  end
210
236
  end
211
237
 
238
+ def resource_class_for_relationship(assoc_name)
239
+ @operation.resource_klass._relationship(assoc_name).resource_klass
240
+ end
241
+
212
242
  def model_class_for_relationship(assoc_name)
213
- @operation.resource_klass._relationship(assoc_name).resource_klass._model_class
243
+ resource_class_for_relationship(assoc_name)._model_class
214
244
  end
215
245
 
216
246
  def related_models
@@ -218,13 +248,71 @@ module JSONAPI
218
248
  return [] if data.nil?
219
249
 
220
250
  [:to_one, :to_many].flat_map do |rel_type|
221
- data[rel_type].flat_map do |assoc_name, assoc_ids|
222
- assoc_klass = model_class_for_relationship(assoc_name)
223
- # TODO: find_by_key?
224
- assoc_klass.find(assoc_ids)
251
+ data[rel_type].flat_map do |assoc_name, assoc_value|
252
+ case assoc_value
253
+ when Hash # polymorphic relationship
254
+ resource_class = @operation.resource_klass.resource_for(assoc_value[:type].to_s)
255
+ resource_class.find_by_key(assoc_value[:id], context: @operation.options[:context])._model
256
+ else
257
+ resource_class = resource_class_for_relationship(assoc_name)
258
+ primary_key = resource_class._primary_key
259
+ resource_class._model_class.where(primary_key => assoc_value)
260
+ end
225
261
  end
226
262
  end
227
263
  end
264
+
265
+ def authorize_model_includes(source_record)
266
+ if @request.include_directives
267
+ @request.include_directives.model_includes.each do |include_item|
268
+ authorize_include_item(@operation.resource_klass, source_record, include_item)
269
+ end
270
+ end
271
+ end
272
+
273
+ def authorize_include_item(resource_klass, source_record, include_item)
274
+ case include_item
275
+ when Hash
276
+ # e.g. {articles: [:comments, :author]} when ?include=articles.comments,articles.author
277
+ include_item.each do |rel_name, deep|
278
+ authorize_include_item(resource_klass, source_record, rel_name)
279
+ relationship = resource_klass._relationship(rel_name)
280
+ next_resource_klass = relationship.resource_klass
281
+ Array.wrap(
282
+ source_record.public_send(
283
+ relationship.relation_name(@operation.options[:context])
284
+ )
285
+ ).each do |next_source_record|
286
+ deep.each do |next_include_item|
287
+ authorize_include_item(
288
+ next_resource_klass,
289
+ next_source_record,
290
+ next_include_item
291
+ )
292
+ end
293
+ end
294
+ end
295
+ when Symbol
296
+ relationship = resource_klass._relationship(include_item)
297
+ case relationship
298
+ when JSONAPI::Relationship::ToOne
299
+ related_record = source_record.public_send(
300
+ relationship.relation_name(@operation.options[:context])
301
+ )
302
+ return if related_record.nil?
303
+ authorizer.include_has_one_resource(source_record, related_record)
304
+ when JSONAPI::Relationship::ToMany
305
+ authorizer.include_has_many_resource(
306
+ source_record,
307
+ relationship.resource_klass._model_class
308
+ )
309
+ else
310
+ raise "Unexpected relationship type: #{relationship.inspect}"
311
+ end
312
+ else
313
+ raise "Unknown include directive: #{include_item}"
314
+ end
315
+ end
228
316
  end
229
317
  end
230
318
  end
@@ -190,6 +190,40 @@ module JSONAPI
190
190
  def remove_to_one_relationship(source_record, related_record)
191
191
  raise NotImplementedError
192
192
  end
193
+
194
+ # Any request including <tt>?include=other-resources</tt>
195
+ #
196
+ # This will be called for each has_many relationship if the include goes
197
+ # deeper than one level until some authorization fails or the include
198
+ # directive has been travelled completely.
199
+ #
200
+ # We can't pass all the records of a +has_many+ association here due to
201
+ # performance reasons, so the class is passed instead.
202
+ #
203
+ # ==== Parameters
204
+ #
205
+ # * +source_record+ — The source relationship record, e.g. an Article in
206
+ # article.comments check
207
+ # * +record_class+ - The underlying record class for the relationships
208
+ # resource.
209
+ def include_has_many_resource(source_record, record_class)
210
+ ::Pundit.authorize(user, record_class, 'index?')
211
+ end
212
+
213
+ # Any request including <tt>?include=another-resource</tt>
214
+ #
215
+ # This will be called for each has_one relationship if the include goes
216
+ # deeper than one level until some authorization fails or the include
217
+ # directive has been travelled completely.
218
+ #
219
+ # ==== Parameters
220
+ #
221
+ # * +source_record+ — The source relationship record, e.g. an Article in
222
+ # article.author check
223
+ # * +related_record+ - The associated record to return
224
+ def include_has_one_resource(source_record, related_record)
225
+ ::Pundit.authorize(user, related_record, 'show?')
226
+ end
193
227
  end
194
228
  end
195
229
  end
@@ -1,5 +1,5 @@
1
1
  module JSONAPI
2
2
  module Authorization
3
- VERSION = "0.5.0".freeze
3
+ VERSION = "0.6.0".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapi-authorization
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vesa Laakso
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-01-28 00:00:00.000000000 Z
12
+ date: 2016-03-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: jsonapi-resources