haveapi 0.20.0 → 0.21.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Rakefile +6 -6
- data/haveapi.gemspec +13 -13
- data/lib/haveapi/action.rb +153 -167
- data/lib/haveapi/action_state.rb +2 -6
- data/lib/haveapi/actions/default.rb +8 -10
- data/lib/haveapi/api.rb +2 -1
- data/lib/haveapi/authentication/base.rb +5 -8
- data/lib/haveapi/authentication/basic/provider.rb +4 -5
- data/lib/haveapi/authentication/chain.rb +19 -17
- data/lib/haveapi/authentication/oauth2/config.rb +12 -32
- data/lib/haveapi/authentication/oauth2/provider.rb +20 -30
- data/lib/haveapi/authentication/oauth2/revoke_endpoint.rb +1 -2
- data/lib/haveapi/authentication/token/action_config.rb +5 -3
- data/lib/haveapi/authentication/token/config.rb +5 -5
- data/lib/haveapi/authentication/token/provider.rb +33 -37
- data/lib/haveapi/authorization.rb +10 -4
- data/lib/haveapi/client_example.rb +11 -14
- data/lib/haveapi/client_examples/curl.rb +37 -37
- data/lib/haveapi/client_examples/fs_client.rb +29 -31
- data/lib/haveapi/client_examples/http.rb +35 -36
- data/lib/haveapi/client_examples/js_client.rb +62 -63
- data/lib/haveapi/client_examples/php_client.rb +77 -76
- data/lib/haveapi/client_examples/ruby_cli.rb +30 -30
- data/lib/haveapi/client_examples/ruby_client.rb +26 -26
- data/lib/haveapi/common.rb +3 -4
- data/lib/haveapi/context.rb +11 -10
- data/lib/haveapi/example.rb +9 -4
- data/lib/haveapi/example_list.rb +2 -2
- data/lib/haveapi/exceptions.rb +1 -1
- data/lib/haveapi/extensions/action_exceptions.rb +2 -2
- data/lib/haveapi/extensions/base.rb +1 -3
- data/lib/haveapi/extensions/exception_mailer.rb +260 -257
- data/lib/haveapi/hooks.rb +40 -39
- data/lib/haveapi/metadata.rb +1 -1
- data/lib/haveapi/model_adapter.rb +16 -27
- data/lib/haveapi/model_adapters/active_record.rb +59 -69
- data/lib/haveapi/output_formatter.rb +7 -7
- data/lib/haveapi/output_formatters/base.rb +2 -4
- data/lib/haveapi/parameters/resource.rb +7 -7
- data/lib/haveapi/parameters/typed.rb +6 -9
- data/lib/haveapi/params.rb +38 -45
- data/lib/haveapi/resource.rb +8 -8
- data/lib/haveapi/resources/action_state.rb +11 -19
- data/lib/haveapi/server.rb +102 -107
- data/lib/haveapi/spec/api_response.rb +1 -1
- data/lib/haveapi/spec/helpers.rb +1 -1
- data/lib/haveapi/spec/mock_action.rb +11 -10
- data/lib/haveapi/spec/spec_methods.rb +9 -8
- data/lib/haveapi/tasks/yard.rb +2 -2
- data/lib/haveapi/types.rb +0 -3
- data/lib/haveapi/validator.rb +6 -3
- data/lib/haveapi/validator_chain.rb +9 -8
- data/lib/haveapi/validators/acceptance.rb +6 -6
- data/lib/haveapi/validators/confirmation.rb +2 -3
- data/lib/haveapi/validators/exclusion.rb +1 -1
- data/lib/haveapi/validators/format.rb +1 -1
- data/lib/haveapi/validators/inclusion.rb +1 -1
- data/lib/haveapi/validators/length.rb +12 -11
- data/lib/haveapi/validators/numericality.rb +14 -13
- data/lib/haveapi/validators/presence.rb +4 -3
- data/lib/haveapi/version.rb +2 -2
- data/lib/haveapi.rb +2 -3
- data/spec/.rubocop.yml +4 -0
- data/spec/action/dsl_spec.rb +18 -18
- data/spec/authorization_spec.rb +8 -8
- data/spec/common_spec.rb +2 -1
- data/spec/documentation_spec.rb +2 -9
- data/spec/envelope_spec.rb +2 -2
- data/spec/hooks_spec.rb +12 -12
- data/spec/parameters/typed_spec.rb +6 -6
- data/spec/params_spec.rb +22 -24
- data/spec/resource_spec.rb +5 -7
- data/spec/spec_helper.rb +0 -1
- data/spec/validators/acceptance_spec.rb +1 -1
- data/spec/validators/confirmation_spec.rb +5 -5
- data/spec/validators/exclusion_spec.rb +3 -3
- data/spec/validators/format_spec.rb +2 -2
- data/spec/validators/inclusion_spec.rb +4 -4
- data/spec/validators/length_spec.rb +23 -23
- data/spec/validators/numericality_spec.rb +13 -13
- data/spec/validators/presence_spec.rb +3 -3
- metadata +49 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e72ad9fd9ee5a7d0ada6b5985e28f51d6fe65423b290aae824f6ff55a067145
|
4
|
+
data.tar.gz: c6c35096b29c02199c3dd4ae46d2ee8ec6920e2f5d5436596e4cde1a133c80cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 722c8af5849aef6fe6dbbf48d53bb159c66a9dcd4decafcc4ba20a5f6fee441dbe0eb2d08a2f91283dd900869e1e36632281fcabc038a0ad8ed83dbc9255e053
|
7
|
+
data.tar.gz: b26b675cb2ce63c3d7f2723f3084bb7e7289d4ee896dfbdcf875ed841adedc9feb991b3ee76715586fc79d8b21657e537c446e2284aab24dd94361dfbbd78383
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -16,16 +16,16 @@ begin
|
|
16
16
|
YARD::Rake::YardocTask.new do |t|
|
17
17
|
t.files = ['lib/**/*.rb']
|
18
18
|
t.options = [
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
'--protected',
|
20
|
+
'--output-dir=html_doc',
|
21
|
+
'--files=doc/*.md',
|
22
|
+
'--files=doc/*.html'
|
23
23
|
]
|
24
|
-
t.before =
|
24
|
+
t.before = proc do
|
25
25
|
document_hooks.call
|
26
26
|
render_doc_file('doc/json-schema.erb', 'doc/JSON-Schema.html').call
|
27
27
|
end
|
28
28
|
end
|
29
|
-
|
30
29
|
rescue LoadError
|
30
|
+
# ignore
|
31
31
|
end
|
data/haveapi.gemspec
CHANGED
@@ -1,30 +1,30 @@
|
|
1
|
-
lib = File.expand_path('
|
2
|
-
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$:.unshift(lib) unless $:.include?(lib)
|
3
3
|
require 'haveapi/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'haveapi'
|
7
7
|
s.version = HaveAPI::VERSION
|
8
8
|
s.summary =
|
9
|
-
|
9
|
+
s.description = 'Framework for creating self-describing APIs'
|
10
10
|
s.authors = 'Jakub Skokan'
|
11
11
|
s.email = 'jakub.skokan@vpsfree.cz'
|
12
12
|
s.files = `git ls-files -z`.split("\x0") + Dir.glob('doc/*')
|
13
13
|
s.license = 'MIT'
|
14
14
|
|
15
|
-
s.required_ruby_version =
|
15
|
+
s.required_ruby_version = ">= #{File.read('../../.ruby-version').strip}"
|
16
16
|
|
17
|
-
s.add_runtime_dependency 'require_all', '~> 2.0.0'
|
18
|
-
s.add_runtime_dependency 'json'
|
19
17
|
s.add_runtime_dependency 'activesupport', '>= 7.1'
|
20
|
-
s.add_runtime_dependency 'sinatra', '~> 3.1.0'
|
21
|
-
s.add_runtime_dependency 'sinatra-contrib', '~> 3.1.0'
|
22
|
-
s.add_runtime_dependency 'tilt', '~> 2.3.0'
|
23
|
-
s.add_runtime_dependency 'redcarpet', '~> 3.6'
|
24
|
-
s.add_runtime_dependency 'rake'
|
25
18
|
s.add_runtime_dependency 'github-markdown'
|
26
|
-
s.add_runtime_dependency '
|
27
|
-
s.add_runtime_dependency '
|
19
|
+
s.add_runtime_dependency 'haveapi-client', '~> 0.21.1'
|
20
|
+
s.add_runtime_dependency 'json'
|
28
21
|
s.add_runtime_dependency 'mail'
|
22
|
+
s.add_runtime_dependency 'nesty', '~> 1.0'
|
29
23
|
s.add_runtime_dependency 'rack-oauth2', '~> 2.2.0'
|
24
|
+
s.add_runtime_dependency 'rake'
|
25
|
+
s.add_runtime_dependency 'redcarpet', '~> 3.6'
|
26
|
+
s.add_runtime_dependency 'require_all', '~> 2.0.0'
|
27
|
+
s.add_runtime_dependency 'sinatra', '~> 3.1.0'
|
28
|
+
s.add_runtime_dependency 'sinatra-contrib', '~> 3.1.0'
|
29
|
+
s.add_runtime_dependency 'tilt', '~> 2.3.0'
|
30
30
|
end
|
data/lib/haveapi/action.rb
CHANGED
@@ -17,29 +17,26 @@ module HaveAPI
|
|
17
17
|
include Hookable
|
18
18
|
|
19
19
|
has_hook :pre_authorize,
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
ret: {
|
28
|
-
blocks: 'array of authorization blocks',
|
29
|
-
}
|
20
|
+
desc: "Called to provide additional authorization blocks. These blocks are called before action's own authorization block. Note that if any of the blocks uses allow/deny rule, it will be the final authorization decision and even action's own authorization block will not be called.",
|
21
|
+
args: {
|
22
|
+
context: 'HaveAPI::Context instance'
|
23
|
+
},
|
24
|
+
ret: {
|
25
|
+
blocks: 'array of authorization blocks'
|
26
|
+
}
|
30
27
|
|
31
28
|
has_hook :exec_exception,
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
attr_reader :message, :errors, :version
|
29
|
+
desc: 'Called when unhandled exceptions occurs during Action.exec',
|
30
|
+
args: {
|
31
|
+
context: 'HaveAPI::Context instance',
|
32
|
+
exception: 'exception instance'
|
33
|
+
},
|
34
|
+
ret: {
|
35
|
+
status: 'true or false, indicating whether error should be reported',
|
36
|
+
message: 'error message sent to the user'
|
37
|
+
}
|
38
|
+
|
39
|
+
attr_reader :message, :errors, :version, :current_user, :request
|
43
40
|
attr_accessor :flags
|
44
41
|
|
45
42
|
class << self
|
@@ -48,13 +45,13 @@ module HaveAPI
|
|
48
45
|
|
49
46
|
def inherited(subclass)
|
50
47
|
# puts "Action.inherited called #{subclass} from #{to_s}"
|
51
|
-
|
48
|
+
super
|
52
49
|
subclass.instance_variable_set(:@obj_type, obj_type)
|
53
50
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
51
|
+
return unless subclass.name
|
52
|
+
|
53
|
+
# not an anonymouse class
|
54
|
+
delayed_inherited(subclass)
|
58
55
|
end
|
59
56
|
|
60
57
|
def delayed_inherited(subclass)
|
@@ -71,9 +68,10 @@ module HaveAPI
|
|
71
68
|
|
72
69
|
m = {}
|
73
70
|
|
74
|
-
@meta.each do |k,v|
|
71
|
+
@meta.each do |k, v|
|
75
72
|
m[k] = v && v.clone
|
76
73
|
next unless v
|
74
|
+
|
77
75
|
m[k].action = subclass
|
78
76
|
end
|
79
77
|
|
@@ -86,11 +84,11 @@ module HaveAPI
|
|
86
84
|
subclass.instance_variable_set(:@model, resource.model)
|
87
85
|
resource.action_defined(subclass)
|
88
86
|
rescue NoMethodError
|
89
|
-
|
87
|
+
nil
|
90
88
|
end
|
91
89
|
end
|
92
90
|
|
93
|
-
def initialize
|
91
|
+
def initialize # rubocop:disable Lint/MissingSuper
|
94
92
|
return if @initialized
|
95
93
|
|
96
94
|
check_build("#{self}.input") do
|
@@ -109,9 +107,9 @@ module HaveAPI
|
|
109
107
|
meta(:global) do
|
110
108
|
output do
|
111
109
|
integer :action_state_id,
|
112
|
-
|
113
|
-
|
114
|
-
|
110
|
+
label: 'Action state ID',
|
111
|
+
desc: 'ID of ActionState object for state querying. When null, the action ' \
|
112
|
+
'is not blocking for the current invocation.'
|
115
113
|
end
|
116
114
|
end
|
117
115
|
end
|
@@ -171,7 +169,7 @@ module HaveAPI
|
|
171
169
|
|
172
170
|
def meta(type = :object, &block)
|
173
171
|
if block
|
174
|
-
@meta ||= {object: nil, global: nil}
|
172
|
+
@meta ||= { object: nil, global: nil }
|
175
173
|
@meta[type] ||= Metadata::ActionMetadata.new
|
176
174
|
@meta[type].action = self
|
177
175
|
@meta[type].instance_exec(&block)
|
@@ -180,14 +178,14 @@ module HaveAPI
|
|
180
178
|
end
|
181
179
|
end
|
182
180
|
|
183
|
-
def authorize(&
|
184
|
-
@authorization = Authorization.new(&
|
181
|
+
def authorize(&)
|
182
|
+
@authorization = Authorization.new(&)
|
185
183
|
end
|
186
184
|
|
187
|
-
def example(title = '', &
|
185
|
+
def example(title = '', &)
|
188
186
|
@examples ||= ExampleList.new
|
189
187
|
e = Example.new(title)
|
190
|
-
e.instance_eval(&
|
188
|
+
e.instance_eval(&)
|
191
189
|
@examples << e
|
192
190
|
end
|
193
191
|
|
@@ -195,29 +193,28 @@ module HaveAPI
|
|
195
193
|
(@action_name ? @action_name.to_s : to_s).demodulize
|
196
194
|
end
|
197
195
|
|
198
|
-
|
199
|
-
@action_name = name
|
200
|
-
end
|
196
|
+
attr_writer :action_name
|
201
197
|
|
202
198
|
def build_route(prefix)
|
203
199
|
route = @route || action_name.underscore
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
200
|
+
if @route
|
201
|
+
@route
|
202
|
+
elsif action_name
|
203
|
+
action_name.to_s.demodulize.underscore
|
204
|
+
else
|
205
|
+
to_s.demodulize.underscore
|
206
|
+
end
|
211
207
|
|
212
208
|
if !route.is_a?(String) && route.respond_to?(:call)
|
213
|
-
route = route.call(
|
209
|
+
route = route.call(resource)
|
214
210
|
end
|
215
211
|
|
216
|
-
prefix + route
|
212
|
+
prefix + format(route, resource: resource.resource_name.underscore)
|
217
213
|
end
|
218
214
|
|
219
215
|
def describe(context)
|
220
216
|
authorization = (@authorization && @authorization.clone) || Authorization.new
|
217
|
+
add_pre_authorize_blocks(authorization, context)
|
221
218
|
|
222
219
|
if (context.endpoint || context.current_user) \
|
223
220
|
&& !authorization.authorized?(context.current_user, context.path_params_from_args)
|
@@ -242,14 +239,14 @@ module HaveAPI
|
|
242
239
|
description: @desc,
|
243
240
|
aliases: @aliases,
|
244
241
|
blocking: @blocking ? true : false,
|
245
|
-
input: @input ? @input.describe(context) : {parameters: {}},
|
246
|
-
output: @output ? @output.describe(context) : {parameters: {}},
|
242
|
+
input: @input ? @input.describe(context) : { parameters: {} },
|
243
|
+
output: @output ? @output.describe(context) : { parameters: {} },
|
247
244
|
meta: @meta ? @meta.merge(@meta) { |_, v| v && v.describe(context) } : nil,
|
248
245
|
examples: @examples ? @examples.describe(context) : [],
|
249
246
|
scope: context.action_scope,
|
250
247
|
path: context.resolved_path,
|
251
248
|
method: route_method,
|
252
|
-
help: "#{context.path}?method=#{route_method}"
|
249
|
+
help: "#{context.path}?method=#{route_method}"
|
253
250
|
}
|
254
251
|
end
|
255
252
|
|
@@ -257,7 +254,6 @@ module HaveAPI
|
|
257
254
|
def inherit_attrs_from_resource(action, r, attrs)
|
258
255
|
begin
|
259
256
|
return unless r.obj_type == :resource
|
260
|
-
|
261
257
|
rescue NoMethodError
|
262
258
|
return
|
263
259
|
end
|
@@ -279,16 +275,29 @@ module HaveAPI
|
|
279
275
|
end
|
280
276
|
|
281
277
|
def resolve_path_params(object)
|
282
|
-
if
|
283
|
-
|
278
|
+
if resolve
|
279
|
+
resolve.call(object)
|
284
280
|
|
285
281
|
else
|
286
282
|
object.respond_to?(:id) ? object.id : nil
|
287
283
|
end
|
288
284
|
end
|
285
|
+
|
286
|
+
def add_pre_authorize_blocks(authorization, context)
|
287
|
+
ret = Action.call_hooks(
|
288
|
+
:pre_authorize,
|
289
|
+
args: [context],
|
290
|
+
initial: { blocks: [] }
|
291
|
+
)
|
292
|
+
|
293
|
+
ret[:blocks].reverse_each do |block|
|
294
|
+
authorization.prepend_block(block)
|
295
|
+
end
|
296
|
+
end
|
289
297
|
end
|
290
298
|
|
291
299
|
def initialize(request, version, params, body, context)
|
300
|
+
super()
|
292
301
|
@request = request
|
293
302
|
@version = version
|
294
303
|
@params = params
|
@@ -297,35 +306,24 @@ module HaveAPI
|
|
297
306
|
@context.action = self.class
|
298
307
|
@context.action_instance = self
|
299
308
|
@metadata = {}
|
300
|
-
@reply_meta = {object: {}, global: {}}
|
309
|
+
@reply_meta = { object: {}, global: {} }
|
301
310
|
@flags = {}
|
302
311
|
|
303
312
|
class_auth = self.class.authorization
|
304
313
|
|
305
|
-
if class_auth
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
ret = call_class_hooks_as_for(
|
312
|
-
Action,
|
313
|
-
:pre_authorize,
|
314
|
-
args: [@context],
|
315
|
-
initial: {blocks: []},
|
316
|
-
)
|
314
|
+
@authorization = if class_auth
|
315
|
+
class_auth.clone
|
316
|
+
else
|
317
|
+
Authorization.new {}
|
318
|
+
end
|
317
319
|
|
318
|
-
|
319
|
-
@authorization.prepend_block(block)
|
320
|
-
end
|
320
|
+
self.class.add_pre_authorize_blocks(@authorization, @context)
|
321
321
|
end
|
322
322
|
|
323
323
|
def validate!
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
error(e.message, e.to_hash)
|
328
|
-
end
|
324
|
+
@params = validate
|
325
|
+
rescue ValidationError => e
|
326
|
+
error(e.message, e.to_hash)
|
329
327
|
end
|
330
328
|
|
331
329
|
def authorized?(user)
|
@@ -333,20 +331,12 @@ module HaveAPI
|
|
333
331
|
@authorization.authorized?(user, extract_path_params)
|
334
332
|
end
|
335
333
|
|
336
|
-
def current_user
|
337
|
-
@current_user
|
338
|
-
end
|
339
|
-
|
340
334
|
def params
|
341
335
|
@safe_params
|
342
336
|
end
|
343
337
|
|
344
338
|
def input
|
345
|
-
@safe_params[
|
346
|
-
end
|
347
|
-
|
348
|
-
def request
|
349
|
-
@request
|
339
|
+
@safe_params[self.class.input.namespace] if self.class.input
|
350
340
|
end
|
351
341
|
|
352
342
|
def meta
|
@@ -364,13 +354,9 @@ module HaveAPI
|
|
364
354
|
# --
|
365
355
|
# FIXME: is this correct behaviour?
|
366
356
|
# ++
|
367
|
-
def prepare
|
357
|
+
def prepare; end
|
368
358
|
|
369
|
-
end
|
370
|
-
|
371
|
-
def pre_exec
|
372
|
-
|
373
|
-
end
|
359
|
+
def pre_exec; end
|
374
360
|
|
375
361
|
# This method must be reimplemented in every action.
|
376
362
|
# It must not be invoked directly, only via safe_exec, which restricts output.
|
@@ -383,29 +369,27 @@ module HaveAPI
|
|
383
369
|
# Return array +[status, data|error, errors]+
|
384
370
|
def safe_exec
|
385
371
|
exec_ret = catch(:return) do
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
tmp = call_class_hooks_as_for(Action, :exec_exception, args: [@context, e])
|
393
|
-
|
394
|
-
if tmp.empty?
|
395
|
-
p e.message
|
396
|
-
puts e.backtrace
|
397
|
-
error('Server error occurred')
|
398
|
-
end
|
372
|
+
validate!
|
373
|
+
prepare
|
374
|
+
pre_exec
|
375
|
+
exec
|
376
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
377
|
+
tmp = call_class_hooks_as_for(Action, :exec_exception, args: [@context, e])
|
399
378
|
|
400
|
-
|
401
|
-
|
402
|
-
|
379
|
+
if tmp.empty?
|
380
|
+
p e.message
|
381
|
+
puts e.backtrace
|
382
|
+
error('Server error occurred')
|
383
|
+
end
|
384
|
+
|
385
|
+
unless tmp[:status]
|
386
|
+
error(tmp[:message], {}, http_status: tmp[:http_status] || 500)
|
403
387
|
end
|
404
388
|
end
|
405
389
|
|
406
390
|
begin
|
407
391
|
output_ret = safe_output(exec_ret)
|
408
|
-
rescue Exception => e
|
392
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
409
393
|
tmp = call_class_hooks_as_for(Action, :exec_exception, args: [@context, e])
|
410
394
|
|
411
395
|
p e.message
|
@@ -415,7 +399,7 @@ module HaveAPI
|
|
415
399
|
tmp[:status] || false,
|
416
400
|
tmp[:message] || 'Server error occurred',
|
417
401
|
{},
|
418
|
-
tmp[:http_status] || 500
|
402
|
+
tmp[:http_status] || 500
|
419
403
|
]
|
420
404
|
end
|
421
405
|
|
@@ -436,55 +420,55 @@ module HaveAPI
|
|
436
420
|
out_params = self.class.output.params
|
437
421
|
|
438
422
|
case output.layout
|
439
|
-
|
440
|
-
|
441
|
-
|
423
|
+
when :object
|
424
|
+
out = adapter.output(@context, ret)
|
425
|
+
safe_ret = @authorization.filter_output(
|
426
|
+
out_params,
|
427
|
+
out,
|
428
|
+
true
|
429
|
+
)
|
430
|
+
@reply_meta[:global].update(out.meta)
|
431
|
+
|
432
|
+
when :object_list
|
433
|
+
safe_ret = []
|
434
|
+
|
435
|
+
ret.each do |obj|
|
436
|
+
out = adapter.output(@context, obj)
|
437
|
+
|
438
|
+
safe_ret << @authorization.filter_output(
|
442
439
|
out_params,
|
443
440
|
out,
|
444
441
|
true
|
445
442
|
)
|
446
|
-
|
447
|
-
|
448
|
-
when :object_list
|
449
|
-
safe_ret = []
|
450
|
-
|
451
|
-
ret.each do |obj|
|
452
|
-
out = adapter.output(@context, obj)
|
443
|
+
safe_ret.last.update({ Metadata.namespace => out.meta }) unless meta[:no]
|
444
|
+
end
|
453
445
|
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
end
|
446
|
+
when :hash
|
447
|
+
safe_ret = @authorization.filter_output(
|
448
|
+
out_params,
|
449
|
+
adapter.output(@context, ret),
|
450
|
+
true
|
451
|
+
)
|
461
452
|
|
462
|
-
|
463
|
-
|
453
|
+
when :hash_list
|
454
|
+
safe_ret = ret
|
455
|
+
safe_ret.map! do |hash|
|
456
|
+
@authorization.filter_output(
|
464
457
|
out_params,
|
465
|
-
adapter.output(@context,
|
458
|
+
adapter.output(@context, hash),
|
466
459
|
true
|
467
460
|
)
|
461
|
+
end
|
468
462
|
|
469
|
-
|
470
|
-
|
471
|
-
safe_ret.map! do |hash|
|
472
|
-
@authorization.filter_output(
|
473
|
-
out_params,
|
474
|
-
adapter.output(@context, hash),
|
475
|
-
true
|
476
|
-
)
|
477
|
-
end
|
478
|
-
|
479
|
-
else
|
480
|
-
safe_ret = ret
|
463
|
+
else
|
464
|
+
safe_ret = ret
|
481
465
|
end
|
482
466
|
|
483
467
|
if self.class.blocking
|
484
468
|
@reply_meta[:global][:action_state_id] = state_id
|
485
469
|
end
|
486
470
|
|
487
|
-
ns = {output.namespace => safe_ret}
|
471
|
+
ns = { output.namespace => safe_ret }
|
488
472
|
ns[Metadata.namespace] = @reply_meta[:global] unless meta[:no]
|
489
473
|
|
490
474
|
[true, ns]
|
@@ -507,6 +491,7 @@ module HaveAPI
|
|
507
491
|
end
|
508
492
|
|
509
493
|
protected
|
494
|
+
|
510
495
|
def with_restricted(**kwargs)
|
511
496
|
if kwargs.empty?
|
512
497
|
@authorization.restrictions
|
@@ -517,7 +502,7 @@ module HaveAPI
|
|
517
502
|
|
518
503
|
# Convert parameter names to corresponding DB names.
|
519
504
|
# By default, input parameters are used for the translation.
|
520
|
-
def to_db_names(hash, src
|
505
|
+
def to_db_names(hash, src = :input)
|
521
506
|
return {} unless hash
|
522
507
|
|
523
508
|
params = self.class.method(src).call.params
|
@@ -528,11 +513,11 @@ module HaveAPI
|
|
528
513
|
hit = false
|
529
514
|
|
530
515
|
params.each do |p|
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
516
|
+
next unless k == p.name
|
517
|
+
|
518
|
+
ret[p.db_name] = v
|
519
|
+
hit = true
|
520
|
+
break
|
536
521
|
end
|
537
522
|
|
538
523
|
ret[k] = v unless hit
|
@@ -543,7 +528,7 @@ module HaveAPI
|
|
543
528
|
|
544
529
|
# Convert DB names to corresponding parameter names.
|
545
530
|
# By default, output parameters are used for the translation.
|
546
|
-
def to_param_names(hash, src
|
531
|
+
def to_param_names(hash, src = :output)
|
547
532
|
return {} unless hash
|
548
533
|
|
549
534
|
params = self.class.method(src).call.params
|
@@ -554,11 +539,11 @@ module HaveAPI
|
|
554
539
|
hit = false
|
555
540
|
|
556
541
|
params.each do |p|
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
542
|
+
next unless k == p.db_name
|
543
|
+
|
544
|
+
ret[p.name] = v
|
545
|
+
hit = true
|
546
|
+
break
|
562
547
|
end
|
563
548
|
|
564
549
|
ret[k] = v unless hit
|
@@ -587,6 +572,7 @@ module HaveAPI
|
|
587
572
|
end
|
588
573
|
|
589
574
|
private
|
575
|
+
|
590
576
|
def validate
|
591
577
|
# Validate standard input
|
592
578
|
@safe_params = @params.dup
|
@@ -598,19 +584,19 @@ module HaveAPI
|
|
598
584
|
|
599
585
|
# Then filter allowed params
|
600
586
|
case input.layout
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
self.class.input.params,
|
605
|
-
self.class.model_adapter(self.class.input.layout).input(obj)
|
606
|
-
)
|
607
|
-
end
|
608
|
-
|
609
|
-
else
|
610
|
-
@safe_params[input.namespace] = @authorization.filter_input(
|
587
|
+
when :object_list, :hash_list
|
588
|
+
@safe_params[input.namespace].map! do |obj|
|
589
|
+
@authorization.filter_input(
|
611
590
|
self.class.input.params,
|
612
|
-
self.class.model_adapter(self.class.input.layout).input(
|
591
|
+
self.class.model_adapter(self.class.input.layout).input(obj)
|
613
592
|
)
|
593
|
+
end
|
594
|
+
|
595
|
+
else
|
596
|
+
@safe_params[input.namespace] = @authorization.filter_input(
|
597
|
+
self.class.input.params,
|
598
|
+
self.class.model_adapter(self.class.input.layout).input(@safe_params[input.namespace])
|
599
|
+
)
|
614
600
|
end
|
615
601
|
|
616
602
|
# Now check required params, convert types and set defaults
|
@@ -621,9 +607,9 @@ module HaveAPI
|
|
621
607
|
auth = Authorization.new { allow }
|
622
608
|
@metadata = {}
|
623
609
|
|
624
|
-
return if input && %i
|
610
|
+
return if input && %i[object_list hash_list].include?(input.layout)
|
625
611
|
|
626
|
-
[
|
612
|
+
%i[object global].each do |v|
|
627
613
|
meta = self.class.meta(v)
|
628
614
|
next unless meta
|
629
615
|
|
data/lib/haveapi/action_state.rb
CHANGED
@@ -65,14 +65,10 @@ module HaveAPI
|
|
65
65
|
end
|
66
66
|
|
67
67
|
# @return [Time]
|
68
|
-
def created_at
|
69
|
-
|
70
|
-
end
|
68
|
+
def created_at; end
|
71
69
|
|
72
70
|
# @return [Time]
|
73
|
-
def updated_at
|
74
|
-
|
75
|
-
end
|
71
|
+
def updated_at; end
|
76
72
|
|
77
73
|
# @return [Boolean] true if the action can be cancelled
|
78
74
|
def can_cancel?
|