haveapi 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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 +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: 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 '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.0'
|
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,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?
|