haveapi 0.20.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
data/lib/haveapi/params.rb
CHANGED
@@ -1,18 +1,13 @@
|
|
1
1
|
module HaveAPI
|
2
2
|
module Parameters
|
3
|
-
|
4
3
|
end
|
5
4
|
|
6
|
-
class ValidationError <
|
5
|
+
class ValidationError < StandardError
|
7
6
|
def initialize(msg, errors = {})
|
8
|
-
|
7
|
+
super(msg)
|
9
8
|
@errors = errors
|
10
9
|
end
|
11
10
|
|
12
|
-
def message
|
13
|
-
@msg
|
14
|
-
end
|
15
|
-
|
16
11
|
def to_hash
|
17
12
|
@errors
|
18
13
|
end
|
@@ -57,7 +52,7 @@ module HaveAPI
|
|
57
52
|
def layout
|
58
53
|
return @cache[:layout] if @cache[:layout]
|
59
54
|
|
60
|
-
@cache[:layout] = @layout
|
55
|
+
@cache[:layout] = @layout || :object
|
61
56
|
end
|
62
57
|
|
63
58
|
def layout=(l)
|
@@ -69,7 +64,7 @@ module HaveAPI
|
|
69
64
|
return @cache[:namespace] = @namespace unless @namespace.nil?
|
70
65
|
|
71
66
|
n = @action.resource.resource_name.underscore
|
72
|
-
n = n.pluralize if %i
|
67
|
+
n = n.pluralize if %i[object_list hash_list].include?(layout)
|
73
68
|
@cache[:namespace] = n.to_sym
|
74
69
|
end
|
75
70
|
|
@@ -106,8 +101,8 @@ module HaveAPI
|
|
106
101
|
add_param(name, apply(kwargs, type: Integer))
|
107
102
|
end
|
108
103
|
|
109
|
-
|
110
|
-
|
104
|
+
alias id integer
|
105
|
+
alias foreign_key integer
|
111
106
|
|
112
107
|
def float(name, **kwargs)
|
113
108
|
add_param(name, apply(kwargs, type: Float))
|
@@ -127,33 +122,33 @@ module HaveAPI
|
|
127
122
|
|
128
123
|
block = @action.resource.params(name)
|
129
124
|
|
130
|
-
|
131
|
-
@include_back << @include.clone if @include
|
132
|
-
@exclude_back << @exclude.clone if @exclude
|
125
|
+
return unless block
|
133
126
|
|
134
|
-
|
135
|
-
|
136
|
-
@include.concat(include)
|
137
|
-
end
|
127
|
+
@include_back << @include.clone if @include
|
128
|
+
@exclude_back << @exclude.clone if @exclude
|
138
129
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
instance_eval(&block)
|
130
|
+
if include
|
131
|
+
@include ||= []
|
132
|
+
@include.concat(include)
|
133
|
+
end
|
145
134
|
|
146
|
-
|
147
|
-
@exclude
|
135
|
+
if exclude
|
136
|
+
@exclude ||= []
|
137
|
+
@exclude.concat(exclude)
|
148
138
|
end
|
139
|
+
|
140
|
+
instance_eval(&block)
|
141
|
+
|
142
|
+
@include = @include_back.pop if @include
|
143
|
+
@exclude = @exclude_back.pop if @exclude
|
149
144
|
end
|
150
145
|
|
151
146
|
def resource(name, **kwargs)
|
152
147
|
add_resource(name, kwargs)
|
153
148
|
end
|
154
149
|
|
155
|
-
|
156
|
-
|
150
|
+
alias references resource
|
151
|
+
alias belongs_to resource
|
157
152
|
|
158
153
|
def patch(name, **changes)
|
159
154
|
@params.detect { |p| p.name == name }.patch(changes)
|
@@ -167,7 +162,7 @@ module HaveAPI
|
|
167
162
|
def describe(context)
|
168
163
|
context.layout = layout
|
169
164
|
|
170
|
-
ret = {parameters: {}}
|
165
|
+
ret = { parameters: {} }
|
171
166
|
ret[:layout] = layout
|
172
167
|
ret[:namespace] = namespace
|
173
168
|
ret[:format] = @structure if @structure
|
@@ -176,17 +171,17 @@ module HaveAPI
|
|
176
171
|
ret[:parameters][p.name] = p.describe(context)
|
177
172
|
end
|
178
173
|
|
179
|
-
if @direction == :input
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
174
|
+
ret[:parameters] = if @direction == :input
|
175
|
+
context.authorization.filter_input(
|
176
|
+
@params,
|
177
|
+
ModelAdapters::Hash.output(context, ret[:parameters])
|
178
|
+
)
|
179
|
+
else
|
180
|
+
context.authorization.filter_output(
|
181
|
+
@params,
|
182
|
+
ModelAdapters::Hash.output(context, ret[:parameters])
|
183
|
+
)
|
184
|
+
end
|
190
185
|
|
191
186
|
ret
|
192
187
|
end
|
@@ -235,7 +230,6 @@ module HaveAPI
|
|
235
230
|
|
236
231
|
begin
|
237
232
|
cleaned = p.clean(input[p.name])
|
238
|
-
|
239
233
|
rescue ValidationError => e
|
240
234
|
errors[p.name] ||= []
|
241
235
|
errors[p.name] << e.message
|
@@ -271,6 +265,7 @@ module HaveAPI
|
|
271
265
|
end
|
272
266
|
|
273
267
|
private
|
268
|
+
|
274
269
|
def add_param(name, kwargs)
|
275
270
|
p = Parameters::Typed.new(name, kwargs)
|
276
271
|
|
@@ -311,7 +306,7 @@ module HaveAPI
|
|
311
306
|
end
|
312
307
|
end
|
313
308
|
|
314
|
-
def layout_aware(params)
|
309
|
+
def layout_aware(params, &)
|
315
310
|
ns = namespace
|
316
311
|
|
317
312
|
case layout
|
@@ -319,9 +314,7 @@ module HaveAPI
|
|
319
314
|
yield(ns ? params[namespace] : params)
|
320
315
|
|
321
316
|
when :object_list, :hash_list
|
322
|
-
(ns ? params[namespace] : params).each
|
323
|
-
yield(object)
|
324
|
-
end
|
317
|
+
(ns ? params[namespace] : params).each(&)
|
325
318
|
|
326
319
|
else
|
327
320
|
false
|
data/lib/haveapi/resource.rb
CHANGED
@@ -11,6 +11,7 @@ module HaveAPI
|
|
11
11
|
has_attr :singular, false
|
12
12
|
|
13
13
|
def self.inherited(subclass)
|
14
|
+
super
|
14
15
|
subclass.instance_variable_set(:@obj_type, obj_type)
|
15
16
|
end
|
16
17
|
|
@@ -28,8 +29,8 @@ module HaveAPI
|
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
31
|
-
def self.actions(&
|
32
|
-
(@actions || []).each(&
|
32
|
+
def self.actions(&)
|
33
|
+
(@actions || []).each(&)
|
33
34
|
end
|
34
35
|
|
35
36
|
def self.resources
|
@@ -40,7 +41,6 @@ module HaveAPI
|
|
40
41
|
if obj.obj_type == :resource
|
41
42
|
yield obj
|
42
43
|
end
|
43
|
-
|
44
44
|
rescue NoMethodError
|
45
45
|
next
|
46
46
|
end
|
@@ -51,15 +51,15 @@ module HaveAPI
|
|
51
51
|
(@resource_name ? @resource_name.to_s : to_s).demodulize
|
52
52
|
end
|
53
53
|
|
54
|
-
|
55
|
-
|
54
|
+
class << self
|
55
|
+
attr_writer :resource_name
|
56
56
|
end
|
57
57
|
|
58
58
|
def self.rest_name
|
59
59
|
singular ? resource_name.singularize.underscore : resource_name.tableize
|
60
60
|
end
|
61
61
|
|
62
|
-
def self.routes(prefix='/', resource_path: [])
|
62
|
+
def self.routes(prefix = '/', resource_path: [])
|
63
63
|
ret = []
|
64
64
|
prefix = "#{prefix}#{@route || rest_name}/"
|
65
65
|
new_resource_path = resource_path + [resource_name.underscore]
|
@@ -73,14 +73,14 @@ module HaveAPI
|
|
73
73
|
end
|
74
74
|
|
75
75
|
resources do |r|
|
76
|
-
ret << {r => r.routes(prefix, resource_path: new_resource_path)}
|
76
|
+
ret << { r => r.routes(prefix, resource_path: new_resource_path) }
|
77
77
|
end
|
78
78
|
|
79
79
|
ret
|
80
80
|
end
|
81
81
|
|
82
82
|
def self.describe(hash, context)
|
83
|
-
ret = {description:
|
83
|
+
ret = { description: desc, actions: {}, resources: {} }
|
84
84
|
|
85
85
|
context.resource = self
|
86
86
|
|
@@ -11,16 +11,16 @@ module HaveAPI::Resources
|
|
11
11
|
string :label, label: 'Label'
|
12
12
|
bool :finished, label: 'Finished'
|
13
13
|
bool :status, label: 'Status',
|
14
|
-
|
14
|
+
desc: 'Determines whether the action is proceeding or failing'
|
15
15
|
integer :current, label: 'Current progress'
|
16
16
|
integer :total, label: 'Total',
|
17
|
-
|
17
|
+
desc: 'The action is finished when current equals to total'
|
18
18
|
string :unit, label: 'Unit', desc: 'Unit of current and total'
|
19
19
|
bool :can_cancel, label: 'Can cancel',
|
20
|
-
|
20
|
+
desc: 'When true, execution of this action can be cancelled'
|
21
21
|
datetime :created_at, label: 'Created at'
|
22
22
|
datetime :updated_at, label: 'Updated at',
|
23
|
-
|
23
|
+
desc: 'When was the progress last updated'
|
24
24
|
end
|
25
25
|
|
26
26
|
module Mixin
|
@@ -31,15 +31,10 @@ module HaveAPI::Resources
|
|
31
31
|
status: state.status,
|
32
32
|
created_at: state.created_at,
|
33
33
|
updated_at: state.updated_at,
|
34
|
-
can_cancel: state.can_cancel
|
34
|
+
can_cancel: state.can_cancel?
|
35
35
|
}
|
36
36
|
|
37
|
-
|
38
|
-
hash[:finished] = true
|
39
|
-
|
40
|
-
else
|
41
|
-
hash[:finished] = false
|
42
|
-
end
|
37
|
+
hash[:finished] = state.finished?
|
43
38
|
|
44
39
|
progress = state.progress
|
45
40
|
hash[:current] = progress[:current] || 0
|
@@ -56,7 +51,7 @@ module HaveAPI::Resources
|
|
56
51
|
desc 'List states of pending actions'
|
57
52
|
|
58
53
|
input(:hash) do
|
59
|
-
string :order, choices: %w
|
54
|
+
string :order, choices: %w[newest oldest], default: 'newest', fill: true
|
60
55
|
end
|
61
56
|
|
62
57
|
output(:hash_list) do
|
@@ -92,8 +87,8 @@ module HaveAPI::Resources
|
|
92
87
|
input(:hash) do
|
93
88
|
float :timeout, label: 'Timeout', desc: 'in seconds', default: 15, fill: true
|
94
89
|
float :update_in, label: 'Progress',
|
95
|
-
|
96
|
-
|
90
|
+
desc: 'number of seconds after which the state is returned if the progress ' \
|
91
|
+
'has changed'
|
97
92
|
bool :status, desc: 'status to check with if update_in is set'
|
98
93
|
integer :current, desc: 'progress to check with if update_in is set'
|
99
94
|
integer :total, desc: 'progress to check with if update_in is set'
|
@@ -122,7 +117,7 @@ module HaveAPI::Resources
|
|
122
117
|
elsif input[:update_in]
|
123
118
|
new_state = state_to_hash(state)
|
124
119
|
|
125
|
-
%i
|
120
|
+
%i[status current total].each do |v|
|
126
121
|
return new_state if input[v] != new_state[v]
|
127
122
|
end
|
128
123
|
end
|
@@ -185,14 +180,11 @@ module HaveAPI::Resources
|
|
185
180
|
else
|
186
181
|
error('cancellation failed')
|
187
182
|
end
|
188
|
-
|
189
183
|
rescue RuntimeError, NotImplementedError => e
|
190
184
|
error(e.message)
|
191
185
|
end
|
192
186
|
|
193
|
-
|
194
|
-
@state_id
|
195
|
-
end
|
187
|
+
attr_reader :state_id
|
196
188
|
end
|
197
189
|
end
|
198
190
|
end
|