restful_json 3.4.2 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +656 -453
- data/Rakefile +1 -1
- data/lib/restful_json.rb +0 -4
- data/lib/restful_json/config.rb +58 -14
- data/lib/restful_json/controller.rb +132 -67
- data/lib/restful_json/default_controller.rb +9 -1
- data/lib/restful_json/version.rb +1 -1
- metadata +2 -48
- data/lib/restful_json/base_controller.rb +0 -13
- data/lib/restful_json/railtie.rb +0 -19
- data/lib/twinturbo/application_permitter.rb +0 -93
- data/lib/twinturbo/controller.rb +0 -43
data/Rakefile
CHANGED
data/lib/restful_json.rb
CHANGED
@@ -1,8 +1,4 @@
|
|
1
1
|
require 'restful_json/version'
|
2
2
|
require 'restful_json/config'
|
3
|
-
require 'twinturbo/application_permitter'
|
4
|
-
require 'twinturbo/controller'
|
5
|
-
require 'restful_json/base_controller'
|
6
3
|
require 'restful_json/controller'
|
7
4
|
require 'restful_json/default_controller'
|
8
|
-
require 'restful_json/railtie' if defined? ::Rails::Railtie
|
data/lib/restful_json/config.rb
CHANGED
@@ -9,6 +9,11 @@ module RestfulJson
|
|
9
9
|
:return_resource,
|
10
10
|
:render_enabled,
|
11
11
|
:use_permitters,
|
12
|
+
:action_to_permitter,
|
13
|
+
:allow_action_specific_params_methods,
|
14
|
+
:actions_that_authorize,
|
15
|
+
:actions_that_permit,
|
16
|
+
:actions_supporting_params_methods,
|
12
17
|
:avoid_respond_with,
|
13
18
|
:return_error_data,
|
14
19
|
:rescue_class,
|
@@ -23,37 +28,76 @@ module RestfulJson
|
|
23
28
|
end
|
24
29
|
|
25
30
|
RestfulJson.configure do
|
31
|
+
|
32
|
+
# default for :using in can_filter_by
|
26
33
|
self.can_filter_by_default_using = [:eq]
|
34
|
+
|
35
|
+
# to log debug info during request handling
|
27
36
|
self.debug = false
|
37
|
+
|
38
|
+
# delimiter for values in request parameter values
|
28
39
|
self.filter_split = ','.freeze
|
40
|
+
|
41
|
+
# equivalent to specifying respond_to :json, :html in the controller, and can be overriden in the controller. Note that by default responders gem sets respond_to :html in application_controller.rb.
|
29
42
|
self.formats = :json, :html
|
43
|
+
|
44
|
+
# default number of records to return if using the page request function
|
30
45
|
self.number_of_records_in_a_page = 15
|
46
|
+
|
47
|
+
# delimiter for ARel predicate in the request parameter name
|
31
48
|
self.predicate_prefix = '!'.freeze
|
49
|
+
|
50
|
+
# if true, will render resource and HTTP 201 for post/create or resource and HTTP 200 for put/update. ignored if render_enabled is false.
|
32
51
|
self.return_resource = false
|
52
|
+
|
53
|
+
# if false, controller actions will just set instance variable and return it instead of calling setting instance variable and then calling render/respond_with
|
33
54
|
self.render_enabled = true
|
55
|
+
|
56
|
+
# use Permitters
|
34
57
|
self.use_permitters = true
|
58
|
+
|
59
|
+
# instead of using Rails default respond_with, explicitly define render in respond_with block
|
35
60
|
self.avoid_respond_with = true
|
61
|
+
|
62
|
+
# use the permitter_class for create and update, if use_permitters = true
|
63
|
+
self.action_to_permitter = {create: nil, update: nil}
|
64
|
+
|
65
|
+
# the methods that call authorize! action_sym, @model_class
|
66
|
+
self.actions_that_authorize = [:create, :update]
|
67
|
+
|
68
|
+
# if not using permitters, will check respond_to?("(action)_(plural_or_singular_model_name)_params".to_sym) and if true will __send__(method)
|
69
|
+
self.allow_action_specific_params_methods = true
|
70
|
+
|
71
|
+
# if not using permitters, will check respond_to?("(singular_model_name)_params".to_sym) and if true will __send__(method)
|
72
|
+
self.actions_that_permit = [:create, :update]
|
73
|
+
|
74
|
+
# in error JSON, break out the exception info into fields for debugging
|
36
75
|
self.return_error_data = true
|
37
|
-
|
76
|
+
|
77
|
+
# the class that is rescued in each action method, but if nil will always reraise and not handle
|
38
78
|
self.rescue_class = StandardError
|
79
|
+
|
80
|
+
# will define order of errors handled and what status and/or i18n message key to use
|
39
81
|
self.rescue_handlers = []
|
40
|
-
|
41
|
-
#
|
82
|
+
|
83
|
+
# rescue_handlers are an ordered array of handlers to handle rescue of self.rescue_class or sub types.
|
84
|
+
# can use optional i18n_key for message, but will default to e.message if i18n_key not found.
|
85
|
+
|
86
|
+
# support 404 error for ActiveRecord::RecordNotFound if using ActiveRecord.
|
42
87
|
begin
|
43
88
|
require 'active_record/errors'
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
]
|
53
|
-
end
|
89
|
+
self.rescue_handlers << {exception_classes: [ActiveRecord::RecordNotFound], status: :not_found, i18n_key: 'api.not_found'.freeze}
|
90
|
+
rescue LoadError, NameError
|
91
|
+
end
|
92
|
+
|
93
|
+
# support 403 error for CanCan::AccessDenied if using CanCan
|
94
|
+
begin
|
95
|
+
require 'cancan/exceptions'
|
96
|
+
self.rescue_handlers << {exception_classes: [CanCan::AccessDenied], status: :forbidden, i18n_key: 'api.not_found'.freeze}
|
54
97
|
rescue LoadError, NameError
|
55
98
|
end
|
56
99
|
|
57
|
-
#
|
100
|
+
# support 500 error for everything else that is a self.rescue_class (in action)
|
58
101
|
self.rescue_handlers << {status: :internal_server_error, i18n_key: 'api.internal_server_error'.freeze}
|
102
|
+
|
59
103
|
end
|
@@ -16,8 +16,8 @@ module RestfulJson
|
|
16
16
|
module Controller
|
17
17
|
extend ::ActiveSupport::Concern
|
18
18
|
|
19
|
-
NILS = ['NULL'.freeze,'null'.freeze,'nil'.freeze]
|
20
|
-
SINGLE_VALUE_ACTIONS = [
|
19
|
+
NILS = ['NULL'.freeze, 'null'.freeze, 'nil'.freeze]
|
20
|
+
SINGLE_VALUE_ACTIONS = [:create, :update, :destroy, :show, :new, :edit]
|
21
21
|
|
22
22
|
included do
|
23
23
|
# this can be overriden in the controller via defining respond_to
|
@@ -113,7 +113,7 @@ module RestfulJson
|
|
113
113
|
# TODO: support custom actions to be automaticaly defined
|
114
114
|
args.each do |an_action|
|
115
115
|
if options[:is]
|
116
|
-
self.action_to_query[an_action.
|
116
|
+
self.action_to_query[an_action.to_sym] = options[:is]
|
117
117
|
else
|
118
118
|
raise "#{self.class.name} must supply an :is option with query_for #{an_action.inspect}"
|
119
119
|
end
|
@@ -132,7 +132,7 @@ module RestfulJson
|
|
132
132
|
self.ordered_by = (Array.wrap(self.ordered_by) + Array.wrap(args)).flatten.compact.collect {|item|item.is_a?(Hash) ? item : {item.to_sym => :asc}}
|
133
133
|
end
|
134
134
|
|
135
|
-
# Associate a non-standard ActiveModel
|
135
|
+
# Associate a non-standard ActiveModel::Serializer for one or more actions, e.g.
|
136
136
|
# serialize_action :index, with: FoosSerializer
|
137
137
|
# or
|
138
138
|
# serialize_action :index, :some_custom_action, with: FooSerializer
|
@@ -143,13 +143,27 @@ module RestfulJson
|
|
143
143
|
options = args.extract_options!
|
144
144
|
args.each do |an_action|
|
145
145
|
if options[:with]
|
146
|
-
self.action_to_serializer[an_action.
|
147
|
-
self.action_to_serializer_for[an_action.
|
146
|
+
self.action_to_serializer[an_action.to_sym] = options[:with]
|
147
|
+
self.action_to_serializer_for[an_action.to_sym] = options[:for] if options[:for]
|
148
148
|
else
|
149
149
|
raise "#{self.class.name} must supply an :with option with serialize_action #{an_action.inspect}"
|
150
150
|
end
|
151
151
|
end
|
152
152
|
end
|
153
|
+
|
154
|
+
# Use default or custom ActionController::Permitter with one or more actions, e.g.
|
155
|
+
# permit_action :create, :update # this does nothing because it uses permitter_class, e.g. FooPermitter for FoosController
|
156
|
+
# or:
|
157
|
+
# permit_action :index, :some_custom_action, with: FoosQueryPermitter
|
158
|
+
def permit_action(*args)
|
159
|
+
options = args.extract_options!
|
160
|
+
args.each do |an_action|
|
161
|
+
if options[:with]
|
162
|
+
# if key set to nil, it will use the permitter_class method during the action
|
163
|
+
self.action_to_permitter[an_action.to_sym] = options[:with]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
153
167
|
end
|
154
168
|
|
155
169
|
# In initialize we:
|
@@ -173,10 +187,12 @@ module RestfulJson
|
|
173
187
|
@model_at_plural_name_sym = "@#{@model_plural_name}".to_sym
|
174
188
|
@model_at_singular_name_sym = "@#{@model_singular_name}".to_sym
|
175
189
|
|
176
|
-
#
|
190
|
+
# default methods for strong parameters
|
191
|
+
@model_plural_name_params_sym = "#{@model_plural_name}_params".to_sym
|
177
192
|
@model_singular_name_params_sym = "#{@model_singular_name}_params".to_sym
|
178
|
-
|
179
|
-
@
|
193
|
+
|
194
|
+
@action_to_singular_action_model_params_method = {}
|
195
|
+
@action_to_plural_action_model_params_method = {}
|
180
196
|
|
181
197
|
underscored_modules_and_underscored_plural_model_name = qualified_controller_name.gsub('::','_').underscore
|
182
198
|
|
@@ -228,6 +244,62 @@ module RestfulJson
|
|
228
244
|
render_error(e, handling_data) unless @performed_render
|
229
245
|
end
|
230
246
|
|
247
|
+
# Finds model using provided info in params, prior to any permittance,
|
248
|
+
# via where()...first.
|
249
|
+
#
|
250
|
+
# Supports composite_keys.
|
251
|
+
def find_model_instance
|
252
|
+
# to_s as safety measure for vulnerabilities similar to CVE-2013-1854.
|
253
|
+
# primary_key array support for composite_primary_keys.
|
254
|
+
if @model_class.primary_key.is_a? Array
|
255
|
+
c = @model_class
|
256
|
+
c.primary_key.each {|pkey|c.where(pkey.to_sym => params[pkey].to_s)}
|
257
|
+
@value = c.first
|
258
|
+
else
|
259
|
+
@value = @model_class.where(@model_class.primary_key.to_sym => params[@model_class.primary_key].to_s).first
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# Finds model using provided info in params, prior to any permittance,
|
264
|
+
# via where()...first! with exception raise if does not exist.
|
265
|
+
#
|
266
|
+
# Supports composite_keys.
|
267
|
+
def find_model_instance!
|
268
|
+
# to_s as safety measure for vulnerabilities similar to CVE-2013-1854.
|
269
|
+
# primary_key array support for composite_primary_keys.
|
270
|
+
if @model_class.primary_key.is_a? Array
|
271
|
+
c = @model_class
|
272
|
+
c.primary_key.each {|pkey|c.where(pkey.to_sym => params[pkey].to_s)}
|
273
|
+
# raise exception if not found
|
274
|
+
@value = c.first!
|
275
|
+
else
|
276
|
+
@value = @model_class.where(@model_class.primary_key.to_sym => params[@model_class.primary_key].to_s).first! # raise exception if not found
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def allowed_params
|
281
|
+
action_sym = params[:action].to_sym
|
282
|
+
singular = single_value_response?
|
283
|
+
action_specific_params_method = singular ? (@action_to_singular_action_model_params_method[action_sym] ||= "#{action_sym}_#{@model_singular_name}_params".to_sym) : (@action_to_plural_action_model_params_method[action_sym] ||= "#{action_sym}_#{@model_plural_name}_params".to_sym)
|
284
|
+
model_name_params_method = singular ? @model_singular_name_params_sym : @model_plural_name_params_sym
|
285
|
+
|
286
|
+
if self.actions_that_authorize.include?(action_sym)
|
287
|
+
authorize! action_sym, @model_class
|
288
|
+
end
|
289
|
+
|
290
|
+
if self.actions_that_permit.include?(action_sym)
|
291
|
+
if self.use_permitters
|
292
|
+
return permitted_params_using(self.action_to_permitter[action_sym] || permitter_class)
|
293
|
+
elsif self.allow_action_specific_params_methods && respond_to?(action_specific_params_method)
|
294
|
+
return __send__(action_specific_params_method)
|
295
|
+
elsif self.actions_supporting_params_methods.include?(action_sym) && respond_to?(model_name_params_method)
|
296
|
+
return __send__(model_name_params_method)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
params
|
301
|
+
end
|
302
|
+
|
231
303
|
# Renders error using handling data options (where options are probably hash from self.rescue_handlers that was matched).
|
232
304
|
#
|
233
305
|
# If include_error_data? is true, it returns something like the following (with the appropriate HTTP status code via setting appropriate status in respond_do:
|
@@ -271,8 +343,8 @@ module RestfulJson
|
|
271
343
|
respond_with(@value) do |format|
|
272
344
|
format.json do
|
273
345
|
# define local variables in blocks, not outside of them, to be safe, even though would work in this case
|
274
|
-
custom_action_serializer = self.action_to_serializer[params[:action].
|
275
|
-
custom_action_serializer_for = self.action_to_serializer_for[params[:action].
|
346
|
+
custom_action_serializer = self.action_to_serializer[params[:action].to_sym]
|
347
|
+
custom_action_serializer_for = self.action_to_serializer_for[params[:action].to_sym]
|
276
348
|
serialization_key = single_value_response? ? (custom_action_serializer_for == :each ? :each_serializer : :serializer) : (custom_action_serializer_for == :array ? :serializer : :each_serializer)
|
277
349
|
if !@value.respond_to?(:errors) || @value.errors.empty?
|
278
350
|
render custom_action_serializer ? {json: @value, status: success_code, serialization_key => custom_action_serializer} : {json: @value, status: success_code}
|
@@ -283,10 +355,10 @@ module RestfulJson
|
|
283
355
|
end
|
284
356
|
else
|
285
357
|
# code duplicated from above because local vars don't always traverse well into block (based on wierd ruby-proc bug experienced)
|
286
|
-
custom_action_serializer = self.action_to_serializer[params[:action].
|
287
|
-
custom_action_serializer_for = self.action_to_serializer_for[params[:action].
|
358
|
+
custom_action_serializer = self.action_to_serializer[params[:action].to_sym]
|
359
|
+
custom_action_serializer_for = self.action_to_serializer_for[params[:action].to_sym]
|
288
360
|
serialization_key = single_value_response? ? (custom_action_serializer_for == :array ? :serializer : :each_serializer) : (custom_action_serializer_for == :each ? :each_serializer : :serializer)
|
289
|
-
respond_with @value, custom_action_serializer ? {(self.action_to_serializer_for[params[:action].
|
361
|
+
respond_with @value, custom_action_serializer ? {(self.action_to_serializer_for[params[:action].to_sym] == :each ? :each_serializer : :serializer) => custom_action_serializer} : {}
|
290
362
|
end
|
291
363
|
else
|
292
364
|
@value
|
@@ -294,7 +366,7 @@ module RestfulJson
|
|
294
366
|
end
|
295
367
|
|
296
368
|
def single_value_response?
|
297
|
-
SINGLE_VALUE_ACTIONS.include?(params[:action].
|
369
|
+
SINGLE_VALUE_ACTIONS.include?(params[:action].to_sym)
|
298
370
|
end
|
299
371
|
|
300
372
|
# The controller's index (list) method to list resources.
|
@@ -302,10 +374,11 @@ module RestfulJson
|
|
302
374
|
# Note: this method be alias_method'd by query_for, so it is more than just index.
|
303
375
|
def index
|
304
376
|
# could be index or another action if alias_method'd by query_for
|
305
|
-
logger.debug "#{params[:action]
|
377
|
+
logger.debug "#{params[:action]} called in #{self.class}: model=#{@model_class}, request.format=#{request.format}, request.content_type=#{request.content_type}, params=#{params.inspect}" if self.debug
|
378
|
+
p_params = allowed_params
|
306
379
|
t = @model_class.arel_table
|
307
380
|
value = @model_class.scoped # returns ActiveRecord::Relation equivalent to select with no where clause
|
308
|
-
custom_query = self.action_to_query[params[:action].
|
381
|
+
custom_query = self.action_to_query[params[:action].to_sym]
|
309
382
|
if custom_query
|
310
383
|
value = custom_query.call(t, value)
|
311
384
|
end
|
@@ -313,12 +386,12 @@ module RestfulJson
|
|
313
386
|
self.param_to_query.each do |param_name, param_query|
|
314
387
|
if params[param_name]
|
315
388
|
# to_s as safety measure for vulnerabilities similar to CVE-2013-1854
|
316
|
-
value = param_query.call(t, value,
|
389
|
+
value = param_query.call(t, value, p_params[param_name].to_s)
|
317
390
|
end
|
318
391
|
end
|
319
392
|
|
320
393
|
self.param_to_through.each do |param_name, through_array|
|
321
|
-
if
|
394
|
+
if p_params[param_name]
|
322
395
|
# build query
|
323
396
|
# e.g. SomeModel.scoped.joins({:assoc_name => {:sub_assoc => {:sub_sub_assoc => :sub_sub_sub_assoc}}).where(sub_sub_sub_assoc_model_table_name: {column_name: value})
|
324
397
|
last_model_class = @model_class
|
@@ -327,7 +400,7 @@ module RestfulJson
|
|
327
400
|
if association_or_attribute == through_array.last
|
328
401
|
# must convert param value to string before possibly using with ARel because of CVE-2013-1854, fixed in: 3.2.13 and 3.1.12
|
329
402
|
# https://groups.google.com/forum/?fromgroups=#!msg/rubyonrails-security/jgJ4cjjS8FE/BGbHRxnDRTIJ
|
330
|
-
value = value.joins(joins).where(last_model_class.table_name.to_sym => {association_or_attribute =>
|
403
|
+
value = value.joins(joins).where(last_model_class.table_name.to_sym => {association_or_attribute => p_params[param_name].to_s})
|
331
404
|
else
|
332
405
|
found_classes = last_model_class.reflections.collect {|association_name, reflection| reflection.class_name.constantize if association_name.to_sym == association_or_attribute}.compact
|
333
406
|
if found_classes.size > 0
|
@@ -350,7 +423,7 @@ module RestfulJson
|
|
350
423
|
self.param_to_attr_and_arel_predicate.keys.each do |param_name|
|
351
424
|
options = param_to_attr_and_arel_predicate[param_name][2]
|
352
425
|
# to_s as safety measure for vulnerabilities similar to CVE-2013-1854
|
353
|
-
param =
|
426
|
+
param = p_params[param_name].to_s || options[:with_default]
|
354
427
|
|
355
428
|
if param.present? && param_to_attr_and_arel_predicate[param_name]
|
356
429
|
attr_sym = param_to_attr_and_arel_predicate[param_name][0]
|
@@ -364,42 +437,42 @@ module RestfulJson
|
|
364
437
|
end
|
365
438
|
end
|
366
439
|
|
367
|
-
if
|
368
|
-
page =
|
440
|
+
if p_params[:page] && self.supported_functions.include?(:page)
|
441
|
+
page = p_params[:page].to_i
|
369
442
|
page = 1 if page < 1 # to avoid people using this as a way to get all records unpaged, as that probably isn't the intent?
|
370
443
|
#TODO: to_s is hack to avoid it becoming an Arel::SelectManager for some reason which not sure what to do with
|
371
444
|
value = value.skip((self.number_of_records_in_a_page * (page - 1)).to_s)
|
372
445
|
value = value.take((self.number_of_records_in_a_page).to_s)
|
373
446
|
end
|
374
447
|
|
375
|
-
if
|
448
|
+
if p_params[:skip] && self.supported_functions.include?(:skip)
|
376
449
|
# to_s as safety measure for vulnerabilities similar to CVE-2013-1854
|
377
|
-
value = value.skip(
|
450
|
+
value = value.skip(p_params[:skip].to_s)
|
378
451
|
end
|
379
452
|
|
380
|
-
if
|
453
|
+
if p_params[:take] && self.supported_functions.include?(:take)
|
381
454
|
# to_s as safety measure for vulnerabilities similar to CVE-2013-1854
|
382
|
-
value = value.take(
|
455
|
+
value = value.take(p_params[:take].to_s)
|
383
456
|
end
|
384
457
|
|
385
|
-
if
|
458
|
+
if p_params[:uniq] && self.supported_functions.include?(:uniq)
|
386
459
|
value = value.uniq
|
387
460
|
end
|
388
461
|
|
389
462
|
# these must happen at the end and are independent
|
390
|
-
if
|
463
|
+
if p_params[:count] && self.supported_functions.include?(:count)
|
391
464
|
value = value.count.to_i
|
392
|
-
elsif
|
465
|
+
elsif p_params[:page_count] && self.supported_functions.include?(:page_count)
|
393
466
|
count_value = value.count.to_i # this executes the query so nothing else can be done in AREL
|
394
467
|
value = (count_value / self.number_of_records_in_a_page) + (count_value % self.number_of_records_in_a_page ? 1 : 0)
|
395
468
|
else
|
469
|
+
#TODO: also declaratively specify order via order=attr1,attr2, etc. like can_filter_by w/queries, subattrs, and direction.
|
396
470
|
self.ordered_by.each do |attr_to_direction|
|
397
471
|
# this looks nasty, but makes no sense to iterate keys if only single of each
|
398
472
|
value = value.order(t[attr_to_direction.keys[0]].send(attr_to_direction.values[0]))
|
399
473
|
end
|
400
474
|
value = value.to_a
|
401
|
-
end
|
402
|
-
|
475
|
+
end
|
403
476
|
@value = value
|
404
477
|
instance_variable_set(@model_at_plural_name_sym, @value)
|
405
478
|
render_or_respond(true)
|
@@ -409,9 +482,11 @@ module RestfulJson
|
|
409
482
|
|
410
483
|
# The controller's show (get) method to return a resource.
|
411
484
|
def show
|
412
|
-
logger.debug "#{params[:action]
|
413
|
-
|
414
|
-
|
485
|
+
logger.debug "#{params[:action]} called in #{self.class}: model=#{@model_class}, request.format=#{request.format}, request.content_type=#{request.content_type}, params=#{params.inspect}" if self.debug
|
486
|
+
@value = find_model_instance!
|
487
|
+
# allowed_params used primarily for authorization. can't do this to get id param(s) because those are sent via route, not
|
488
|
+
# in wrapped params (if wrapped)
|
489
|
+
allowed_params
|
415
490
|
instance_variable_set(@model_at_singular_name_sym, @value)
|
416
491
|
render_or_respond(true, @value.nil? ? :not_found : :ok)
|
417
492
|
rescue self.rescue_class => e
|
@@ -420,7 +495,10 @@ module RestfulJson
|
|
420
495
|
|
421
496
|
# The controller's new method (e.g. used for new record in html format).
|
422
497
|
def new
|
423
|
-
logger.debug "#{params[:action]
|
498
|
+
logger.debug "#{params[:action]} called in #{self.class}: model=#{@model_class}, request.format=#{request.format}, request.content_type=#{request.content_type}, params=#{params.inspect}" if self.debug
|
499
|
+
# allowed_params used primarily for authorization. can't do this to get id param(s) because those are sent via route, not
|
500
|
+
# in wrapped params (if wrapped)
|
501
|
+
allowed_params
|
424
502
|
@value = @model_class.new
|
425
503
|
instance_variable_set(@model_at_singular_name_sym, @value)
|
426
504
|
render_or_respond(true)
|
@@ -430,9 +508,11 @@ module RestfulJson
|
|
430
508
|
|
431
509
|
# The controller's edit method (e.g. used for edit record in html format).
|
432
510
|
def edit
|
433
|
-
logger.debug "#{params[:action]
|
434
|
-
|
435
|
-
|
511
|
+
logger.debug "#{params[:action]} called in #{self.class}: model=#{@model_class}, request.format=#{request.format}, request.content_type=#{request.content_type}, params=#{params.inspect}" if self.debug
|
512
|
+
@value = find_model_instance!
|
513
|
+
# allowed_params used primarily for authorization. can't do this to get id param(s) because those are sent via route, not
|
514
|
+
# in wrapped params (if wrapped)
|
515
|
+
allowed_params
|
436
516
|
instance_variable_set(@model_at_singular_name_sym, @value)
|
437
517
|
@value
|
438
518
|
rescue self.rescue_class => e
|
@@ -441,17 +521,7 @@ module RestfulJson
|
|
441
521
|
|
442
522
|
# The controller's create (post) method to create a resource.
|
443
523
|
def create
|
444
|
-
logger.debug "#{params[:action]
|
445
|
-
if self.use_permitters
|
446
|
-
authorize! :create, @model_class
|
447
|
-
allowed_params = permitted_params
|
448
|
-
elsif respond_to? @create_model_singular_name_params_sym
|
449
|
-
allowed_params = send(@create_model_singular_name_params_sym)
|
450
|
-
elsif respond_to? @model_singular_name_params_sym
|
451
|
-
allowed_params = send(@model_singular_name_params_sym)
|
452
|
-
else
|
453
|
-
allowed_params = params
|
454
|
-
end
|
524
|
+
logger.debug "#{params[:action]} called in #{self.class}: model=#{@model_class}, request.format=#{request.format}, request.content_type=#{request.content_type}, params=#{params.inspect}" if self.debug
|
455
525
|
@value = @model_class.new(allowed_params)
|
456
526
|
@value.save
|
457
527
|
instance_variable_set(@model_at_singular_name_sym, @value)
|
@@ -462,20 +532,12 @@ module RestfulJson
|
|
462
532
|
|
463
533
|
# The controller's update (put) method to update a resource.
|
464
534
|
def update
|
465
|
-
logger.debug "#{params[:action]
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
elsif respond_to? @model_singular_name_params_sym
|
472
|
-
allowed_params = send(@model_singular_name_params_sym)
|
473
|
-
else
|
474
|
-
allowed_params = params
|
475
|
-
end
|
476
|
-
# to_s as safety measure for vulnerabilities similar to CVE-2013-1854
|
477
|
-
@value = @model_class.where(id: params[:id].to_s).first # don't raise exception
|
478
|
-
@value.update_attributes(allowed_params) unless @value.nil?
|
535
|
+
logger.debug "#{params[:action]} called in #{self.class}: model=#{@model_class}, request.format=#{request.format}, request.content_type=#{request.content_type}, params=#{params.inspect}" if self.debug
|
536
|
+
@value = find_model_instance!
|
537
|
+
# allowed_params used primarily for authorization. can't do this to get id param(s) because those are sent via route, not
|
538
|
+
# in wrapped params (if wrapped)
|
539
|
+
p_params = allowed_params
|
540
|
+
@value.update_attributes(p_params) unless @value.nil?
|
479
541
|
instance_variable_set(@model_at_singular_name_sym, @value)
|
480
542
|
render_or_respond(true, @value.nil? ? :not_found : :ok)
|
481
543
|
rescue self.rescue_class => e
|
@@ -484,9 +546,12 @@ module RestfulJson
|
|
484
546
|
|
485
547
|
# The controller's destroy (delete) method to destroy a resource.
|
486
548
|
def destroy
|
487
|
-
logger.debug "#{params[:action]
|
488
|
-
#
|
489
|
-
@value =
|
549
|
+
logger.debug "#{params[:action]} called in #{self.class}: model=#{@model_class}, request.format=#{request.format}, request.content_type=#{request.content_type}, params=#{params.inspect}" if self.debug
|
550
|
+
# don't raise error- DELETE should be idempotent per REST.
|
551
|
+
@value = find_model_instance
|
552
|
+
# allowed_params used primarily for authorization. can't do this to get id param(s) because those are sent via route, not
|
553
|
+
# in wrapped params (if wrapped)
|
554
|
+
p_params = allowed_params
|
490
555
|
@value.destroy if @value
|
491
556
|
instance_variable_set(@model_at_singular_name_sym, @value)
|
492
557
|
if !@value.respond_to?(:errors) || @value.errors.empty? || (request.format != 'text/html' && request.content_type != 'text/html')
|