haveapi 0.19.3 → 0.21.0
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 +140 -158
- 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 +5 -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 +105 -108
- 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 +5 -6
- 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: 2b5848df30ec9ad0b4ce0539e09cbbb0f8ab46b3ddbd9ebe0c06fbafa08eb842
|
4
|
+
data.tar.gz: 30218273467496ad5d42c275794de72dfc6a73c74e94022d5230adac64bcd4f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cbf71233376763da8ef40eb176f15d0686b2417a502deb15c1a82efe3079177e31d4664cfebe6269c93abbe7e6f9446027ab1451a0232ddbc3379a0b79e7e5e
|
7
|
+
data.tar.gz: 4871a061b0c3e85dc8bf1aef0fbedc37d91057281a35fcdae49727cf7ce80d9d318236fd5d231479df927576eb58deea52a82bf9ad8a3516531aae545f4fdd7b
|
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 '
|
17
|
+
s.add_runtime_dependency 'activesupport', '>= 7.1'
|
18
|
+
s.add_runtime_dependency 'github-markdown'
|
19
|
+
s.add_runtime_dependency 'haveapi-client', '~> 0.21.0'
|
18
20
|
s.add_runtime_dependency 'json'
|
19
|
-
s.add_runtime_dependency '
|
21
|
+
s.add_runtime_dependency 'mail'
|
22
|
+
s.add_runtime_dependency 'nesty', '~> 1.0'
|
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'
|
20
27
|
s.add_runtime_dependency 'sinatra', '~> 3.1.0'
|
21
28
|
s.add_runtime_dependency 'sinatra-contrib', '~> 3.1.0'
|
22
29
|
s.add_runtime_dependency 'tilt', '~> 2.3.0'
|
23
|
-
s.add_runtime_dependency 'redcarpet', '~> 3.6'
|
24
|
-
s.add_runtime_dependency 'rake'
|
25
|
-
s.add_runtime_dependency 'github-markdown'
|
26
|
-
s.add_runtime_dependency 'nesty', '~> 1.0'
|
27
|
-
s.add_runtime_dependency 'haveapi-client', '~> 0.19.3'
|
28
|
-
s.add_runtime_dependency 'mail'
|
29
|
-
s.add_runtime_dependency 'rack-oauth2', '~> 2.2.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,25 +193,23 @@ 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)
|
@@ -242,14 +238,14 @@ module HaveAPI
|
|
242
238
|
description: @desc,
|
243
239
|
aliases: @aliases,
|
244
240
|
blocking: @blocking ? true : false,
|
245
|
-
input: @input ? @input.describe(context) : {parameters: {}},
|
246
|
-
output: @output ? @output.describe(context) : {parameters: {}},
|
241
|
+
input: @input ? @input.describe(context) : { parameters: {} },
|
242
|
+
output: @output ? @output.describe(context) : { parameters: {} },
|
247
243
|
meta: @meta ? @meta.merge(@meta) { |_, v| v && v.describe(context) } : nil,
|
248
244
|
examples: @examples ? @examples.describe(context) : [],
|
249
245
|
scope: context.action_scope,
|
250
246
|
path: context.resolved_path,
|
251
247
|
method: route_method,
|
252
|
-
help: "#{context.path}?method=#{route_method}"
|
248
|
+
help: "#{context.path}?method=#{route_method}"
|
253
249
|
}
|
254
250
|
end
|
255
251
|
|
@@ -257,7 +253,6 @@ module HaveAPI
|
|
257
253
|
def inherit_attrs_from_resource(action, r, attrs)
|
258
254
|
begin
|
259
255
|
return unless r.obj_type == :resource
|
260
|
-
|
261
256
|
rescue NoMethodError
|
262
257
|
return
|
263
258
|
end
|
@@ -279,8 +274,8 @@ module HaveAPI
|
|
279
274
|
end
|
280
275
|
|
281
276
|
def resolve_path_params(object)
|
282
|
-
if
|
283
|
-
|
277
|
+
if resolve
|
278
|
+
resolve.call(object)
|
284
279
|
|
285
280
|
else
|
286
281
|
object.respond_to?(:id) ? object.id : nil
|
@@ -289,6 +284,7 @@ module HaveAPI
|
|
289
284
|
end
|
290
285
|
|
291
286
|
def initialize(request, version, params, body, context)
|
287
|
+
super()
|
292
288
|
@request = request
|
293
289
|
@version = version
|
294
290
|
@params = params
|
@@ -297,22 +293,22 @@ module HaveAPI
|
|
297
293
|
@context.action = self.class
|
298
294
|
@context.action_instance = self
|
299
295
|
@metadata = {}
|
300
|
-
@reply_meta = {object: {}, global: {}}
|
296
|
+
@reply_meta = { object: {}, global: {} }
|
301
297
|
@flags = {}
|
302
298
|
|
303
299
|
class_auth = self.class.authorization
|
304
300
|
|
305
|
-
if class_auth
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
301
|
+
@authorization = if class_auth
|
302
|
+
class_auth.clone
|
303
|
+
else
|
304
|
+
Authorization.new {}
|
305
|
+
end
|
310
306
|
|
311
307
|
ret = call_class_hooks_as_for(
|
312
308
|
Action,
|
313
309
|
:pre_authorize,
|
314
310
|
args: [@context],
|
315
|
-
initial: {blocks: []}
|
311
|
+
initial: { blocks: [] }
|
316
312
|
)
|
317
313
|
|
318
314
|
ret[:blocks].reverse_each do |block|
|
@@ -321,11 +317,9 @@ module HaveAPI
|
|
321
317
|
end
|
322
318
|
|
323
319
|
def validate!
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
error(e.message, e.to_hash)
|
328
|
-
end
|
320
|
+
@params = validate
|
321
|
+
rescue ValidationError => e
|
322
|
+
error(e.message, e.to_hash)
|
329
323
|
end
|
330
324
|
|
331
325
|
def authorized?(user)
|
@@ -333,20 +327,12 @@ module HaveAPI
|
|
333
327
|
@authorization.authorized?(user, extract_path_params)
|
334
328
|
end
|
335
329
|
|
336
|
-
def current_user
|
337
|
-
@current_user
|
338
|
-
end
|
339
|
-
|
340
330
|
def params
|
341
331
|
@safe_params
|
342
332
|
end
|
343
333
|
|
344
334
|
def input
|
345
|
-
@safe_params[
|
346
|
-
end
|
347
|
-
|
348
|
-
def request
|
349
|
-
@request
|
335
|
+
@safe_params[self.class.input.namespace] if self.class.input
|
350
336
|
end
|
351
337
|
|
352
338
|
def meta
|
@@ -364,13 +350,9 @@ module HaveAPI
|
|
364
350
|
# --
|
365
351
|
# FIXME: is this correct behaviour?
|
366
352
|
# ++
|
367
|
-
def prepare
|
353
|
+
def prepare; end
|
368
354
|
|
369
|
-
end
|
370
|
-
|
371
|
-
def pre_exec
|
372
|
-
|
373
|
-
end
|
355
|
+
def pre_exec; end
|
374
356
|
|
375
357
|
# This method must be reimplemented in every action.
|
376
358
|
# It must not be invoked directly, only via safe_exec, which restricts output.
|
@@ -383,29 +365,27 @@ module HaveAPI
|
|
383
365
|
# Return array +[status, data|error, errors]+
|
384
366
|
def safe_exec
|
385
367
|
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
|
368
|
+
validate!
|
369
|
+
prepare
|
370
|
+
pre_exec
|
371
|
+
exec
|
372
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
373
|
+
tmp = call_class_hooks_as_for(Action, :exec_exception, args: [@context, e])
|
399
374
|
|
400
|
-
|
401
|
-
|
402
|
-
|
375
|
+
if tmp.empty?
|
376
|
+
p e.message
|
377
|
+
puts e.backtrace
|
378
|
+
error('Server error occurred')
|
379
|
+
end
|
380
|
+
|
381
|
+
unless tmp[:status]
|
382
|
+
error(tmp[:message], {}, http_status: tmp[:http_status] || 500)
|
403
383
|
end
|
404
384
|
end
|
405
385
|
|
406
386
|
begin
|
407
387
|
output_ret = safe_output(exec_ret)
|
408
|
-
rescue Exception => e
|
388
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
409
389
|
tmp = call_class_hooks_as_for(Action, :exec_exception, args: [@context, e])
|
410
390
|
|
411
391
|
p e.message
|
@@ -415,7 +395,7 @@ module HaveAPI
|
|
415
395
|
tmp[:status] || false,
|
416
396
|
tmp[:message] || 'Server error occurred',
|
417
397
|
{},
|
418
|
-
tmp[:http_status] || 500
|
398
|
+
tmp[:http_status] || 500
|
419
399
|
]
|
420
400
|
end
|
421
401
|
|
@@ -436,55 +416,55 @@ module HaveAPI
|
|
436
416
|
out_params = self.class.output.params
|
437
417
|
|
438
418
|
case output.layout
|
439
|
-
|
440
|
-
|
441
|
-
|
419
|
+
when :object
|
420
|
+
out = adapter.output(@context, ret)
|
421
|
+
safe_ret = @authorization.filter_output(
|
422
|
+
out_params,
|
423
|
+
out,
|
424
|
+
true
|
425
|
+
)
|
426
|
+
@reply_meta[:global].update(out.meta)
|
427
|
+
|
428
|
+
when :object_list
|
429
|
+
safe_ret = []
|
430
|
+
|
431
|
+
ret.each do |obj|
|
432
|
+
out = adapter.output(@context, obj)
|
433
|
+
|
434
|
+
safe_ret << @authorization.filter_output(
|
442
435
|
out_params,
|
443
436
|
out,
|
444
437
|
true
|
445
438
|
)
|
446
|
-
|
447
|
-
|
448
|
-
when :object_list
|
449
|
-
safe_ret = []
|
450
|
-
|
451
|
-
ret.each do |obj|
|
452
|
-
out = adapter.output(@context, obj)
|
439
|
+
safe_ret.last.update({ Metadata.namespace => out.meta }) unless meta[:no]
|
440
|
+
end
|
453
441
|
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
end
|
442
|
+
when :hash
|
443
|
+
safe_ret = @authorization.filter_output(
|
444
|
+
out_params,
|
445
|
+
adapter.output(@context, ret),
|
446
|
+
true
|
447
|
+
)
|
461
448
|
|
462
|
-
|
463
|
-
|
449
|
+
when :hash_list
|
450
|
+
safe_ret = ret
|
451
|
+
safe_ret.map! do |hash|
|
452
|
+
@authorization.filter_output(
|
464
453
|
out_params,
|
465
|
-
adapter.output(@context,
|
454
|
+
adapter.output(@context, hash),
|
466
455
|
true
|
467
456
|
)
|
457
|
+
end
|
468
458
|
|
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
|
459
|
+
else
|
460
|
+
safe_ret = ret
|
481
461
|
end
|
482
462
|
|
483
463
|
if self.class.blocking
|
484
464
|
@reply_meta[:global][:action_state_id] = state_id
|
485
465
|
end
|
486
466
|
|
487
|
-
ns = {output.namespace => safe_ret}
|
467
|
+
ns = { output.namespace => safe_ret }
|
488
468
|
ns[Metadata.namespace] = @reply_meta[:global] unless meta[:no]
|
489
469
|
|
490
470
|
[true, ns]
|
@@ -507,6 +487,7 @@ module HaveAPI
|
|
507
487
|
end
|
508
488
|
|
509
489
|
protected
|
490
|
+
|
510
491
|
def with_restricted(**kwargs)
|
511
492
|
if kwargs.empty?
|
512
493
|
@authorization.restrictions
|
@@ -517,7 +498,7 @@ module HaveAPI
|
|
517
498
|
|
518
499
|
# Convert parameter names to corresponding DB names.
|
519
500
|
# By default, input parameters are used for the translation.
|
520
|
-
def to_db_names(hash, src
|
501
|
+
def to_db_names(hash, src = :input)
|
521
502
|
return {} unless hash
|
522
503
|
|
523
504
|
params = self.class.method(src).call.params
|
@@ -528,11 +509,11 @@ module HaveAPI
|
|
528
509
|
hit = false
|
529
510
|
|
530
511
|
params.each do |p|
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
512
|
+
next unless k == p.name
|
513
|
+
|
514
|
+
ret[p.db_name] = v
|
515
|
+
hit = true
|
516
|
+
break
|
536
517
|
end
|
537
518
|
|
538
519
|
ret[k] = v unless hit
|
@@ -543,7 +524,7 @@ module HaveAPI
|
|
543
524
|
|
544
525
|
# Convert DB names to corresponding parameter names.
|
545
526
|
# By default, output parameters are used for the translation.
|
546
|
-
def to_param_names(hash, src
|
527
|
+
def to_param_names(hash, src = :output)
|
547
528
|
return {} unless hash
|
548
529
|
|
549
530
|
params = self.class.method(src).call.params
|
@@ -554,11 +535,11 @@ module HaveAPI
|
|
554
535
|
hit = false
|
555
536
|
|
556
537
|
params.each do |p|
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
538
|
+
next unless k == p.db_name
|
539
|
+
|
540
|
+
ret[p.name] = v
|
541
|
+
hit = true
|
542
|
+
break
|
562
543
|
end
|
563
544
|
|
564
545
|
ret[k] = v unless hit
|
@@ -587,6 +568,7 @@ module HaveAPI
|
|
587
568
|
end
|
588
569
|
|
589
570
|
private
|
571
|
+
|
590
572
|
def validate
|
591
573
|
# Validate standard input
|
592
574
|
@safe_params = @params.dup
|
@@ -598,19 +580,19 @@ module HaveAPI
|
|
598
580
|
|
599
581
|
# Then filter allowed params
|
600
582
|
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(
|
583
|
+
when :object_list, :hash_list
|
584
|
+
@safe_params[input.namespace].map! do |obj|
|
585
|
+
@authorization.filter_input(
|
611
586
|
self.class.input.params,
|
612
|
-
self.class.model_adapter(self.class.input.layout).input(
|
587
|
+
self.class.model_adapter(self.class.input.layout).input(obj)
|
613
588
|
)
|
589
|
+
end
|
590
|
+
|
591
|
+
else
|
592
|
+
@safe_params[input.namespace] = @authorization.filter_input(
|
593
|
+
self.class.input.params,
|
594
|
+
self.class.model_adapter(self.class.input.layout).input(@safe_params[input.namespace])
|
595
|
+
)
|
614
596
|
end
|
615
597
|
|
616
598
|
# Now check required params, convert types and set defaults
|
@@ -621,9 +603,9 @@ module HaveAPI
|
|
621
603
|
auth = Authorization.new { allow }
|
622
604
|
@metadata = {}
|
623
605
|
|
624
|
-
return if input && %i
|
606
|
+
return if input && %i[object_list hash_list].include?(input.layout)
|
625
607
|
|
626
|
-
[
|
608
|
+
%i[object global].each do |v|
|
627
609
|
meta = self.class.meta(v)
|
628
610
|
next unless meta
|
629
611
|
|
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?
|