cancancan 1.11.0 → 2.3.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 +5 -5
- data/cancancan.gemspec +15 -19
- data/lib/cancan/ability/actions.rb +91 -0
- data/lib/cancan/ability/rules.rb +85 -0
- data/lib/cancan/ability.rb +74 -136
- data/lib/cancan/conditions_matcher.rb +93 -0
- data/lib/cancan/controller_additions.rb +34 -40
- data/lib/cancan/controller_resource.rb +47 -212
- data/lib/cancan/controller_resource_builder.rb +24 -0
- data/lib/cancan/controller_resource_finder.rb +40 -0
- data/lib/cancan/controller_resource_loader.rb +116 -0
- data/lib/cancan/controller_resource_name_finder.rb +21 -0
- data/lib/cancan/controller_resource_sanitizer.rb +30 -0
- data/lib/cancan/exceptions.rb +7 -3
- data/lib/cancan/matchers.rb +12 -3
- data/lib/cancan/model_adapters/abstract_adapter.rb +8 -8
- data/lib/cancan/model_adapters/active_record_4_adapter.rb +33 -10
- data/lib/cancan/model_adapters/active_record_5_adapter.rb +70 -0
- data/lib/cancan/model_adapters/active_record_adapter.rb +41 -81
- data/lib/cancan/model_adapters/can_can/model_adapters/active_record_adapter/joins.rb +39 -0
- data/lib/cancan/model_adapters/conditions_extractor.rb +75 -0
- data/lib/cancan/model_additions.rb +0 -1
- data/lib/cancan/rule.rb +36 -92
- data/lib/cancan/rules_compressor.rb +20 -0
- data/lib/cancan/version.rb +1 -1
- data/lib/cancan.rb +5 -12
- data/lib/generators/cancan/ability/ability_generator.rb +1 -1
- metadata +54 -65
- data/.gitignore +0 -15
- data/.rspec +0 -1
- data/.travis.yml +0 -55
- data/Appraisals +0 -136
- data/CHANGELOG.rdoc +0 -503
- data/CONTRIBUTING.md +0 -23
- data/Gemfile +0 -3
- data/LICENSE +0 -22
- data/README.md +0 -188
- data/Rakefile +0 -9
- data/gemfiles/activerecord_3.0.gemfile +0 -18
- data/gemfiles/activerecord_3.1.gemfile +0 -20
- data/gemfiles/activerecord_3.2.gemfile +0 -20
- data/gemfiles/activerecord_4.0.gemfile +0 -17
- data/gemfiles/activerecord_4.1.gemfile +0 -17
- data/gemfiles/activerecord_4.2.gemfile +0 -18
- data/gemfiles/datamapper_1.x.gemfile +0 -14
- data/gemfiles/mongoid_2.x.gemfile +0 -20
- data/gemfiles/sequel_3.x.gemfile +0 -20
- data/lib/cancan/inherited_resource.rb +0 -20
- data/lib/cancan/model_adapters/active_record_3_adapter.rb +0 -47
- data/lib/cancan/model_adapters/data_mapper_adapter.rb +0 -34
- data/lib/cancan/model_adapters/mongoid_adapter.rb +0 -54
- data/lib/cancan/model_adapters/sequel_adapter.rb +0 -87
- data/spec/README.rdoc +0 -27
- data/spec/cancan/ability_spec.rb +0 -487
- data/spec/cancan/controller_additions_spec.rb +0 -141
- data/spec/cancan/controller_resource_spec.rb +0 -632
- data/spec/cancan/exceptions_spec.rb +0 -58
- data/spec/cancan/inherited_resource_spec.rb +0 -71
- data/spec/cancan/matchers_spec.rb +0 -29
- data/spec/cancan/model_adapters/active_record_4_adapter_spec.rb +0 -85
- data/spec/cancan/model_adapters/active_record_adapter_spec.rb +0 -446
- data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +0 -119
- data/spec/cancan/model_adapters/default_adapter_spec.rb +0 -7
- data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +0 -227
- data/spec/cancan/model_adapters/sequel_adapter_spec.rb +0 -132
- data/spec/cancan/rule_spec.rb +0 -52
- data/spec/matchers.rb +0 -13
- data/spec/spec.opts +0 -2
- data/spec/spec_helper.rb +0 -28
- data/spec/support/ability.rb +0 -7
@@ -1,5 +1,4 @@
|
|
1
1
|
module CanCan
|
2
|
-
|
3
2
|
# This module is automatically included into all controllers.
|
4
3
|
# It also makes the "can?" and "cannot?" methods available to all views.
|
5
4
|
module ControllerAdditions
|
@@ -12,7 +11,7 @@ module CanCan
|
|
12
11
|
# end
|
13
12
|
#
|
14
13
|
def load_and_authorize_resource(*args)
|
15
|
-
cancan_resource_class.
|
14
|
+
cancan_resource_class.add_before_action(self, :load_and_authorize_resource, *args)
|
16
15
|
end
|
17
16
|
|
18
17
|
# Sets up a before filter which loads the model resource into an instance variable.
|
@@ -32,16 +31,16 @@ module CanCan
|
|
32
31
|
# end
|
33
32
|
#
|
34
33
|
# A resource is not loaded if the instance variable is already set. This makes it easy to override
|
35
|
-
# the behavior through a
|
34
|
+
# the behavior through a before_action on certain actions.
|
36
35
|
#
|
37
36
|
# class BooksController < ApplicationController
|
38
|
-
#
|
37
|
+
# before_action :find_book_by_permalink, :only => :show
|
39
38
|
# load_resource
|
40
39
|
#
|
41
40
|
# private
|
42
41
|
#
|
43
42
|
# def find_book_by_permalink
|
44
|
-
# @book = Book.find_by_permalink!(params[:id)
|
43
|
+
# @book = Book.find_by_permalink!(params[:id])
|
45
44
|
# end
|
46
45
|
# end
|
47
46
|
#
|
@@ -72,8 +71,8 @@ module CanCan
|
|
72
71
|
# Load this resource through another one. This should match the name of the parent instance variable or method.
|
73
72
|
#
|
74
73
|
# [:+through_association+]
|
75
|
-
# The name of the association to fetch the child records through the parent resource.
|
76
|
-
# because it defaults to the pluralized resource name.
|
74
|
+
# The name of the association to fetch the child records through the parent resource.
|
75
|
+
# This is normally not needed because it defaults to the pluralized resource name.
|
77
76
|
#
|
78
77
|
# [:+shallow+]
|
79
78
|
# Pass +true+ to allow this resource to be loaded directly when parent is +nil+. Defaults to +false+.
|
@@ -82,8 +81,8 @@ module CanCan
|
|
82
81
|
# Pass +true+ if this is a singleton resource through a +has_one+ association.
|
83
82
|
#
|
84
83
|
# [:+parent+]
|
85
|
-
# True or false depending on if the resource is considered a parent resource.
|
86
|
-
# name is given which does not match the controller.
|
84
|
+
# True or false depending on if the resource is considered a parent resource.
|
85
|
+
# This defaults to +true+ if a resource name is given which does not match the controller.
|
87
86
|
#
|
88
87
|
# [:+class+]
|
89
88
|
# The class to use for the model (string or constant).
|
@@ -115,10 +114,10 @@ module CanCan
|
|
115
114
|
# load_resource :new => :build
|
116
115
|
#
|
117
116
|
# [:+prepend+]
|
118
|
-
# Passing +true+ will use
|
117
|
+
# Passing +true+ will use prepend_before_action instead of a normal before_action.
|
119
118
|
#
|
120
119
|
def load_resource(*args)
|
121
|
-
cancan_resource_class.
|
120
|
+
cancan_resource_class.add_before_action(self, :load_resource, *args)
|
122
121
|
end
|
123
122
|
|
124
123
|
# Sets up a before filter which authorizes the resource using the instance variable.
|
@@ -160,8 +159,8 @@ module CanCan
|
|
160
159
|
# Pass +true+ if this is a singleton resource through a +has_one+ association.
|
161
160
|
#
|
162
161
|
# [:+parent+]
|
163
|
-
# True or false depending on if the resource is considered a parent resource.
|
164
|
-
# name is given which does not match the controller.
|
162
|
+
# True or false depending on if the resource is considered a parent resource.
|
163
|
+
# This defaults to +true+ if a resource name is given which does not match the controller.
|
165
164
|
#
|
166
165
|
# [:+class+]
|
167
166
|
# The class to use for the model (string or constant). This passed in when the instance variable is not set.
|
@@ -174,10 +173,10 @@ module CanCan
|
|
174
173
|
# Authorize conditions on this parent resource when instance isn't available.
|
175
174
|
#
|
176
175
|
# [:+prepend+]
|
177
|
-
# Passing +true+ will use
|
176
|
+
# Passing +true+ will use prepend_before_action instead of a normal before_action.
|
178
177
|
#
|
179
178
|
def authorize_resource(*args)
|
180
|
-
cancan_resource_class.
|
179
|
+
cancan_resource_class.add_before_action(self, :authorize_resource, *args)
|
181
180
|
end
|
182
181
|
|
183
182
|
# Skip both the loading and authorization behavior of CanCan for this given controller. This is primarily
|
@@ -227,7 +226,8 @@ module CanCan
|
|
227
226
|
end
|
228
227
|
|
229
228
|
# Add this to a controller to ensure it performs authorization through +authorized+! or +authorize_resource+ call.
|
230
|
-
# If neither of these authorization methods are called,
|
229
|
+
# If neither of these authorization methods are called,
|
230
|
+
# a CanCan::AuthorizationNotPerformed exception will be raised.
|
231
231
|
# This is normally added to the ApplicationController to ensure all controller actions do authorization.
|
232
232
|
#
|
233
233
|
# class ApplicationController < ActionController::Base
|
@@ -244,22 +244,28 @@ module CanCan
|
|
244
244
|
# Does not apply to given actions.
|
245
245
|
#
|
246
246
|
# [:+if+]
|
247
|
-
# Supply the name of a controller method to be called.
|
247
|
+
# Supply the name of a controller method to be called.
|
248
|
+
# The authorization check only takes place if this returns true.
|
248
249
|
#
|
249
250
|
# check_authorization :if => :admin_controller?
|
250
251
|
#
|
251
252
|
# [:+unless+]
|
252
|
-
# Supply the name of a controller method to be called.
|
253
|
+
# Supply the name of a controller method to be called.
|
254
|
+
# The authorization check only takes place if this returns false.
|
253
255
|
#
|
254
256
|
# check_authorization :unless => :devise_controller?
|
255
257
|
#
|
256
258
|
def check_authorization(options = {})
|
257
|
-
|
259
|
+
block = proc do |controller|
|
258
260
|
next if controller.instance_variable_defined?(:@_authorized)
|
259
261
|
next if options[:if] && !controller.send(options[:if])
|
260
262
|
next if options[:unless] && controller.send(options[:unless])
|
261
|
-
raise AuthorizationNotPerformed,
|
263
|
+
raise AuthorizationNotPerformed,
|
264
|
+
'This action failed the check_authorization because it does not authorize_resource. '\
|
265
|
+
'Add skip_authorization_check to bypass this check.'
|
262
266
|
end
|
267
|
+
|
268
|
+
send(:after_action, options.slice(:only, :except), &block)
|
263
269
|
end
|
264
270
|
|
265
271
|
# Call this in the class of a controller to skip the check_authorization behavior on the actions.
|
@@ -268,33 +274,25 @@ module CanCan
|
|
268
274
|
# skip_authorization_check :only => :index
|
269
275
|
# end
|
270
276
|
#
|
271
|
-
# Any arguments are passed to the +
|
277
|
+
# Any arguments are passed to the +before_action+ it triggers.
|
272
278
|
def skip_authorization_check(*args)
|
273
|
-
|
274
|
-
|
275
|
-
end
|
276
|
-
end
|
277
|
-
|
278
|
-
def skip_authorization(*args)
|
279
|
-
raise ImplementationRemoved, "The CanCan skip_authorization method has been renamed to skip_authorization_check. Please update your code."
|
279
|
+
block = proc { |controller| controller.instance_variable_set(:@_authorized, true) }
|
280
|
+
send(:before_action, *args, &block)
|
280
281
|
end
|
281
282
|
|
282
283
|
def cancan_resource_class
|
283
|
-
|
284
|
-
InheritedResource
|
285
|
-
else
|
286
|
-
ControllerResource
|
287
|
-
end
|
284
|
+
ControllerResource
|
288
285
|
end
|
289
286
|
|
290
287
|
def cancan_skipper
|
291
|
-
|
288
|
+
self._cancan_skipper ||= { authorize: {}, load: {} }
|
292
289
|
end
|
293
290
|
end
|
294
291
|
|
295
292
|
def self.included(base)
|
296
293
|
base.extend ClassMethods
|
297
294
|
base.helper_method :can?, :cannot?, :current_ability if base.respond_to? :helper_method
|
295
|
+
base.class_attribute :_cancan_skipper
|
298
296
|
end
|
299
297
|
|
300
298
|
# Raises a CanCan::AccessDenied exception if the current_ability cannot
|
@@ -338,10 +336,6 @@ module CanCan
|
|
338
336
|
current_ability.authorize!(*args)
|
339
337
|
end
|
340
338
|
|
341
|
-
def unauthorized!(message = nil)
|
342
|
-
raise ImplementationRemoved, "The unauthorized! method has been removed from CanCan, use authorize! instead."
|
343
|
-
end
|
344
|
-
|
345
339
|
# Creates and returns the current user's ability and caches it. If you
|
346
340
|
# want to override how the Ability is defined then this is the place.
|
347
341
|
# Just define the method in the controller to change behavior.
|
@@ -390,8 +384,8 @@ module CanCan
|
|
390
384
|
end
|
391
385
|
end
|
392
386
|
|
393
|
-
if defined?
|
394
|
-
|
387
|
+
if defined? ActiveSupport
|
388
|
+
ActiveSupport.on_load(:action_controller) do
|
395
389
|
include CanCan::ControllerAdditions
|
396
390
|
end
|
397
391
|
end
|
@@ -1,24 +1,30 @@
|
|
1
|
+
require_relative 'controller_resource_loader.rb'
|
1
2
|
module CanCan
|
2
|
-
# Handle the load and authorization controller logic
|
3
|
+
# Handle the load and authorization controller logic
|
4
|
+
# so we don't clutter up all controllers with non-interface methods.
|
3
5
|
# This class is used internally, so you do not need to call methods directly on it.
|
4
6
|
class ControllerResource # :nodoc:
|
5
|
-
|
7
|
+
include ControllerResourceLoader
|
8
|
+
|
9
|
+
def self.add_before_action(controller_class, method, *args)
|
6
10
|
options = args.extract_options!
|
7
11
|
resource_name = args.first
|
8
|
-
|
9
|
-
controller_class.send(
|
10
|
-
controller.class.cancan_resource_class
|
12
|
+
before_action_method = before_callback_name(options)
|
13
|
+
controller_class.send(before_action_method, options.slice(:only, :except, :if, :unless)) do |controller|
|
14
|
+
controller.class.cancan_resource_class
|
15
|
+
.new(controller, resource_name, options.except(:only, :except, :if, :unless)).send(method)
|
11
16
|
end
|
12
17
|
end
|
13
18
|
|
19
|
+
def self.before_callback_name(options)
|
20
|
+
options.delete(:prepend) ? :prepend_before_action : :before_action
|
21
|
+
end
|
22
|
+
|
14
23
|
def initialize(controller, *args)
|
15
24
|
@controller = controller
|
16
25
|
@params = controller.params
|
17
26
|
@options = args.extract_options!
|
18
27
|
@name = args.first
|
19
|
-
raise CanCan::ImplementationRemoved, "The :nested option is no longer supported, instead use :through with separate load/authorize call." if @options[:nested]
|
20
|
-
raise CanCan::ImplementationRemoved, "The :name option is no longer supported, instead pass the name as the first argument." if @options[:name]
|
21
|
-
raise CanCan::ImplementationRemoved, "The :resource option has been renamed back to :class, use false if no class." if @options[:resource]
|
22
28
|
end
|
23
29
|
|
24
30
|
def load_and_authorize_resource
|
@@ -26,41 +32,37 @@ module CanCan
|
|
26
32
|
authorize_resource
|
27
33
|
end
|
28
34
|
|
29
|
-
def load_resource
|
30
|
-
unless skip?(:load)
|
31
|
-
if load_instance?
|
32
|
-
self.resource_instance ||= load_resource_instance
|
33
|
-
elsif load_collection?
|
34
|
-
self.collection_instance ||= load_collection
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
35
|
def authorize_resource
|
40
|
-
|
41
|
-
|
42
|
-
end
|
36
|
+
return if skip?(:authorize)
|
37
|
+
@controller.authorize!(authorization_action, resource_instance || resource_class_with_parent)
|
43
38
|
end
|
44
39
|
|
45
40
|
def parent?
|
46
|
-
@options.
|
41
|
+
@options.key?(:parent) ? @options[:parent] : @name && @name != name_from_controller.to_sym
|
47
42
|
end
|
48
43
|
|
49
44
|
def skip?(behavior)
|
50
|
-
return false unless options = @controller.class.cancan_skipper[behavior][@name]
|
51
|
-
|
45
|
+
return false unless (options = @controller.class.cancan_skipper[behavior][@name])
|
52
46
|
options == {} ||
|
53
|
-
|
54
|
-
|
47
|
+
options[:except] && !action_exists_in?(options[:except]) ||
|
48
|
+
action_exists_in?(options[:only])
|
55
49
|
end
|
56
50
|
|
57
51
|
protected
|
58
52
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
53
|
+
# Returns the class used for this resource. This can be overriden by the :class option.
|
54
|
+
# If +false+ is passed in it will use the resource name as a symbol in which case it should
|
55
|
+
# only be used for authorization, not loading since there's no class to load through.
|
56
|
+
def resource_class
|
57
|
+
case @options[:class]
|
58
|
+
when false
|
59
|
+
name.to_sym
|
60
|
+
when nil
|
61
|
+
namespaced_name.to_s.camelize.constantize
|
62
|
+
when String
|
63
|
+
@options[:class].constantize
|
64
|
+
else
|
65
|
+
@options[:class]
|
64
66
|
end
|
65
67
|
end
|
66
68
|
|
@@ -72,89 +74,14 @@ module CanCan
|
|
72
74
|
resource_base.respond_to?(:accessible_by) && !current_ability.has_block?(authorization_action, resource_class)
|
73
75
|
end
|
74
76
|
|
75
|
-
def load_collection
|
76
|
-
resource_base.accessible_by(current_ability, authorization_action)
|
77
|
-
end
|
78
|
-
|
79
|
-
def build_resource
|
80
|
-
resource = resource_base.new(resource_params || {})
|
81
|
-
assign_attributes(resource)
|
82
|
-
end
|
83
|
-
|
84
|
-
def assign_attributes(resource)
|
85
|
-
resource.send("#{parent_name}=", parent_resource) if @options[:singleton] && parent_resource
|
86
|
-
initial_attributes.each do |attr_name, value|
|
87
|
-
resource.send("#{attr_name}=", value)
|
88
|
-
end
|
89
|
-
resource
|
90
|
-
end
|
91
|
-
|
92
|
-
def initial_attributes
|
93
|
-
current_ability.attributes_for(@params[:action].to_sym, resource_class).delete_if do |key, value|
|
94
|
-
resource_params && resource_params.include?(key)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def find_resource
|
99
|
-
if @options[:singleton] && parent_resource.respond_to?(name)
|
100
|
-
parent_resource.send(name)
|
101
|
-
else
|
102
|
-
if @options[:find_by]
|
103
|
-
if resource_base.respond_to? "find_by_#{@options[:find_by]}!"
|
104
|
-
resource_base.send("find_by_#{@options[:find_by]}!", id_param)
|
105
|
-
elsif resource_base.respond_to? "find_by"
|
106
|
-
resource_base.send("find_by", { @options[:find_by].to_sym => id_param })
|
107
|
-
else
|
108
|
-
resource_base.send(@options[:find_by], id_param)
|
109
|
-
end
|
110
|
-
else
|
111
|
-
adapter.find(resource_base, id_param)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def adapter
|
117
|
-
ModelAdapters::AbstractAdapter.adapter_class(resource_class)
|
118
|
-
end
|
119
|
-
|
120
|
-
def authorization_action
|
121
|
-
parent? ? parent_authorization_action : @params[:action].to_sym
|
122
|
-
end
|
123
|
-
|
124
|
-
def parent_authorization_action
|
125
|
-
@options[:parent_action] || :show
|
126
|
-
end
|
127
|
-
|
128
|
-
def id_param
|
129
|
-
@params[id_param_key].to_s if @params[id_param_key]
|
130
|
-
end
|
131
|
-
|
132
|
-
def id_param_key
|
133
|
-
if @options[:id_param]
|
134
|
-
@options[:id_param]
|
135
|
-
else
|
136
|
-
parent? ? :"#{name}_id" : :id
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
77
|
def member_action?
|
141
|
-
new_actions.include?(@params[:action].to_sym) || @options[:singleton] ||
|
142
|
-
|
143
|
-
|
144
|
-
# Returns the class used for this resource. This can be overriden by the :class option.
|
145
|
-
# If +false+ is passed in it will use the resource name as a symbol in which case it should
|
146
|
-
# only be used for authorization, not loading since there's no class to load through.
|
147
|
-
def resource_class
|
148
|
-
case @options[:class]
|
149
|
-
when false then name.to_sym
|
150
|
-
when nil then namespaced_name.to_s.camelize.constantize
|
151
|
-
when String then @options[:class].constantize
|
152
|
-
else @options[:class]
|
153
|
-
end
|
78
|
+
new_actions.include?(@params[:action].to_sym) || @options[:singleton] ||
|
79
|
+
((@params[:id] || @params[@options[:id_param]]) &&
|
80
|
+
!collection_actions.include?(@params[:action].to_sym))
|
154
81
|
end
|
155
82
|
|
156
83
|
def resource_class_with_parent
|
157
|
-
parent_resource ? {parent_resource => resource_class} : resource_class
|
84
|
+
parent_resource ? { parent_resource => resource_class } : resource_class
|
158
85
|
end
|
159
86
|
|
160
87
|
def resource_instance=(instance)
|
@@ -162,7 +89,8 @@ module CanCan
|
|
162
89
|
end
|
163
90
|
|
164
91
|
def resource_instance
|
165
|
-
@controller.
|
92
|
+
return unless load_instance? && @controller.instance_variable_defined?("@#{instance_name}")
|
93
|
+
@controller.instance_variable_get("@#{instance_name}")
|
166
94
|
end
|
167
95
|
|
168
96
|
def collection_instance=(instance)
|
@@ -170,107 +98,14 @@ module CanCan
|
|
170
98
|
end
|
171
99
|
|
172
100
|
def collection_instance
|
101
|
+
return unless @controller.instance_variable_defined?("@#{instance_name.to_s.pluralize}")
|
173
102
|
@controller.instance_variable_get("@#{instance_name.to_s.pluralize}")
|
174
103
|
end
|
175
104
|
|
176
|
-
# The object that methods (such as "find", "new" or "build") are called on.
|
177
|
-
# If the :through option is passed it will go through an association on that instance.
|
178
|
-
# If the :shallow option is passed it will use the resource_class if there's no parent
|
179
|
-
# If the :singleton option is passed it won't use the association because it needs to be handled later.
|
180
|
-
def resource_base
|
181
|
-
if @options[:through]
|
182
|
-
if parent_resource
|
183
|
-
base = @options[:singleton] ? resource_class : parent_resource.send(@options[:through_association] || name.to_s.pluralize)
|
184
|
-
base = base.scoped if base.respond_to?(:scoped) && defined?(ActiveRecord) && ActiveRecord::VERSION::MAJOR == 3
|
185
|
-
base
|
186
|
-
elsif @options[:shallow]
|
187
|
-
resource_class
|
188
|
-
else
|
189
|
-
raise AccessDenied.new(nil, authorization_action, resource_class) # maybe this should be a record not found error instead?
|
190
|
-
end
|
191
|
-
else
|
192
|
-
resource_class
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
def parent_name
|
197
|
-
@options[:through] && [@options[:through]].flatten.detect { |i| fetch_parent(i) }
|
198
|
-
end
|
199
|
-
|
200
|
-
# The object to load this resource through.
|
201
|
-
def parent_resource
|
202
|
-
parent_name && fetch_parent(parent_name)
|
203
|
-
end
|
204
|
-
|
205
|
-
def fetch_parent(name)
|
206
|
-
if @controller.instance_variable_defined? "@#{name}"
|
207
|
-
@controller.instance_variable_get("@#{name}")
|
208
|
-
elsif @controller.respond_to?(name, true)
|
209
|
-
@controller.send(name)
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
def current_ability
|
214
|
-
@controller.send(:current_ability)
|
215
|
-
end
|
216
|
-
|
217
|
-
def name
|
218
|
-
@name || name_from_controller
|
219
|
-
end
|
220
|
-
|
221
|
-
def resource_params
|
222
|
-
if parameters_require_sanitizing? && params_method.present?
|
223
|
-
return case params_method
|
224
|
-
when Symbol then @controller.send(params_method)
|
225
|
-
when String then @controller.instance_eval(params_method)
|
226
|
-
when Proc then params_method.call(@controller)
|
227
|
-
end
|
228
|
-
else
|
229
|
-
resource_params_by_namespaced_name
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
105
|
def parameters_require_sanitizing?
|
234
106
|
save_actions.include?(@params[:action].to_sym) || resource_params_by_namespaced_name.present?
|
235
107
|
end
|
236
108
|
|
237
|
-
def resource_params_by_namespaced_name
|
238
|
-
if @options[:instance_name] && @params.has_key?(extract_key(@options[:instance_name]))
|
239
|
-
@params[extract_key(@options[:instance_name])]
|
240
|
-
elsif @options[:class] && @params.has_key?(extract_key(@options[:class]))
|
241
|
-
@params[extract_key(@options[:class])]
|
242
|
-
else
|
243
|
-
@params[extract_key(namespaced_name)]
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
def params_method
|
248
|
-
params_methods.each do |method|
|
249
|
-
return method if (method.is_a?(Symbol) && @controller.respond_to?(method, true)) || method.is_a?(String) || method.is_a?(Proc)
|
250
|
-
end
|
251
|
-
nil
|
252
|
-
end
|
253
|
-
|
254
|
-
def params_methods
|
255
|
-
methods = ["#{@params[:action]}_params".to_sym, "#{name}_params".to_sym, :resource_params]
|
256
|
-
methods.unshift(@options[:param_method]) if @options[:param_method].present?
|
257
|
-
methods
|
258
|
-
end
|
259
|
-
|
260
|
-
def namespace
|
261
|
-
@params[:controller].split('/')[0..-2]
|
262
|
-
end
|
263
|
-
|
264
|
-
def namespaced_name
|
265
|
-
[namespace, name.camelize].flatten.map(&:camelize).join('::').singularize.constantize
|
266
|
-
rescue NameError
|
267
|
-
name
|
268
|
-
end
|
269
|
-
|
270
|
-
def name_from_controller
|
271
|
-
@params[:controller].split('/').last.singularize
|
272
|
-
end
|
273
|
-
|
274
109
|
def instance_name
|
275
110
|
@options[:instance_name] || name
|
276
111
|
end
|
@@ -279,12 +114,8 @@ module CanCan
|
|
279
114
|
[:index] + Array(@options[:collection])
|
280
115
|
end
|
281
116
|
|
282
|
-
def new_actions
|
283
|
-
[:new, :create] + Array(@options[:new])
|
284
|
-
end
|
285
|
-
|
286
117
|
def save_actions
|
287
|
-
[
|
118
|
+
%i[create update]
|
288
119
|
end
|
289
120
|
|
290
121
|
private
|
@@ -293,8 +124,12 @@ module CanCan
|
|
293
124
|
Array(options).include?(@params[:action].to_sym)
|
294
125
|
end
|
295
126
|
|
296
|
-
def
|
297
|
-
|
127
|
+
def adapter
|
128
|
+
ModelAdapters::AbstractAdapter.adapter_class(resource_class)
|
129
|
+
end
|
130
|
+
|
131
|
+
def current_ability
|
132
|
+
@controller.send(:current_ability)
|
298
133
|
end
|
299
134
|
end
|
300
135
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module CanCan
|
2
|
+
module ControllerResourceBuilder
|
3
|
+
protected
|
4
|
+
|
5
|
+
def build_resource
|
6
|
+
resource = resource_base.new(resource_params || {})
|
7
|
+
assign_attributes(resource)
|
8
|
+
end
|
9
|
+
|
10
|
+
def assign_attributes(resource)
|
11
|
+
resource.send("#{parent_name}=", parent_resource) if @options[:singleton] && parent_resource
|
12
|
+
initial_attributes.each do |attr_name, value|
|
13
|
+
resource.send("#{attr_name}=", value)
|
14
|
+
end
|
15
|
+
resource
|
16
|
+
end
|
17
|
+
|
18
|
+
def initial_attributes
|
19
|
+
current_ability.attributes_for(@params[:action].to_sym, resource_class).delete_if do |key, _value|
|
20
|
+
resource_params && resource_params.include?(key)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module CanCan
|
2
|
+
module ControllerResourceFinder
|
3
|
+
protected
|
4
|
+
|
5
|
+
def find_resource
|
6
|
+
if @options[:singleton] && parent_resource.respond_to?(name)
|
7
|
+
parent_resource.send(name)
|
8
|
+
elsif @options[:find_by]
|
9
|
+
find_resource_using_find_by
|
10
|
+
else
|
11
|
+
adapter.find(resource_base, id_param)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_resource_using_find_by
|
16
|
+
find_by_dynamic_finder || find_by_find_by_finder || resource_base.send(@options[:find_by], id_param)
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_by_dynamic_finder
|
20
|
+
method_name = "find_by_#{@options[:find_by]}!"
|
21
|
+
resource_base.send(method_name, id_param) if resource_base.respond_to? method_name
|
22
|
+
end
|
23
|
+
|
24
|
+
def find_by_find_by_finder
|
25
|
+
resource_base.find_by(@options[:find_by].to_sym => id_param) if resource_base.respond_to? :find_by
|
26
|
+
end
|
27
|
+
|
28
|
+
def id_param
|
29
|
+
@params[id_param_key].to_s if @params[id_param_key].present?
|
30
|
+
end
|
31
|
+
|
32
|
+
def id_param_key
|
33
|
+
if @options[:id_param]
|
34
|
+
@options[:id_param]
|
35
|
+
else
|
36
|
+
parent? ? :"#{name}_id" : :id
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|