haveapi-client 0.12.1 → 0.13.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/haveapi-client.gemspec +1 -2
- data/lib/haveapi/cli/authentication/base.rb +7 -4
- data/lib/haveapi/cli/authentication/token.rb +40 -23
- data/lib/haveapi/cli/cli.rb +48 -48
- data/lib/haveapi/cli/utils.rb +28 -0
- data/lib/haveapi/client/action.rb +16 -16
- data/lib/haveapi/client/authentication/base.rb +3 -2
- data/lib/haveapi/client/authentication/token.rb +52 -15
- data/lib/haveapi/client/client.rb +2 -2
- data/lib/haveapi/client/communicator.rb +12 -7
- data/lib/haveapi/client/resource_instance.rb +5 -5
- data/lib/haveapi/client/version.rb +2 -2
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0ef69654a1ce04be90ccdc628dd976c3c6b09d91c24455cce5a1bb9df008185
|
4
|
+
data.tar.gz: fd976abf5adb0366bb573bbef70074977b61accb2d37013aec3a8a8c30e485da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51e600c0543471f31308f0d8c60fc3e36ae51f048e94a851c0889604b0c22eb97b5880f940903f19aad575a7f6bb73a2ddb9ca6d0313916ce6154f372763907f
|
7
|
+
data.tar.gz: d37e9baf1f316e2f4d5ea0e03af7b98aa6b010fbdb256cc263bd53da60d43359a5ccb6546e318947f80e883fa3a4c7ccdb75d51988c1ffcc5b689447d9a65b1f
|
data/haveapi-client.gemspec
CHANGED
@@ -6,7 +6,6 @@ require 'haveapi/client/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'haveapi-client'
|
8
8
|
spec.version = HaveAPI::Client::VERSION
|
9
|
-
spec.date = '2017-11-27'
|
10
9
|
spec.authors = ['Jakub Skokan']
|
11
10
|
spec.email = ['jakub.skokan@vpsfree.cz']
|
12
11
|
spec.summary =
|
@@ -19,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
19
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
19
|
spec.require_paths = ['lib']
|
21
20
|
|
22
|
-
spec.add_development_dependency 'bundler'
|
21
|
+
spec.add_development_dependency 'bundler'
|
23
22
|
spec.add_development_dependency 'rake'
|
24
23
|
|
25
24
|
spec.add_runtime_dependency 'activesupport', '>= 4.0'
|
@@ -12,9 +12,9 @@ module HaveAPI::CLI
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
def initialize(communicator, desc, opts = {})
|
16
|
+
@communicator = communicator
|
17
|
+
@desc = desc
|
18
18
|
opts ||= {}
|
19
19
|
|
20
20
|
opts.each do |k, v|
|
@@ -47,6 +47,9 @@ module HaveAPI::CLI
|
|
47
47
|
def save
|
48
48
|
@communicator.auth_save
|
49
49
|
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
attr_reader :communicator, :desc
|
50
53
|
end
|
51
54
|
end
|
52
|
-
end
|
55
|
+
end
|
@@ -1,16 +1,20 @@
|
|
1
1
|
require 'haveapi/cli/authentication/base'
|
2
|
+
require 'haveapi/cli/utils'
|
2
3
|
|
3
4
|
module HaveAPI::CLI::Authentication
|
4
5
|
class Token < Base
|
5
6
|
register :token
|
6
7
|
|
8
|
+
include HaveAPI::CLI::Utils
|
9
|
+
|
7
10
|
def options(opts)
|
8
|
-
|
9
|
-
@user = u
|
10
|
-
end
|
11
|
+
@credentials = {}
|
11
12
|
|
12
|
-
|
13
|
-
|
13
|
+
request_credentials.each do |name, desc|
|
14
|
+
opts.on(
|
15
|
+
param_option(name, desc),
|
16
|
+
desc[:label] || name.to_s
|
17
|
+
) { |v| @credentials[name] = v }
|
14
18
|
end
|
15
19
|
|
16
20
|
opts.on('--token TOKEN', 'Token') do |t|
|
@@ -44,31 +48,44 @@ module HaveAPI::CLI::Authentication
|
|
44
48
|
def validate
|
45
49
|
return if @token
|
46
50
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
q.echo = false
|
51
|
+
request_credentials.each do |name, desc|
|
52
|
+
if !@credentials.has_key?(name)
|
53
|
+
@credentials[name] = read_param(name, desc)
|
54
|
+
end
|
52
55
|
end
|
53
56
|
end
|
54
57
|
|
55
58
|
def authenticate
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
59
|
+
opts = {
|
60
|
+
token: @token,
|
61
|
+
lifetime: @lifetime || :renewable_auto,
|
62
|
+
interval: @interval,
|
63
|
+
valid_to: @valid_to,
|
64
|
+
via: @via,
|
65
|
+
}
|
66
|
+
|
67
|
+
opts.update(@credentials) if @credentials
|
68
|
+
|
69
|
+
@communicator.authenticate(:token, opts) do |action, params|
|
70
|
+
ret = {}
|
71
|
+
|
72
|
+
params.each do |name, desc|
|
73
|
+
ret[name] = read_param(name, desc)
|
74
|
+
end
|
75
|
+
|
76
|
+
ret
|
77
|
+
end
|
65
78
|
end
|
66
79
|
|
67
80
|
def save
|
68
|
-
super.update({
|
69
|
-
|
70
|
-
|
71
|
-
|
81
|
+
super.update({via: @via, interval: @interval})
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
def request_credentials
|
86
|
+
desc[:resources][:token][:actions][:request][:input][:parameters].reject do |name, _|
|
87
|
+
%i(lifetime interval).include?(name)
|
88
|
+
end
|
72
89
|
end
|
73
90
|
end
|
74
91
|
end
|
data/lib/haveapi/cli/cli.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
require 'pp'
|
3
|
-
require 'highline/import'
|
4
3
|
require 'yaml'
|
5
4
|
require 'time'
|
6
5
|
require 'date'
|
6
|
+
require 'haveapi/cli/utils'
|
7
7
|
|
8
8
|
module HaveAPI::CLI
|
9
9
|
class Cli
|
@@ -29,12 +29,13 @@ module HaveAPI::CLI
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
include Utils
|
33
|
+
|
32
34
|
def initialize
|
33
35
|
@config = read_config || {}
|
34
36
|
args, @opts = options
|
35
37
|
|
36
|
-
|
37
|
-
@api.identity = $0.split('/').last
|
38
|
+
connect_api unless @api
|
38
39
|
|
39
40
|
if @action
|
40
41
|
method(@action.first).call( * @action[1..-1] )
|
@@ -53,7 +54,7 @@ module HaveAPI::CLI
|
|
53
54
|
if cmd = find_command(resources, args[1])
|
54
55
|
authenticate if @auth
|
55
56
|
c = cmd.new(@opts, HaveAPI::Client::Client.new(nil, communicator: @api))
|
56
|
-
|
57
|
+
|
57
58
|
cmd_opt = OptionParser.new do |opts|
|
58
59
|
opts.banner = "\nCommand options:"
|
59
60
|
c.options(opts)
|
@@ -64,13 +65,13 @@ module HaveAPI::CLI
|
|
64
65
|
end
|
65
66
|
end
|
66
67
|
end
|
67
|
-
|
68
|
+
|
68
69
|
if @opts[:help]
|
69
70
|
show_help do
|
70
71
|
puts cmd_opt.help
|
71
72
|
end
|
72
73
|
end
|
73
|
-
|
74
|
+
|
74
75
|
if sep = ARGV.index('--')
|
75
76
|
cmd_opt.parse!(ARGV[sep+1..-1])
|
76
77
|
end
|
@@ -106,7 +107,7 @@ module HaveAPI::CLI
|
|
106
107
|
@selected_params = @opts[:output] ? @opts[:output].split(',').uniq
|
107
108
|
: nil
|
108
109
|
|
109
|
-
@input_params = parameters(action)
|
110
|
+
@input_params = parameters(action)
|
110
111
|
|
111
112
|
includes = build_includes(action) if @selected_params
|
112
113
|
@input_params[:meta] = { includes: includes } if includes
|
@@ -174,7 +175,15 @@ module HaveAPI::CLI
|
|
174
175
|
|
175
176
|
opts.on('-a', '--auth METHOD', Cli.auth_methods.keys, 'Authentication method') do |m|
|
176
177
|
options[:auth] = m
|
177
|
-
|
178
|
+
connect_api(url: options[:client], version: options[:version])
|
179
|
+
|
180
|
+
@auth = Cli.auth_methods[m].new(
|
181
|
+
@api,
|
182
|
+
@api.describe_api(options[:version])[:authentication][m],
|
183
|
+
server_config(options[:client])[:auth][m]
|
184
|
+
)
|
185
|
+
|
186
|
+
opts.separator "\nAuthentication options:"
|
178
187
|
@auth.options(opts)
|
179
188
|
end
|
180
189
|
|
@@ -217,7 +226,7 @@ module HaveAPI::CLI
|
|
217
226
|
opts.on('-r', '--rows', 'Print output in rows') do
|
218
227
|
options[:layout] = :rows
|
219
228
|
end
|
220
|
-
|
229
|
+
|
221
230
|
opts.on('-s', '--sort PARAMETER', 'Sort output by parameter') do |p|
|
222
231
|
options[:sort] = p
|
223
232
|
end
|
@@ -225,7 +234,7 @@ module HaveAPI::CLI
|
|
225
234
|
opts.on('--save', 'Save credentials to config file for later use') do
|
226
235
|
options[:save] = true
|
227
236
|
end
|
228
|
-
|
237
|
+
|
229
238
|
opts.on('--raw', 'Print raw response as is') do
|
230
239
|
options[:raw] = true
|
231
240
|
end
|
@@ -249,7 +258,7 @@ module HaveAPI::CLI
|
|
249
258
|
opts.on('--[no-]block', 'Toggle action blocking mode') do |v|
|
250
259
|
options[:block] = v
|
251
260
|
end
|
252
|
-
|
261
|
+
|
253
262
|
opts.on(
|
254
263
|
'--timeout SEC',
|
255
264
|
Float,
|
@@ -265,11 +274,11 @@ module HaveAPI::CLI
|
|
265
274
|
opts.on('--client-version', 'Show client version') do
|
266
275
|
@action = [:show_version]
|
267
276
|
end
|
268
|
-
|
277
|
+
|
269
278
|
opts.on('--protocol-version', 'Show protocol version') do
|
270
279
|
@action = [:protocol_version]
|
271
280
|
end
|
272
|
-
|
281
|
+
|
273
282
|
opts.on('--check-compatibility', 'Check compatibility with API server') do
|
274
283
|
@action = [:check_compat]
|
275
284
|
end
|
@@ -293,8 +302,15 @@ module HaveAPI::CLI
|
|
293
302
|
|
294
303
|
unless options[:auth]
|
295
304
|
cfg = server_config(options[:client])
|
305
|
+
connect_api(url: options[:client], version: options[:version]) unless @api
|
296
306
|
|
297
|
-
|
307
|
+
if m = cfg[:last_auth]
|
308
|
+
@auth = Cli.auth_methods[m].new(
|
309
|
+
@api,
|
310
|
+
@api.describe_api(options[:version])[:authentication][m],
|
311
|
+
cfg[:auth][m],
|
312
|
+
)
|
313
|
+
end
|
298
314
|
end
|
299
315
|
|
300
316
|
[args, options]
|
@@ -356,29 +372,6 @@ module HaveAPI::CLI
|
|
356
372
|
options
|
357
373
|
end
|
358
374
|
|
359
|
-
def param_option(name, p)
|
360
|
-
ret = '--'
|
361
|
-
name = name.to_s.dasherize
|
362
|
-
|
363
|
-
if p[:type] == 'Boolean'
|
364
|
-
ret += "[no-]#{name}"
|
365
|
-
|
366
|
-
else
|
367
|
-
ret += "#{name} [#{name.underscore.upcase}]"
|
368
|
-
end
|
369
|
-
|
370
|
-
ret
|
371
|
-
end
|
372
|
-
|
373
|
-
def read_param(name, p)
|
374
|
-
prompt = "#{p[:label] || name}: "
|
375
|
-
|
376
|
-
ask(prompt) do |q|
|
377
|
-
q.default = nil
|
378
|
-
q.echo = !p[:protected]
|
379
|
-
end
|
380
|
-
end
|
381
|
-
|
382
375
|
def list_versions
|
383
376
|
desc = @api.available_versions
|
384
377
|
|
@@ -521,7 +514,7 @@ module HaveAPI::CLI
|
|
521
514
|
end
|
522
515
|
|
523
516
|
cols = []
|
524
|
-
|
517
|
+
|
525
518
|
(@selected_params || action.params.keys).each do |raw_name|
|
526
519
|
col = {}
|
527
520
|
name = nil
|
@@ -536,7 +529,7 @@ module HaveAPI::CLI
|
|
536
529
|
|
537
530
|
parts.each do |part|
|
538
531
|
fail "'#{part}' not found" unless top.has_key?(part)
|
539
|
-
|
532
|
+
|
540
533
|
if top[part][:type] == 'Resource'
|
541
534
|
param = top[part]
|
542
535
|
top = @api.get_action(top[part][:resource], :show, []).params
|
@@ -556,7 +549,7 @@ module HaveAPI::CLI
|
|
556
549
|
break if top[part].nil?
|
557
550
|
top = top[part]
|
558
551
|
end
|
559
|
-
|
552
|
+
|
560
553
|
case param[:type]
|
561
554
|
when 'Resource'
|
562
555
|
"#{top[ param[:value_label].to_sym ]} (##{top[ param[:value_id].to_sym ]})"
|
@@ -570,12 +563,12 @@ module HaveAPI::CLI
|
|
570
563
|
end
|
571
564
|
|
572
565
|
col[:label] = raw_name
|
573
|
-
|
566
|
+
|
574
567
|
else # directly accessible parameter
|
575
568
|
name = raw_name.to_sym
|
576
569
|
param = action.params[name]
|
577
570
|
fail "parameter '#{name}' does not exist" if param.nil?
|
578
|
-
|
571
|
+
|
579
572
|
if param[:type] == 'Resource'
|
580
573
|
col[:display] = Proc.new do |r|
|
581
574
|
next '' unless r
|
@@ -591,9 +584,9 @@ module HaveAPI::CLI
|
|
591
584
|
name: name,
|
592
585
|
align: %w(Integer Float).include?(param[:type]) ? 'right' : 'left',
|
593
586
|
})
|
594
|
-
|
587
|
+
|
595
588
|
col[:label] ||= param[:label] && !param[:label].empty? ? param[:label] : name.upcase
|
596
|
-
|
589
|
+
|
597
590
|
cols << col
|
598
591
|
end
|
599
592
|
|
@@ -618,7 +611,6 @@ module HaveAPI::CLI
|
|
618
611
|
|
619
612
|
def authenticate(action = nil)
|
620
613
|
if @auth
|
621
|
-
@auth.communicator = @api
|
622
614
|
@auth.validate
|
623
615
|
@auth.authenticate
|
624
616
|
|
@@ -669,6 +661,14 @@ module HaveAPI::CLI
|
|
669
661
|
@config[:servers].last
|
670
662
|
end
|
671
663
|
|
664
|
+
def connect_api(url: nil, version: nil)
|
665
|
+
@api = HaveAPI::Client::Communicator.new(
|
666
|
+
url || api_url,
|
667
|
+
version || (@opts && @opts[:version])
|
668
|
+
)
|
669
|
+
@api.identity = $0.split('/').last
|
670
|
+
end
|
671
|
+
|
672
672
|
def format_errors(action, msg, errors)
|
673
673
|
warn "Action failed: #{msg}"
|
674
674
|
|
@@ -701,7 +701,7 @@ module HaveAPI::CLI
|
|
701
701
|
# node.name => node
|
702
702
|
def build_includes(action)
|
703
703
|
ret = []
|
704
|
-
|
704
|
+
|
705
705
|
@selected_params.each do |param|
|
706
706
|
next unless param.index('.')
|
707
707
|
|
@@ -710,8 +710,8 @@ module HaveAPI::CLI
|
|
710
710
|
|
711
711
|
param.split('.').map! { |v| v.to_sym }.each do |part|
|
712
712
|
next unless top.has_key?(part)
|
713
|
-
next if top[part][:type] != 'Resource'
|
714
|
-
|
713
|
+
next if top[part][:type] != 'Resource'
|
714
|
+
|
715
715
|
includes << part
|
716
716
|
top = @api.get_action(top[part][:resource], :show, []).params
|
717
717
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'highline/import'
|
2
|
+
|
3
|
+
module HaveAPI::CLI
|
4
|
+
module Utils
|
5
|
+
def param_option(name, p)
|
6
|
+
ret = '--'
|
7
|
+
name = name.to_s.dasherize
|
8
|
+
|
9
|
+
if p[:type] == 'Boolean'
|
10
|
+
ret += "[no-]#{name}"
|
11
|
+
|
12
|
+
else
|
13
|
+
ret += "#{name} [#{name.underscore.upcase}]"
|
14
|
+
end
|
15
|
+
|
16
|
+
ret
|
17
|
+
end
|
18
|
+
|
19
|
+
def read_param(name, p)
|
20
|
+
prompt = "#{p[:label] || name}: "
|
21
|
+
|
22
|
+
ask(prompt) do |q|
|
23
|
+
q.default = nil
|
24
|
+
q.echo = !p[:protected]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -14,10 +14,10 @@ module HaveAPI::Client
|
|
14
14
|
|
15
15
|
def execute(data, *_)
|
16
16
|
args = [self]
|
17
|
-
|
17
|
+
|
18
18
|
if input
|
19
19
|
params = Params.new(self, data)
|
20
|
-
|
20
|
+
|
21
21
|
unless params.valid?
|
22
22
|
raise ValidationError.new(self, params.errors)
|
23
23
|
end
|
@@ -98,8 +98,8 @@ module HaveAPI::Client
|
|
98
98
|
@spec[:meta][scope]
|
99
99
|
end
|
100
100
|
|
101
|
-
def
|
102
|
-
@spec[:
|
101
|
+
def path
|
102
|
+
@spec[:path]
|
103
103
|
end
|
104
104
|
|
105
105
|
def help
|
@@ -107,8 +107,8 @@ module HaveAPI::Client
|
|
107
107
|
end
|
108
108
|
|
109
109
|
# Url with resolved parameters.
|
110
|
-
def
|
111
|
-
@
|
110
|
+
def prepared_path
|
111
|
+
@prepared_path || @spec[:path]
|
112
112
|
end
|
113
113
|
|
114
114
|
def prepared_help
|
@@ -120,27 +120,27 @@ module HaveAPI::Client
|
|
120
120
|
end
|
121
121
|
|
122
122
|
def unresolved_args?
|
123
|
-
|
123
|
+
prepared_path =~ /:[a-zA-Z\-_]+/
|
124
124
|
end
|
125
125
|
|
126
126
|
def provide_args(*args)
|
127
127
|
apply_args(args)
|
128
128
|
end
|
129
129
|
|
130
|
-
def
|
131
|
-
@
|
130
|
+
def provide_path(path, help)
|
131
|
+
@prepared_path = path
|
132
132
|
@prepared_help = help
|
133
133
|
end
|
134
134
|
|
135
135
|
def reset
|
136
|
-
@
|
136
|
+
@prepared_path = nil
|
137
137
|
@prepared_help = nil
|
138
138
|
end
|
139
139
|
|
140
140
|
def update_description(spec)
|
141
141
|
@spec = spec
|
142
142
|
end
|
143
|
-
|
143
|
+
|
144
144
|
# Block until the action is completed or timeout occurs. If the block is given,
|
145
145
|
# it is regularly called with the action's state.
|
146
146
|
# @param interval [Float] how often should the action state be checked
|
@@ -185,7 +185,7 @@ module HaveAPI::Client
|
|
185
185
|
cancel_block = state.cancel_block
|
186
186
|
|
187
187
|
ret = cancel(client, id)
|
188
|
-
|
188
|
+
|
189
189
|
if ret.is_a?(Response)
|
190
190
|
# The cancel is not a blocking operation, return immediately
|
191
191
|
raise ActionFailed, ret unless ret.ok?
|
@@ -203,7 +203,7 @@ module HaveAPI::Client
|
|
203
203
|
&cancel_block
|
204
204
|
)
|
205
205
|
end
|
206
|
-
|
206
|
+
|
207
207
|
return ret
|
208
208
|
end
|
209
209
|
|
@@ -232,12 +232,12 @@ module HaveAPI::Client
|
|
232
232
|
|
233
233
|
private
|
234
234
|
def apply_args(args)
|
235
|
-
@
|
235
|
+
@prepared_path ||= @spec[:path].dup
|
236
236
|
@prepared_help ||= @spec[:help].dup
|
237
237
|
|
238
238
|
args.each do |arg|
|
239
|
-
@
|
240
|
-
@prepared_help.sub!(
|
239
|
+
@prepared_path.sub!(/\{[a-zA-Z\-_]+\}/, arg.to_s)
|
240
|
+
@prepared_help.sub!(/\{[a-zA-Z\-_]+\}/, arg.to_s)
|
241
241
|
end
|
242
242
|
end
|
243
243
|
end
|
@@ -29,10 +29,11 @@ module HaveAPI::Client
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
def initialize(communicator, description, opts)
|
32
|
+
def initialize(communicator, description, opts, &block)
|
33
33
|
@communicator = communicator
|
34
34
|
@desc = description
|
35
35
|
@opts = opts
|
36
|
+
@block = block
|
36
37
|
|
37
38
|
setup
|
38
39
|
end
|
@@ -48,7 +49,7 @@ module HaveAPI::Client
|
|
48
49
|
end
|
49
50
|
|
50
51
|
# Called for each request. Returns a hash of query parameters.
|
51
|
-
def
|
52
|
+
def request_query_params
|
52
53
|
{}
|
53
54
|
end
|
54
55
|
|
@@ -15,7 +15,7 @@ module HaveAPI::Client::Authentication
|
|
15
15
|
@configured = true
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def request_query_params
|
19
19
|
return {} unless @configured
|
20
20
|
check_validity
|
21
21
|
@via == :query_param ? {@desc[:query_parameter] => @token} : {}
|
@@ -65,25 +65,50 @@ module HaveAPI::Client::Authentication
|
|
65
65
|
|
66
66
|
protected
|
67
67
|
def request_token
|
68
|
+
input = {
|
69
|
+
lifetime: @opts[:lifetime],
|
70
|
+
interval: @opts[:interval] || 300,
|
71
|
+
}
|
72
|
+
request_credentials.each { |name| input[name] = @opts[name] }
|
73
|
+
|
74
|
+
cont, next_action, token = login_step(:request, input)
|
75
|
+
return if cont == :done
|
76
|
+
|
77
|
+
if @block.nil?
|
78
|
+
raise AuthenticationFailed.new('implement multi-factor authentication')
|
79
|
+
end
|
80
|
+
|
81
|
+
loop do
|
82
|
+
input = {token: token}
|
83
|
+
input.update(@block.call(next_action, auth_action_input(next_action)))
|
84
|
+
|
85
|
+
cont, next_action, token = login_step(next_action, input)
|
86
|
+
return if cont == :done
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def login_step(name, input)
|
68
91
|
a = HaveAPI::Client::Action.new(
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
92
|
+
nil,
|
93
|
+
@communicator,
|
94
|
+
name,
|
95
|
+
@desc[:resources][:token][:actions][name],
|
96
|
+
[]
|
74
97
|
)
|
75
|
-
ret = a.execute({
|
76
|
-
login: @opts[:user],
|
77
|
-
password: @opts[:password],
|
78
|
-
lifetime: @opts[:lifetime],
|
79
|
-
interval: @opts[:interval] || 300})
|
80
98
|
|
81
|
-
|
99
|
+
resp = HaveAPI::Client::Response.new(a, a.execute(input))
|
82
100
|
|
83
|
-
|
101
|
+
if resp.failed?
|
102
|
+
raise AuthenticationFailed.new(resp.message || 'invalid credentials')
|
103
|
+
end
|
84
104
|
|
85
|
-
|
86
|
-
|
105
|
+
if resp[:complete]
|
106
|
+
@token = resp[:token]
|
107
|
+
@valid_to = resp[:valid_to] && DateTime.iso8601(resp[:valid_to]).to_time
|
108
|
+
:done
|
109
|
+
else
|
110
|
+
[:continue, resp[:next_action].to_sym, resp[:token]]
|
111
|
+
end
|
87
112
|
end
|
88
113
|
|
89
114
|
def check_validity
|
@@ -95,5 +120,17 @@ module HaveAPI::Client::Authentication
|
|
95
120
|
end
|
96
121
|
end
|
97
122
|
end
|
123
|
+
|
124
|
+
def request_credentials
|
125
|
+
@desc[:resources][:token][:actions][:request][:input][:parameters].each_key.reject do |name|
|
126
|
+
%i(interval lifetime).include?(name)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def auth_action_input(name)
|
131
|
+
@desc[:resources][:token][:actions][name][:input][:parameters].reject do |k, _|
|
132
|
+
%i(token).include?(k)
|
133
|
+
end
|
134
|
+
end
|
98
135
|
end
|
99
136
|
end
|
@@ -41,10 +41,15 @@ module HaveAPI::Client
|
|
41
41
|
# Authenticate user with selected +auth_method+.
|
42
42
|
# +auth_method+ is a name of registered authentication provider.
|
43
43
|
# +options+ are specific for each authentication provider.
|
44
|
-
def authenticate(auth_method, options = {})
|
44
|
+
def authenticate(auth_method, options = {}, &block)
|
45
45
|
desc = describe_api(@version)
|
46
46
|
|
47
|
-
@auth = self.class.auth_methods[auth_method].new(
|
47
|
+
@auth = self.class.auth_methods[auth_method].new(
|
48
|
+
self,
|
49
|
+
desc[:authentication][auth_method],
|
50
|
+
options,
|
51
|
+
&block
|
52
|
+
)
|
48
53
|
@rest = @auth.resource || @rest
|
49
54
|
end
|
50
55
|
|
@@ -136,11 +141,11 @@ module HaveAPI::Client
|
|
136
141
|
|
137
142
|
end if meta
|
138
143
|
|
139
|
-
args << {params: get_params.update(@auth.
|
144
|
+
args << {params: get_params.update(@auth.request_query_params), accept: :json, user_agent: @identity}.update(@auth.request_headers)
|
140
145
|
end
|
141
146
|
|
142
147
|
begin
|
143
|
-
response = parse(@rest[action.
|
148
|
+
response = parse(@rest[action.prepared_path].method(action.http_method.downcase.to_sym).call(*args))
|
144
149
|
|
145
150
|
rescue RestClient::Forbidden
|
146
151
|
return error('Access forbidden. Bad user name or password? Not authorized?')
|
@@ -184,14 +189,14 @@ module HaveAPI::Client
|
|
184
189
|
|
185
190
|
def description_for(path, query_params={})
|
186
191
|
ret = parse(@rest[path].get_options({
|
187
|
-
params: @auth.request_payload.update(@auth.
|
192
|
+
params: @auth.request_payload.update(@auth.request_query_params).update(query_params),
|
188
193
|
user_agent: @identity
|
189
194
|
}.update(@auth.request_headers)))
|
190
|
-
|
195
|
+
|
191
196
|
@proto_version = ret[:version]
|
192
197
|
p_v = HaveAPI::Client::PROTOCOL_VERSION
|
193
198
|
return ret[:response] if ret[:version] == p_v
|
194
|
-
|
199
|
+
|
195
200
|
unless ret[:version]
|
196
201
|
raise ProtocolError,
|
197
202
|
"Incompatible protocol version: the client uses v#{p_v} "+
|
@@ -23,13 +23,13 @@ module HaveAPI::Client
|
|
23
23
|
if response
|
24
24
|
if response.is_a?(Hash)
|
25
25
|
@params = response
|
26
|
-
@prepared_args = response[:_meta][:
|
26
|
+
@prepared_args = response[:_meta][:path_params]
|
27
27
|
@meta = response[:_meta] unless @meta
|
28
28
|
|
29
29
|
else
|
30
30
|
@response = response
|
31
31
|
@params = response.response
|
32
|
-
@prepared_args = response.meta[:
|
32
|
+
@prepared_args = response.meta[:path_params]
|
33
33
|
@meta = response.meta unless @meta
|
34
34
|
end
|
35
35
|
|
@@ -81,14 +81,14 @@ module HaveAPI::Client
|
|
81
81
|
def resolve
|
82
82
|
return self if @resolved
|
83
83
|
|
84
|
-
@action.provide_args(*@meta[:
|
84
|
+
@action.provide_args(*@meta[:path_params])
|
85
85
|
@response = Response.new(@action, @action.execute({}))
|
86
86
|
@params = @response.response
|
87
87
|
|
88
88
|
setup_from_clone(@resource)
|
89
89
|
define_attributes
|
90
90
|
|
91
|
-
@prepared_args = @response.meta[:
|
91
|
+
@prepared_args = @response.meta[:path_params]
|
92
92
|
@resolved = true
|
93
93
|
self
|
94
94
|
end
|
@@ -133,7 +133,7 @@ module HaveAPI::Client
|
|
133
133
|
resolved: false,
|
134
134
|
# TODO: this will not work for nested resources, as they have
|
135
135
|
# multiple IDs
|
136
|
-
|
136
|
+
path_params: [id],
|
137
137
|
},
|
138
138
|
}
|
139
139
|
)
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haveapi-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jakub Skokan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -147,6 +147,7 @@ files:
|
|
147
147
|
- lib/haveapi/cli/commands/action_state_wait.rb
|
148
148
|
- lib/haveapi/cli/example_formatter.rb
|
149
149
|
- lib/haveapi/cli/output_formatter.rb
|
150
|
+
- lib/haveapi/cli/utils.rb
|
150
151
|
- lib/haveapi/client.rb
|
151
152
|
- lib/haveapi/client/action.rb
|
152
153
|
- lib/haveapi/client/action_state.rb
|