cancancan_resource_controller 0.0.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 +7 -0
- data/lib/cancancan/abstract_resource_controller.rb +440 -0
- data/lib/cancancan_resource_controller.rb +4 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a38bfb98462e336b34961d82c4d130022bf466971f55c11699e707b7e6ce4fff
|
4
|
+
data.tar.gz: aa0be9ebb6885fc7b15156d0517f1df7c236c3da081a8cf01f6e5b3bf1b456ba
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 565013e091449c0a17c33413b7c2c7be15bb660ec644cda55db34df9310cdb7a3b94a3639b256df1745390b1cebc976d121eae3efe39bfe85954f75ef6a4af55
|
7
|
+
data.tar.gz: d7b727d66c11e8cf171e2eb6ba0f5175740b8be186ef0e463782e0a619951ccffca6f83fa4a50576d6ebf406629b77a840f74a5ad57b1344ea20fdce8eb3ddd9
|
@@ -0,0 +1,440 @@
|
|
1
|
+
# How to utilize CanCan Permissions to work with this controller:
|
2
|
+
module CanCanCan
|
3
|
+
module AbstractResourceController
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
before_action :initialize_resource_class
|
8
|
+
end
|
9
|
+
|
10
|
+
# Used to stop infinite recursive on associations (could just be deeply nested structures. Could also be self-referencing).
|
11
|
+
MAX_ASSOCIATIVE_NESTED_DEPTH = 60
|
12
|
+
REGEX_FOR_HTML_TAG_DETECTION = /.*\<\/?[^_\W]+\>.*/
|
13
|
+
|
14
|
+
# to handle adding/removing associations by "_ids" suffix
|
15
|
+
IDS_ATTIB_PERMISSION_KEY_GEN = Proc.new { |assoc_key| "#{assoc_key.to_s.singularize}_ids".to_sym }
|
16
|
+
IDS_ACTION_PERMISSION_KEY_GEN = Proc.new { |assoc_key| "_can_add_or_remove_association_#{assoc_key.to_s}".to_sym }
|
17
|
+
|
18
|
+
# to handle updating nested attributes
|
19
|
+
NESTED_ATTIB_PERMISSION_KEY_GEN = Proc.new { |assoc_key| "#{assoc_key.to_s}_attributes".to_sym }
|
20
|
+
NESTED_ACTION_PERMISSION_KEY_GEN = Proc.new { |assoc_key| "_can_update_association_#{assoc_key.to_s}".to_sym }
|
21
|
+
|
22
|
+
# For Read-Only fields
|
23
|
+
# - define this on your class model
|
24
|
+
# optional allowlist for incoming parameters for the implemented resource
|
25
|
+
# - nil means allowlist is inactive, acceptable parameters are determined by cancan attrib permissions
|
26
|
+
# - [] (empty array) means that no parameters will be accepted for resource
|
27
|
+
# - [<param1>, <param2>, ...] is self-explanatory, only those listed will be accepted
|
28
|
+
# class Resource
|
29
|
+
# RESOURCE_CONTROLLER_ATTRIB_ALLOWLIST = nil
|
30
|
+
# end
|
31
|
+
|
32
|
+
# probably a better way to do this. If there is, it's poorly documented.
|
33
|
+
# - src: https://www.w3schools.com/TAGS/default.ASP
|
34
|
+
# DEFAULT_PARAMETER_SANITIZER_ALLOWED_TAGS - Add to this env var any values to also allow for HTML tags (i.e.: label,span,text_area)
|
35
|
+
# DEFAULT_PARAMETER_SANITIZER_ALLOWED_ATTRIBS - Add to this env var any values to also allow for HTML attribs (i.e.: ng-show,ng-hide,data-id)
|
36
|
+
DEFAULT_PARAMETER_SANITIZER_ALLOWED_TAGS = (
|
37
|
+
%w[
|
38
|
+
p
|
39
|
+
div
|
40
|
+
span
|
41
|
+
body
|
42
|
+
b
|
43
|
+
strong
|
44
|
+
br
|
45
|
+
center
|
46
|
+
font
|
47
|
+
label
|
48
|
+
pre
|
49
|
+
tr
|
50
|
+
td
|
51
|
+
table
|
52
|
+
text_area
|
53
|
+
ul
|
54
|
+
li
|
55
|
+
footer
|
56
|
+
em
|
57
|
+
ol
|
58
|
+
i
|
59
|
+
select
|
60
|
+
option
|
61
|
+
] + (ENV['DEFAULT_PARAMETER_SANITIZER_ALLOWED_TAGS']&.split(',')&.collect(&:strip) || [])
|
62
|
+
).freeze
|
63
|
+
# Only allow attribs that are allowed in HTML friendly text blocks
|
64
|
+
# - i.e. NO HREFs!
|
65
|
+
DEFAULT_PARAMETER_SANITIZER_ALLOWED_ATTRIBS = (
|
66
|
+
%w[
|
67
|
+
style
|
68
|
+
id
|
69
|
+
class
|
70
|
+
type
|
71
|
+
value
|
72
|
+
] + (ENV['DEFAULT_PARAMETER_SANITIZER_ALLOWED_ATTRIBS']&.split(',')&.collect(&:strip) || [])
|
73
|
+
).freeze
|
74
|
+
|
75
|
+
def index
|
76
|
+
authorize! :index, @resource_class
|
77
|
+
@resources ||= @resource_class
|
78
|
+
|
79
|
+
begin
|
80
|
+
@resources = @resources.accessible_by(current_ability)
|
81
|
+
rescue CanCan::Error => e
|
82
|
+
# The accessible_by call cannot be used with a block 'can' definition
|
83
|
+
# Need to switch over to SQL permissions, not using the blocks
|
84
|
+
Rails.logger.error "Error: resource class, #{@resource_class.name}, is using CanCan block definitions, not SQL permissions. Unable to run index permission filter"
|
85
|
+
raise e
|
86
|
+
end
|
87
|
+
|
88
|
+
@resources = index_resource_query(@resources)
|
89
|
+
|
90
|
+
respond_with_resources
|
91
|
+
end
|
92
|
+
|
93
|
+
def show
|
94
|
+
authorize! :show, @resource_class
|
95
|
+
# Allow @resource to be set from subclass controller
|
96
|
+
@resource ||= @resource_class.find(params[:id])
|
97
|
+
authorize! :show, @resource
|
98
|
+
|
99
|
+
respond_with_resource
|
100
|
+
end
|
101
|
+
|
102
|
+
def new
|
103
|
+
authorize! :create, @resource_class
|
104
|
+
@resource ||= @resource_class.new(resource_params)
|
105
|
+
# 2nd auth on the object itself
|
106
|
+
# Not authing on the nested resources, that could have come in as nested attributes.
|
107
|
+
authorize! :create, @resource
|
108
|
+
|
109
|
+
respond_with_resource
|
110
|
+
end
|
111
|
+
|
112
|
+
def edit
|
113
|
+
authorize! :update, @resource_class
|
114
|
+
@resource ||= @resource_class.find(params[:id])
|
115
|
+
authorize! :update, @resource
|
116
|
+
|
117
|
+
respond_to do |format|
|
118
|
+
format.html # Renders the default
|
119
|
+
format.json { render json: @resources }
|
120
|
+
format.xml { render xml: @resources }
|
121
|
+
format.csv # Renders the default
|
122
|
+
format.xlsx # Renders the default
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def create
|
127
|
+
authorize! :create, @resource_class
|
128
|
+
# @resource = @resource_class.new(resource_params)
|
129
|
+
|
130
|
+
# This 2nd @resource initiation is so we run run whitelisting attribs on the object.
|
131
|
+
# Class whitelisting is far more broad than object attrib whitelisting.
|
132
|
+
# Necessary if class permissions have a permissions-block.
|
133
|
+
@resource ||= @resource_class.new(resource_params(@resource))
|
134
|
+
|
135
|
+
# 2nd auth on the object itself
|
136
|
+
authorize! :create, @resource
|
137
|
+
|
138
|
+
if @resource.save
|
139
|
+
respond_with_resource
|
140
|
+
else
|
141
|
+
begin
|
142
|
+
Rails.logger.warn "Failed object validations: could not create #{@resource_class}, id: #{@resource.id}: #{@resource.errors.full_messages}"
|
143
|
+
respond_with_resource_invalid
|
144
|
+
rescue Exception => e
|
145
|
+
Rails.logger.error "CanCanCanResourceController - Caught Internal Server Error: " + e.class.to_s + ': ' + e.message
|
146
|
+
Rails.logger.error Rails.backtrace_cleaner.clean(e.backtrace).join("\n").to_s
|
147
|
+
respond_with_resource_error
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def update
|
153
|
+
authorize! :update, @resource_class
|
154
|
+
@resource ||= @resource_class.find(params[:id])
|
155
|
+
authorize! :update, @resource
|
156
|
+
|
157
|
+
second_authorize = false
|
158
|
+
ActiveRecord::Base.transaction do
|
159
|
+
@resource.assign_attributes(resource_params(@resource))
|
160
|
+
second_authorize = can?(action_name.to_sym, @resource)
|
161
|
+
unless second_authorize
|
162
|
+
# NOTE: Does not halt the controller process, just rolls back the DB
|
163
|
+
raise ActiveRecord::Rollback
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
unless second_authorize
|
168
|
+
raise CanCan::AccessDenied.new("Not authorized!", action_name.to_sym, @resource)
|
169
|
+
end
|
170
|
+
|
171
|
+
# 2nd auth, on the updates of the object, without saving, so we can rollback without auth.
|
172
|
+
# authorize! :update, @resource
|
173
|
+
if @resource.save
|
174
|
+
respond_with_resource
|
175
|
+
else
|
176
|
+
begin
|
177
|
+
Rails.logger.warn "Failed object validations: could not update #{@resource_class}, id: #{@resource.id}: #{@resource.errors.full_messages}"
|
178
|
+
respond_with_resource_error
|
179
|
+
rescue Exception => e
|
180
|
+
Rails.logger.error "CanCanCanResourceController - Caught Internal Server Error: " + e.class.to_s + ': ' + e.message
|
181
|
+
Rails.logger.error Rails.backtrace_cleaner.clean(e.backtrace).join("\n").to_s
|
182
|
+
respond_with_resource_error
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def destroy
|
188
|
+
authorize! :destroy, @resource_class
|
189
|
+
@resource ||= @resource_class.find(params[:id])
|
190
|
+
authorize! :destroy, @resource
|
191
|
+
# retuning the resource in a pre-destroyed state as a destroy response
|
192
|
+
results = @resource
|
193
|
+
if @resource.destroy
|
194
|
+
respond_after_destroy
|
195
|
+
else
|
196
|
+
begin
|
197
|
+
Rails.logger.warn "Failed object validations: could not destroy #{@resource_class}, id: #{@resource.id}: #{@resource.errors.full_messages}"
|
198
|
+
respond_with_resource_invalid
|
199
|
+
rescue Exception => e
|
200
|
+
Rails.logger.error "CanCanCanResourceController - Caught Internal Server Error: " + e.class.to_s + ': ' + e.message
|
201
|
+
Rails.logger.error Rails.backtrace_cleaner.clean(e.backtrace).join("\n").to_s
|
202
|
+
respond_with_resource_error
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
protected
|
208
|
+
|
209
|
+
def respond_with_resources
|
210
|
+
respond_to do |format|
|
211
|
+
format.html # Renders the default
|
212
|
+
format.json { render json: @resources }
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def respond_with_resource
|
217
|
+
respond_to do |format|
|
218
|
+
format.html # Renders the default
|
219
|
+
format.json { render json: @resource }
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def respond_with_resource_invalid
|
224
|
+
respond_to do |format|
|
225
|
+
format.html # Renders the default
|
226
|
+
format.json { render json: @resource.errors.full_messages, status: 422 }
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def respond_with_resource_error
|
231
|
+
respond_to do |format|
|
232
|
+
format.html # Renders the default
|
233
|
+
format.json { render json: ["An error has occured. Our support teams have been notified and are working on a solution."], status: 422 }
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def respond_after_destroy
|
238
|
+
respond_to do |format|
|
239
|
+
format.html { redirect_to url_for(controller: controller_name, action: 'index') }
|
240
|
+
format.json { render json: results, status: :no_content }
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# meant to be overridden by inheriting controllers.
|
245
|
+
def index_resource_query resource_query
|
246
|
+
return resource_query
|
247
|
+
end
|
248
|
+
|
249
|
+
# can pass in custom method to supplant 'param.permit', like if you wanted to whitelist a hash instead of params.
|
250
|
+
# ex: CanCanCanResourceController#deactivate_helper, permits on fake params: ActionController::Parameters.new(deactive_params)
|
251
|
+
def resource_params resource_object = nil, opts = {}, &block
|
252
|
+
local_action_name = opts[:custom_action_name] || action_name
|
253
|
+
allowlist_permitted = get_nested_attributes_for_class(@resource_class, local_action_name.to_sym, resource_object)
|
254
|
+
|
255
|
+
# # Rails kludge, issue with allowing parameters with empty arrays
|
256
|
+
# # Needs to be nested, recursive
|
257
|
+
# # Updating params in-place
|
258
|
+
# params.each do |key, value|
|
259
|
+
# if key.to_s =~ /(.*)_ids/ && (value == "remove" || value == ["remove"])
|
260
|
+
# params[key] = []
|
261
|
+
# end
|
262
|
+
# end
|
263
|
+
|
264
|
+
if block_given?
|
265
|
+
params_with_only_allowed_parameters = yield(allowlist_permitted)
|
266
|
+
else
|
267
|
+
params_with_only_allowed_parameters = param_permit(allowlist_permitted)
|
268
|
+
end
|
269
|
+
|
270
|
+
# sanitize all input.
|
271
|
+
sanitized_params_with_only_allowed_parameters = clean_parameter_data(params_with_only_allowed_parameters)
|
272
|
+
|
273
|
+
# recast type (and have to re-permit)
|
274
|
+
sanitized_params_with_only_allowed_parameters = ActionController::Parameters.new(sanitized_params_with_only_allowed_parameters).permit(allowlist_permitted)
|
275
|
+
|
276
|
+
return sanitized_params_with_only_allowed_parameters
|
277
|
+
end
|
278
|
+
|
279
|
+
# recursive
|
280
|
+
# src: https://apidock.com/rails/v5.2.3/ActionView/Helpers/SanitizeHelper/sanitize
|
281
|
+
def clean_parameter_data param_value
|
282
|
+
# was an array element, and not an object.
|
283
|
+
# Check for HTML tags
|
284
|
+
if param_value.is_a?(String) && !(param_value =~ REGEX_FOR_HTML_TAG_DETECTION).nil?
|
285
|
+
# We need a better way, in the future, to specify the allowed values down to the Class and Column level.
|
286
|
+
return ActionController::Base.helpers.sanitize(param_value, {tags: self.class::DEFAULT_PARAMETER_SANITIZER_ALLOWED_TAGS, attributes: self.class::DEFAULT_PARAMETER_SANITIZER_ALLOWED_ATTRIBS})
|
287
|
+
elsif param_value.is_a?(String) || param_value.is_a?(Integer) || param_value.is_a?(Float) || param_value.nil? || [true, false].include?(param_value)
|
288
|
+
return param_value
|
289
|
+
end
|
290
|
+
|
291
|
+
if param_value.is_a?(Hash) || param_value.is_a?(Array) || param_value.is_a?(ActionController::Parameters)
|
292
|
+
# good to continue
|
293
|
+
else
|
294
|
+
error_msg = "Internal Server Error! Unsupported parameter type: #{param_value} (#{param_value.class})"
|
295
|
+
Rails.logger.error(error_msg)
|
296
|
+
raise error_msg
|
297
|
+
end
|
298
|
+
|
299
|
+
if param_value.is_a?(Array)
|
300
|
+
new_array = []
|
301
|
+
param_value.each do |array_element|
|
302
|
+
new_array << clean_parameter_data(array_element)
|
303
|
+
end
|
304
|
+
return new_array
|
305
|
+
else
|
306
|
+
new_hash = {}
|
307
|
+
keys = param_value.keys
|
308
|
+
keys.each do |key|
|
309
|
+
new_hash[key.to_sym] = clean_parameter_data(param_value[key])
|
310
|
+
end
|
311
|
+
return new_hash
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
# Not checking instances of classes. What if they are object-state dependent?
|
316
|
+
# Need to run them again, after object instantiation, but in a different method.
|
317
|
+
def get_nested_attributes_for_class resource_class, action_name, root_level_object, depth = 0
|
318
|
+
raise "invalid action class: #{action_name.class}" if !action_name.is_a?(Symbol)
|
319
|
+
association_parameters = []
|
320
|
+
if depth > MAX_ASSOCIATIVE_NESTED_DEPTH
|
321
|
+
return association_parameters
|
322
|
+
end
|
323
|
+
|
324
|
+
# Handle resource_class attribs
|
325
|
+
# issue here is the 'action_name' on the root 'resource_class' may not be the action that the user has for the 'assoc_class'
|
326
|
+
# i.e:
|
327
|
+
# We may want the user to update Account, and create attachments on it, but not 'update' attachments.
|
328
|
+
if depth == 0
|
329
|
+
association_parameters = current_ability.permitted_attributes(action_name, (root_level_object || resource_class))
|
330
|
+
else
|
331
|
+
association_parameters = current_ability.permitted_attributes(action_name, resource_class)
|
332
|
+
end
|
333
|
+
|
334
|
+
if resource_class.const_defined?('RESOURCE_CONTROLLER_ATTRIB_ALLOWLIST') && !resource_class::RESOURCE_CONTROLLER_ATTRIB_ALLOWLIST.nil?
|
335
|
+
association_parameters &= resource_class::RESOURCE_CONTROLLER_ATTRIB_ALLOWLIST
|
336
|
+
end
|
337
|
+
|
338
|
+
# remove customized, non-params, assoc' attrib data by only allowing class columns
|
339
|
+
association_parameters &= resource_class.column_names.collect(&:to_sym)
|
340
|
+
|
341
|
+
resource_class.reflect_on_all_associations(:has_many).each do |assoc_class|
|
342
|
+
resource_key = assoc_class.name
|
343
|
+
# attrib_permission_key = (resource_key.to_s.singularize + '_ids').to_sym
|
344
|
+
attrib_permission_key = IDS_ATTIB_PERMISSION_KEY_GEN.call(resource_key)
|
345
|
+
# action_permission_key = ('_can_add_or_remove_association_' + resource_key.to_s).to_sym
|
346
|
+
action_permission_key = IDS_ACTION_PERMISSION_KEY_GEN.call(resource_key)
|
347
|
+
# i.e. can?(:can_participation_ids, Account)
|
348
|
+
# Check to see if we manually gave the user a custom permission
|
349
|
+
# # (i.e.: can [:update, :can_account_sector_ids], Account)
|
350
|
+
# OR
|
351
|
+
# see if it has the attribute on the class's allowed params
|
352
|
+
if can?(action_permission_key, resource_class) || can?(action_name, resource_class, attrib_permission_key)
|
353
|
+
association_parameters << {
|
354
|
+
attrib_permission_key => []
|
355
|
+
}
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
resource_class.nested_attributes_options.each do |resource_key, options|
|
360
|
+
reflection_class = resource_class.reflect_on_association(resource_key).class
|
361
|
+
reflection_type = reflection_class.name
|
362
|
+
assoc_class = resource_class.reflect_on_association(resource_key).klass
|
363
|
+
|
364
|
+
if [
|
365
|
+
"ActiveRecord::Reflection::BelongsToReflection",
|
366
|
+
"ActiveRecord::Reflection::HasOneReflection",
|
367
|
+
"ActiveRecord::Reflection::HasManyReflection"
|
368
|
+
].include?(reflection_type)
|
369
|
+
parameter_key = NESTED_ATTIB_PERMISSION_KEY_GEN.call(resource_key)
|
370
|
+
permission_key = NESTED_ACTION_PERMISSION_KEY_GEN.call(resource_key)
|
371
|
+
|
372
|
+
# Can check if permission to update assoc is defined as an action OR as an attrib on the parent resource_class
|
373
|
+
if can?(permission_key, resource_class) || can?(action_name, resource_class, parameter_key)
|
374
|
+
# Handle recursion
|
375
|
+
assoc_parameters = get_nested_attributes_for_class(assoc_class, action_name, root_level_object, depth + 1)
|
376
|
+
|
377
|
+
if options[:allow_destroy] && can?(:destroy, resource_class)
|
378
|
+
assoc_parameters << :_destroy
|
379
|
+
end
|
380
|
+
|
381
|
+
association_parameters << {
|
382
|
+
parameter_key => assoc_parameters
|
383
|
+
}
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
return association_parameters
|
389
|
+
end
|
390
|
+
|
391
|
+
def param_permit base_parameters
|
392
|
+
params.permit(base_parameters)
|
393
|
+
end
|
394
|
+
|
395
|
+
def initialize_resource_class
|
396
|
+
# First priority is the namespaced model, e.g. User::Group
|
397
|
+
@resource_class ||= begin
|
398
|
+
namespaced_class = self.class.name.sub(/Controller$/, '').singularize
|
399
|
+
namespaced_class.constantize
|
400
|
+
rescue NameError
|
401
|
+
nil
|
402
|
+
end
|
403
|
+
|
404
|
+
# Second priority is the top namespace model, e.g. EngineName::Article for EngineName::Admin::ArticlesController
|
405
|
+
@resource_class ||= begin
|
406
|
+
namespaced_classes = self.class.name.sub(/Controller$/, '').split('::')
|
407
|
+
namespaced_class = [namespaced_classes.first, namespaced_classes.last].join('::').singularize
|
408
|
+
namespaced_class.constantize
|
409
|
+
rescue NameError
|
410
|
+
nil
|
411
|
+
end
|
412
|
+
|
413
|
+
# Third priority the camelcased c, i.e. UserGroup
|
414
|
+
@resource_class ||= begin
|
415
|
+
camelcased_class = self.class.name.sub(/Controller$/, '').gsub('::', '').singularize
|
416
|
+
camelcased_class.constantize
|
417
|
+
rescue NameError
|
418
|
+
nil
|
419
|
+
end
|
420
|
+
|
421
|
+
# Otherwise use the Group class, or fail
|
422
|
+
@resource_class ||= begin
|
423
|
+
class_name = self.controller_name.classify
|
424
|
+
class_name.constantize
|
425
|
+
rescue NameError => e
|
426
|
+
raise unless e.message.include?(class_name)
|
427
|
+
nil
|
428
|
+
end
|
429
|
+
# portal/portal_imports case needed this
|
430
|
+
@resource_class ||= begin
|
431
|
+
class_name = controller_path.classify
|
432
|
+
class_name.camelize.singularize.constantize
|
433
|
+
rescue NameError => e
|
434
|
+
raise unless e.message.include?(class_name)
|
435
|
+
nil
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
end
|
440
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cancancan_resource_controller
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- benjamin.dana.software.dev@gmail.com
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-07-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cancancan
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.5.0
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.5.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.5.0
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.5.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rails
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - '='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 6.1.7.3
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - '='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 6.1.7.3
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '3.9'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3.9'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: listen
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.2'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '3.2'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: rspec-rails
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '4.0'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '4.0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: database_cleaner
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '1.8'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '1.8'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: sqlite3
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '1.4'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '1.4'
|
117
|
+
description:
|
118
|
+
email:
|
119
|
+
executables: []
|
120
|
+
extensions: []
|
121
|
+
extra_rdoc_files: []
|
122
|
+
files:
|
123
|
+
- lib/cancancan/abstract_resource_controller.rb
|
124
|
+
- lib/cancancan_resource_controller.rb
|
125
|
+
homepage: https://github.com/danabr75/cancancan_resource_controller
|
126
|
+
licenses:
|
127
|
+
- LGPL-3.0-only
|
128
|
+
metadata: {}
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '2.4'
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
requirements: []
|
144
|
+
rubygems_version: 3.3.7
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: A Rails Controller Module that uses CanCan's permitted attribs instead of
|
148
|
+
typical parameter allowlisting.
|
149
|
+
test_files: []
|