aspera-cli 4.14.0 → 4.15.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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +54 -3
- data/CONTRIBUTING.md +7 -7
- data/README.md +1457 -880
- data/bin/ascli +18 -9
- data/bin/asession +12 -14
- data/examples/proxy.pac +1 -1
- data/lib/aspera/aoc.rb +198 -127
- data/lib/aspera/ascmd.rb +24 -14
- data/lib/aspera/cli/basic_auth_plugin.rb +9 -6
- data/lib/aspera/cli/error.rb +17 -0
- data/lib/aspera/cli/extended_value.rb +47 -12
- data/lib/aspera/cli/formatter.rb +260 -171
- data/lib/aspera/cli/hints.rb +80 -0
- data/lib/aspera/cli/main.rb +101 -147
- data/lib/aspera/cli/manager.rb +160 -124
- data/lib/aspera/cli/plugin.rb +70 -59
- data/lib/aspera/cli/plugins/alee.rb +0 -1
- data/lib/aspera/cli/plugins/aoc.rb +239 -273
- data/lib/aspera/cli/plugins/ats.rb +8 -5
- data/lib/aspera/cli/plugins/bss.rb +2 -2
- data/lib/aspera/cli/plugins/config.rb +516 -375
- data/lib/aspera/cli/plugins/console.rb +40 -0
- data/lib/aspera/cli/plugins/cos.rb +4 -5
- data/lib/aspera/cli/plugins/faspex.rb +99 -84
- data/lib/aspera/cli/plugins/faspex5.rb +179 -148
- data/lib/aspera/cli/plugins/node.rb +219 -153
- data/lib/aspera/cli/plugins/orchestrator.rb +52 -17
- data/lib/aspera/cli/plugins/preview.rb +46 -32
- data/lib/aspera/cli/plugins/server.rb +57 -17
- data/lib/aspera/cli/plugins/shares.rb +34 -12
- data/lib/aspera/cli/sync_actions.rb +68 -0
- data/lib/aspera/cli/transfer_agent.rb +45 -55
- data/lib/aspera/cli/transfer_progress.rb +74 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +3 -1
- data/lib/aspera/command_line_builder.rb +14 -11
- data/lib/aspera/cos_node.rb +3 -2
- data/lib/aspera/environment.rb +17 -6
- data/lib/aspera/fasp/agent_aspera.rb +126 -0
- data/lib/aspera/fasp/agent_base.rb +31 -77
- data/lib/aspera/fasp/agent_connect.rb +21 -22
- data/lib/aspera/fasp/agent_direct.rb +88 -102
- data/lib/aspera/fasp/agent_httpgw.rb +196 -192
- data/lib/aspera/fasp/agent_node.rb +41 -34
- data/lib/aspera/fasp/agent_trsdk.rb +75 -34
- data/lib/aspera/fasp/error_info.rb +2 -2
- data/lib/aspera/fasp/faux_file.rb +52 -0
- data/lib/aspera/fasp/installation.rb +43 -184
- data/lib/aspera/fasp/management.rb +244 -0
- data/lib/aspera/fasp/parameters.rb +59 -26
- data/lib/aspera/fasp/parameters.yaml +75 -8
- data/lib/aspera/fasp/products.rb +162 -0
- data/lib/aspera/fasp/transfer_spec.rb +1 -1
- data/lib/aspera/fasp/uri.rb +4 -4
- data/lib/aspera/faspex_gw.rb +2 -2
- data/lib/aspera/faspex_postproc.rb +2 -2
- data/lib/aspera/hash_ext.rb +2 -2
- data/lib/aspera/json_rpc.rb +49 -0
- data/lib/aspera/line_logger.rb +23 -0
- data/lib/aspera/log.rb +57 -16
- data/lib/aspera/node.rb +97 -14
- data/lib/aspera/oauth.rb +36 -18
- data/lib/aspera/open_application.rb +4 -4
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/file_types.rb +4 -2
- data/lib/aspera/preview/generator.rb +22 -35
- data/lib/aspera/preview/options.rb +2 -0
- data/lib/aspera/preview/terminal.rb +24 -13
- data/lib/aspera/preview/utils.rb +19 -26
- data/lib/aspera/rest.rb +103 -72
- data/lib/aspera/rest_call_error.rb +1 -1
- data/lib/aspera/rest_error_analyzer.rb +15 -14
- data/lib/aspera/rest_errors_aspera.rb +37 -34
- data/lib/aspera/secret_hider.rb +14 -16
- data/lib/aspera/ssh.rb +4 -1
- data/lib/aspera/sync.rb +128 -122
- data/lib/aspera/temp_file_manager.rb +10 -3
- data/lib/aspera/web_auth.rb +10 -7
- data/lib/aspera/web_server_simple.rb +9 -4
- data.tar.gz.sig +0 -0
- metadata +33 -15
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/listener/line_dump.rb +0 -19
- data/lib/aspera/cli/listener/logger.rb +0 -22
- data/lib/aspera/cli/listener/progress.rb +0 -50
- data/lib/aspera/cli/listener/progress_multi.rb +0 -84
- data/lib/aspera/cli/plugins/sync.rb +0 -44
- data/lib/aspera/fasp/listener.rb +0 -13
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# spellchecker: ignore workgroups
|
3
|
+
# spellchecker: ignore workgroups mypackages passcode
|
4
4
|
|
5
5
|
require 'aspera/cli/basic_auth_plugin'
|
6
6
|
require 'aspera/persistency_action_once'
|
@@ -8,7 +8,6 @@ require 'aspera/id_generator'
|
|
8
8
|
require 'aspera/nagios'
|
9
9
|
require 'aspera/environment'
|
10
10
|
require 'securerandom'
|
11
|
-
require 'ruby-progressbar'
|
12
11
|
require 'tty-spinner'
|
13
12
|
|
14
13
|
module Aspera
|
@@ -22,78 +21,130 @@ module Aspera
|
|
22
21
|
API_LIST_MAILBOX_TYPES = %w[inbox inbox_history inbox_all inbox_all_history outbox outbox_history pending pending_history all].freeze
|
23
22
|
PACKAGE_ALL_INIT = 'INIT'
|
24
23
|
PACKAGE_SEND_FROM_REMOTE_SOURCE = 'remote_source'
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
# Faspex API v5: get transfer spec for connect
|
25
|
+
TRANSFER_CONNECT = 'connect'
|
26
|
+
ADMIN_RESOURCES = %i[
|
27
|
+
accounts contacts jobs workgroups shared_inboxes nodes oauth_clients registrations saml_configs
|
28
|
+
metadata_profiles email_notifications
|
29
|
+
].freeze
|
30
|
+
JOB_RUNNING = %w[queued working].freeze
|
31
|
+
STANDARD_PATH = '/aspera/faspex'
|
32
|
+
private_constant(*%i[JOB_RUNNING RECIPIENT_TYPES PACKAGE_TERMINATED API_DETECT API_LIST_MAILBOX_TYPES PACKAGE_SEND_FROM_REMOTE_SOURCE])
|
28
33
|
class << self
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
+
def application_name
|
35
|
+
'Faspex'
|
36
|
+
end
|
37
|
+
|
38
|
+
def detect(address_or_url)
|
39
|
+
address_or_url = "https://#{address_or_url}" unless address_or_url.match?(%r{^[a-z]{1,6}://})
|
40
|
+
urls = [address_or_url]
|
41
|
+
urls.push("#{address_or_url}#{STANDARD_PATH}") unless address_or_url.end_with?(STANDARD_PATH)
|
42
|
+
|
43
|
+
urls.each do |base_url|
|
44
|
+
next unless base_url.start_with?('https://')
|
45
|
+
api = Rest.new(base_url: base_url, redirect_max: 1)
|
46
|
+
result = api.read(API_DETECT)
|
47
|
+
next unless result[:http].code.start_with?('2') && result[:http].body.strip.empty?
|
48
|
+
url_length = -2 - API_DETECT.length
|
49
|
+
# take redirect if any
|
34
50
|
return {
|
35
51
|
version: result[:http]['x-ibm-aspera'] || '5',
|
36
|
-
url: result[:http].uri.to_s[0..
|
37
|
-
name: 'Faspex 5'
|
52
|
+
url: result[:http].uri.to_s[0..url_length]
|
38
53
|
}
|
54
|
+
rescue StandardError => e
|
55
|
+
Log.log.debug{"detect error: #{e}"}
|
39
56
|
end
|
40
57
|
return nil
|
41
58
|
end
|
42
|
-
end
|
43
59
|
|
44
|
-
|
45
|
-
|
60
|
+
def wizard(object:, private_key_path:, pub_key_pem:)
|
61
|
+
options = object.options
|
62
|
+
formatter = object.formatter
|
63
|
+
instance_url = options.get_option(:url, mandatory: true)
|
64
|
+
wiz_username = options.get_option(:username, mandatory: true)
|
65
|
+
raise "Username shall be an email in Faspex: #{wiz_username}" if !(wiz_username =~ /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i)
|
66
|
+
if options.get_option(:client_id).nil? || options.get_option(:client_secret).nil?
|
67
|
+
formatter.display_status('Ask the ascli client id and secret to your Administrator.'.red)
|
68
|
+
formatter.display_status("Admin should login to: #{instance_url}")
|
69
|
+
OpenApplication.instance.uri(instance_url)
|
70
|
+
formatter.display_status('Navigate to: 𓃑 → Admin → Configurations → API clients')
|
71
|
+
formatter.display_status('Create an API client with:')
|
72
|
+
formatter.display_status('- name: ascli')
|
73
|
+
formatter.display_status('- JWT: enabled')
|
74
|
+
formatter.display_status("Then, logged in as #{wiz_username.red} go to your profile:")
|
75
|
+
formatter.display_status('👤 → Account Settings → Preferences -> Public Key in PEM:')
|
76
|
+
formatter.display_status(pub_key_pem)
|
77
|
+
formatter.display_status('Once set, fill in the parameters:')
|
78
|
+
end
|
79
|
+
return {
|
80
|
+
preset_value: {
|
81
|
+
url: instance_url,
|
82
|
+
username: wiz_username,
|
83
|
+
auth: :jwt.to_s,
|
84
|
+
private_key: "@file:#{private_key_path}",
|
85
|
+
client_id: options.get_option(:client_id, mandatory: true),
|
86
|
+
client_secret: options.get_option(:client_secret, mandatory: true)
|
87
|
+
},
|
88
|
+
test_args: 'user profile show'
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def public_link?(url)
|
93
|
+
url.include?('/public/')
|
94
|
+
end
|
95
|
+
end
|
46
96
|
|
47
97
|
def initialize(env)
|
48
98
|
super(env)
|
49
99
|
options.declare(:client_id, 'OAuth client identifier')
|
50
100
|
options.declare(:client_secret, 'OAuth client secret')
|
51
101
|
options.declare(:redirect_uri, 'OAuth redirect URI for web authentication')
|
52
|
-
options.declare(:auth, 'OAuth type of authentication', values: %i[boot
|
102
|
+
options.declare(:auth, 'OAuth type of authentication', values: %i[boot].concat(Oauth::STD_AUTH_TYPES), default: :jwt)
|
53
103
|
options.declare(:private_key, 'OAuth JWT RSA private key PEM value (prefix file path with @file:)')
|
54
104
|
options.declare(:passphrase, 'OAuth JWT RSA private key passphrase')
|
55
|
-
options.declare(:
|
56
|
-
options.declare(:box, "Package inbox, either shared inbox name or one of #{API_LIST_MAILBOX_TYPES} or #{VAL_ALL}", default: 'inbox')
|
105
|
+
options.declare(:box, "Package inbox, either shared inbox name or one of #{API_LIST_MAILBOX_TYPES} or #{ExtendedValue::ALL}", default: 'inbox')
|
57
106
|
options.declare(:shared_folder, 'Send package with files from shared folder')
|
58
|
-
options.declare(:group_type, '
|
107
|
+
options.declare(:group_type, 'Type of shared box', values: %i[shared_inboxes workgroups], default: :shared_inboxes)
|
59
108
|
options.parse_options!
|
60
109
|
end
|
61
110
|
|
111
|
+
def api_url
|
112
|
+
return "#{@faspex5_api_base_url}/api/v5"
|
113
|
+
end
|
114
|
+
|
115
|
+
def auth_api_url
|
116
|
+
return "#{@faspex5_api_base_url}/auth"
|
117
|
+
end
|
118
|
+
|
62
119
|
def set_api
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
args = URI.decode_www_form(uri.query).each_with_object({}){|v, h|h[v.first] = v.last; }
|
75
|
-
Log.dump(:args, args)
|
76
|
-
context = args['context']
|
77
|
-
raise 'missing context' if context.nil?
|
78
|
-
@pub_link_context = JSON.parse(Base64.decode64(context))
|
79
|
-
Log.dump(:@pub_link_context, @pub_link_context)
|
120
|
+
# get endpoint, remove unnecessary trailing slashes
|
121
|
+
@faspex5_api_base_url = options.get_option(:url, mandatory: true).gsub(%r{/+$}, '')
|
122
|
+
auth_type = self.class.public_link?(@faspex5_api_base_url) ? :public_link : options.get_option(:auth, mandatory: true)
|
123
|
+
case auth_type
|
124
|
+
when :public_link
|
125
|
+
encoded_context = Rest.decode_query(URI.parse(@faspex5_api_base_url).query)['context']
|
126
|
+
raise 'Bad faspex5 public link, missing context in query' if encoded_context.nil?
|
127
|
+
@pub_link_context = JSON.parse(Base64.decode64(encoded_context))
|
128
|
+
Log.log.trace1{Log.dump(:@pub_link_context, @pub_link_context)}
|
129
|
+
# ok, we have the additional parameters, get the base url
|
130
|
+
@faspex5_api_base_url = @faspex5_api_base_url.gsub(%r{/public/.*}, '').gsub(/\?.*/, '')
|
80
131
|
@api_v5 = Rest.new({
|
81
|
-
base_url:
|
132
|
+
base_url: api_url,
|
82
133
|
headers: {'Passcode' => @pub_link_context['passcode']}
|
83
134
|
})
|
84
135
|
when :boot
|
85
136
|
# the password here is the token copied directly from browser in developer mode
|
86
137
|
@api_v5 = Rest.new({
|
87
|
-
base_url:
|
138
|
+
base_url: api_url,
|
88
139
|
headers: {'Authorization' => options.get_option(:password, mandatory: true)}
|
89
140
|
})
|
90
141
|
when :web
|
91
142
|
# opens a browser and ask user to auth using web
|
92
143
|
@api_v5 = Rest.new({
|
93
|
-
base_url:
|
144
|
+
base_url: api_url,
|
94
145
|
auth: {
|
95
146
|
type: :oauth2,
|
96
|
-
base_url:
|
147
|
+
base_url: auth_api_url,
|
97
148
|
grant_method: :web,
|
98
149
|
client_id: options.get_option(:client_id, mandatory: true),
|
99
150
|
web: {redirect_uri: options.get_option(:redirect_uri, mandatory: true)}
|
@@ -101,10 +152,10 @@ module Aspera
|
|
101
152
|
when :jwt
|
102
153
|
app_client_id = options.get_option(:client_id, mandatory: true)
|
103
154
|
@api_v5 = Rest.new({
|
104
|
-
base_url:
|
155
|
+
base_url: api_url,
|
105
156
|
auth: {
|
106
157
|
type: :oauth2,
|
107
|
-
base_url:
|
158
|
+
base_url: auth_api_url,
|
108
159
|
grant_method: :jwt,
|
109
160
|
client_id: app_client_id,
|
110
161
|
jwt: {
|
@@ -147,32 +198,45 @@ module Aspera
|
|
147
198
|
|
148
199
|
# wait for package status to be in provided list
|
149
200
|
def wait_package_status(id, status_list: PACKAGE_TERMINATED)
|
150
|
-
|
151
|
-
|
152
|
-
while true
|
201
|
+
total_sent = false
|
202
|
+
loop do
|
153
203
|
status = @api_v5.read("packages/#{id}/upload_details")[:data]
|
204
|
+
status['id'] = id
|
154
205
|
# user asked to not follow
|
155
|
-
|
206
|
+
return status if status_list.nil?
|
156
207
|
if status['upload_status'].eql?('submitted')
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
spinner.spin
|
163
|
-
elsif progress.nil?
|
164
|
-
progress = ProgressBar.create(
|
165
|
-
format: '%a %B %p%% %r Mbps %e',
|
166
|
-
rate_scale: lambda{|rate|rate / Environment::BYTES_PER_MEBIBIT},
|
167
|
-
title: 'progress',
|
168
|
-
total: status['bytes_total'].to_i)
|
208
|
+
config.progress_bar&.event(session_id: nil, type: :pre_start, info: status['upload_status'])
|
209
|
+
elsif !total_sent
|
210
|
+
config.progress_bar&.event(session_id: id, type: :session_start)
|
211
|
+
config.progress_bar&.event(session_id: id, type: :session_size, info: status['bytes_total'].to_i)
|
212
|
+
total_sent = true
|
169
213
|
else
|
170
|
-
|
214
|
+
config.progress_bar&.event(session_id: id, type: :transfer, info: status['bytes_written'].to_i)
|
215
|
+
end
|
216
|
+
if status_list.include?(status['upload_status'])
|
217
|
+
# if status['upload_status'].eql?('completed')
|
218
|
+
config.progress_bar&.event(session_id: id, type: :end)
|
219
|
+
return status
|
220
|
+
# end
|
221
|
+
end
|
222
|
+
sleep(1.0)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def wait_for_job(job_id)
|
227
|
+
spinner = nil
|
228
|
+
loop do
|
229
|
+
status = @api_v5.read("jobs/#{job_id}", {type: :formatted})[:data]
|
230
|
+
return status unless JOB_RUNNING.include?(status['status'])
|
231
|
+
if spinner.nil?
|
232
|
+
spinner = TTY::Spinner.new('[:spinner] :title', format: :classic)
|
233
|
+
spinner.start
|
171
234
|
end
|
235
|
+
spinner.update(title: status['status'])
|
236
|
+
spinner.spin
|
172
237
|
sleep(0.5)
|
173
238
|
end
|
174
|
-
|
175
|
-
return status
|
239
|
+
raise 'internal error'
|
176
240
|
end
|
177
241
|
|
178
242
|
# get a (full or partial) list of all entities of a given type
|
@@ -228,7 +292,7 @@ module Aspera
|
|
228
292
|
box = options.get_option(:box)
|
229
293
|
api_path =
|
230
294
|
case box
|
231
|
-
when
|
295
|
+
when ExtendedValue::ALL then '' # only admin can list all packages globally
|
232
296
|
when *API_LIST_MAILBOX_TYPES then box
|
233
297
|
else
|
234
298
|
group_type = options.get_option(:group_type)
|
@@ -240,7 +304,7 @@ module Aspera
|
|
240
304
|
path: api_path).select(&filter)
|
241
305
|
end
|
242
306
|
|
243
|
-
def package_receive
|
307
|
+
def package_receive(package_ids)
|
244
308
|
# prepare persistency if needed
|
245
309
|
skip_ids_persistency = nil
|
246
310
|
if options.get_option(:once_only, mandatory: true)
|
@@ -253,50 +317,43 @@ module Aspera
|
|
253
317
|
options.get_option(:url, mandatory: true),
|
254
318
|
options.get_option(:username, mandatory: true)]))
|
255
319
|
end
|
256
|
-
package_ids =
|
257
|
-
if @pub_link_context&.key?('package_id')
|
258
|
-
@pub_link_context['package_id']
|
259
|
-
else
|
260
|
-
# one or several packages
|
261
|
-
instance_identifier
|
262
|
-
end
|
263
320
|
case package_ids
|
264
321
|
when PACKAGE_ALL_INIT
|
265
322
|
raise 'Only with option once_only' unless skip_ids_persistency
|
266
323
|
skip_ids_persistency.data.clear.concat(list_packages_with_filter.map{|p|p['id']})
|
267
324
|
skip_ids_persistency.save
|
268
325
|
return Main.result_status("Initialized skip for #{skip_ids_persistency.data.count} package(s)")
|
269
|
-
when
|
326
|
+
when ExtendedValue::ALL
|
270
327
|
# TODO: if packages have same name, they will overwrite ?
|
271
328
|
package_ids = list_packages_with_filter.map{|p|p['id']}
|
272
|
-
Log.dump(:package_ids, package_ids)
|
273
|
-
Log.dump(:
|
329
|
+
Log.log.debug{Log.dump(:package_ids, package_ids)}
|
330
|
+
Log.log.debug{Log.dump(:skip_ids, skip_ids_persistency.data)}
|
274
331
|
package_ids.reject!{|i|skip_ids_persistency.data.include?(i)} if skip_ids_persistency
|
275
|
-
Log.dump(:package_ids, package_ids)
|
332
|
+
Log.log.debug{Log.dump(:package_ids, package_ids)}
|
276
333
|
end
|
277
334
|
# a single id was provided
|
278
335
|
# TODO: check package_ids is a list of strings
|
279
336
|
package_ids = [package_ids] if package_ids.is_a?(String)
|
280
337
|
result_transfer = []
|
338
|
+
param_file_list = {}
|
339
|
+
begin
|
340
|
+
param_file_list['paths'] = transfer.source_list.map{|source|{'path'=>source}}
|
341
|
+
rescue Cli::BadArgument
|
342
|
+
# paths is optional
|
343
|
+
end
|
344
|
+
download_params = {
|
345
|
+
type: 'received',
|
346
|
+
transfer_type: TRANSFER_CONNECT
|
347
|
+
}
|
348
|
+
box = options.get_option(:box)
|
349
|
+
case box
|
350
|
+
when /outbox/ then download_params[:type] = 'sent'
|
351
|
+
when *API_LIST_MAILBOX_TYPES then nil # nothing to do
|
352
|
+
else # shared inbox / workgroup
|
353
|
+
download_params[:recipient_workgroup_id] = lookup_entity_by_field(type: options.get_option(:group_type), value: box)['id']
|
354
|
+
end
|
281
355
|
package_ids.each do |pkg_id|
|
282
356
|
formatter.display_status("Receiving package #{pkg_id}")
|
283
|
-
param_file_list = {}
|
284
|
-
begin
|
285
|
-
param_file_list['paths'] = transfer.source_list.map{|source|{'path'=>source}}
|
286
|
-
rescue Aspera::Cli::CliBadArgument
|
287
|
-
# paths is optional
|
288
|
-
end
|
289
|
-
download_params = {
|
290
|
-
type: 'received',
|
291
|
-
transfer_type: TRANSFER_CONNECT
|
292
|
-
}
|
293
|
-
box = options.get_option(:box)
|
294
|
-
case box
|
295
|
-
when /outbox/ then download_params[:type] = 'sent'
|
296
|
-
when *API_LIST_MAILBOX_TYPES then nil # nothing to do
|
297
|
-
else # shared inbox / workgroup
|
298
|
-
download_params[:recipient_workgroup_id] = lookup_entity_by_field(type: options.get_option(:group_type), value: box)['id']
|
299
|
-
end
|
300
357
|
# TODO: allow from sent as well ?
|
301
358
|
transfer_spec = @api_v5.call(
|
302
359
|
operation: 'POST',
|
@@ -319,21 +376,15 @@ module Aspera
|
|
319
376
|
end
|
320
377
|
|
321
378
|
def package_action
|
322
|
-
command = options.get_next_command(%i[
|
379
|
+
command = options.get_next_command(%i[show browse status delete receive send list])
|
380
|
+
package_id =
|
381
|
+
if %i[receive show browse status delete].include?(command)
|
382
|
+
@pub_link_context&.key?('package_id') ? @pub_link_context['package_id'] : instance_identifier
|
383
|
+
end
|
323
384
|
case command
|
324
|
-
when :list
|
325
|
-
return {
|
326
|
-
type: :object_list,
|
327
|
-
data: list_packages_with_filter,
|
328
|
-
fields: %w[id title release_date total_bytes total_files created_time state]
|
329
|
-
}
|
330
385
|
when :show
|
331
|
-
|
332
|
-
id ||= instance_identifier
|
333
|
-
return {type: :single_object, data: @api_v5.read("packages/#{id}")[:data]}
|
386
|
+
return {type: :single_object, data: @api_v5.read("packages/#{package_id}")[:data]}
|
334
387
|
when :browse
|
335
|
-
id = @pub_link_context['package_id'] if @pub_link_context&.key?('package_id')
|
336
|
-
id ||= instance_identifier
|
337
388
|
path = options.get_next_argument('path', expected: :single, mandatory: false) || '/'
|
338
389
|
# TODO: support multi-page listing ?
|
339
390
|
params = {
|
@@ -343,29 +394,31 @@ module Aspera
|
|
343
394
|
}
|
344
395
|
result = @api_v5.call({
|
345
396
|
operation: 'POST',
|
346
|
-
subpath: "packages/#{
|
397
|
+
subpath: "packages/#{package_id}/files/received",
|
347
398
|
headers: {'Accept' => 'application/json'},
|
348
399
|
url_params: params,
|
349
400
|
json_params: {'path' => path, 'filters' => {'basenames'=>[]}}})[:data]
|
350
401
|
formatter.display_item_count(result['item_count'], result['total_count'])
|
351
402
|
return {type: :object_list, data: result['items']}
|
352
403
|
when :status
|
353
|
-
status = wait_package_status(
|
404
|
+
status = wait_package_status(package_id, status_list: nil)
|
354
405
|
return {type: :single_object, data: status}
|
355
406
|
when :delete
|
356
|
-
ids =
|
407
|
+
ids = package_id
|
357
408
|
ids = [ids] unless ids.is_a?(Array)
|
358
409
|
raise 'Package identifier must be a single id or an Array' unless ids.is_a?(Array) && ids.all?(String)
|
359
410
|
# API returns 204, empty on success
|
360
411
|
@api_v5.call({operation: 'DELETE', subpath: 'packages', headers: {'Accept' => 'application/json'}, json_params: {ids: ids}})
|
361
412
|
return Main.result_status('Package(s) deleted')
|
413
|
+
when :receive
|
414
|
+
return package_receive(package_id)
|
362
415
|
when :send
|
363
|
-
parameters = value_create_modify(command: command
|
416
|
+
parameters = value_create_modify(command: command)
|
364
417
|
normalize_recipients(parameters)
|
365
418
|
package = @api_v5.create('packages', parameters)[:data]
|
366
419
|
shared_folder = options.get_option(:shared_folder)
|
367
420
|
if shared_folder.nil?
|
368
|
-
#
|
421
|
+
# send from local files
|
369
422
|
transfer_spec = @api_v5.call(
|
370
423
|
operation: 'POST',
|
371
424
|
subpath: "packages/#{package['id']}/transfer_spec/upload",
|
@@ -377,6 +430,7 @@ module Aspera
|
|
377
430
|
transfer_spec.delete('authentication')
|
378
431
|
return Main.result_transfer(transfer.start(transfer_spec))
|
379
432
|
else
|
433
|
+
# send from remote shared folder
|
380
434
|
if (m = shared_folder.match(REGEX_LOOKUP_ID_BY_FIELD))
|
381
435
|
shared_folder = lookup_entity_by_field(type: 'shared_folders', value: m[2])['id']
|
382
436
|
end
|
@@ -390,8 +444,12 @@ module Aspera
|
|
390
444
|
end
|
391
445
|
return {type: :single_object, data: result}
|
392
446
|
end
|
393
|
-
when :
|
394
|
-
return
|
447
|
+
when :list
|
448
|
+
return {
|
449
|
+
type: :object_list,
|
450
|
+
data: list_packages_with_filter,
|
451
|
+
fields: %w[id title release_date total_bytes total_files created_time state]
|
452
|
+
}
|
395
453
|
end # case package
|
396
454
|
end
|
397
455
|
|
@@ -474,10 +532,10 @@ module Aspera
|
|
474
532
|
list_key = false
|
475
533
|
id_as_arg = 'type'
|
476
534
|
when :accounts
|
477
|
-
display_fields =
|
535
|
+
display_fields = Formatter.all_but('user_profile_data_attributes')
|
478
536
|
when :oauth_clients
|
479
|
-
display_fields =
|
480
|
-
adm_api = Rest.new(@api_v5.params.merge({base_url:
|
537
|
+
display_fields = Formatter.all_but('public_key')
|
538
|
+
adm_api = Rest.new(@api_v5.params.merge({base_url: auth_api_url}))
|
481
539
|
when :shared_inboxes, :workgroups
|
482
540
|
available_commands.push(:members, :saml_groups, :invite_external_collaborator)
|
483
541
|
end
|
@@ -533,20 +591,23 @@ module Aspera
|
|
533
591
|
when :show
|
534
592
|
return { type: :single_object, data: @api_v5.read(smtp_path)[:data] }
|
535
593
|
when :create
|
536
|
-
return { type: :single_object, data: @api_v5.create(smtp_path, value_create_modify(command: smtp_cmd
|
594
|
+
return { type: :single_object, data: @api_v5.create(smtp_path, value_create_modify(command: smtp_cmd))[:data] }
|
537
595
|
when :modify
|
538
|
-
return { type: :single_object, data: @api_v5.
|
596
|
+
return { type: :single_object, data: @api_v5.update(smtp_path, value_create_modify(command: smtp_cmd))[:data] }
|
539
597
|
when :delete
|
540
598
|
return { type: :single_object, data: @api_v5.delete(smtp_path)[:data] }
|
541
599
|
when :test
|
542
600
|
test_data = options.get_next_argument('Email or test data, see API')
|
543
601
|
test_data = {test_email_recipient: test_data} if test_data.is_a?(String)
|
544
|
-
|
602
|
+
creation = @api_v5.create(File.join(smtp_path, 'test'), test_data)[:data]
|
603
|
+
result = wait_for_job(creation['job_id'])
|
604
|
+
result['serialized_args'] = JSON.parse(result['serialized_args']) rescue result['serialized_args']
|
605
|
+
return { type: :single_object, data: result }
|
545
606
|
end
|
546
607
|
end
|
547
608
|
when :gateway
|
548
609
|
require 'aspera/faspex_gw'
|
549
|
-
url = value_create_modify(type: String)
|
610
|
+
url = value_create_modify(command: command, type: String)
|
550
611
|
uri = URI.parse(url)
|
551
612
|
server = WebServerSimple.new(uri)
|
552
613
|
server.mount(uri.path, Faspex4GWServlet, @api_v5, nil)
|
@@ -559,7 +620,7 @@ module Aspera
|
|
559
620
|
return Main.result_status('Gateway terminated')
|
560
621
|
when :postprocessing
|
561
622
|
require 'aspera/faspex_postproc' # cspell:disable-line
|
562
|
-
parameters = value_create_modify(
|
623
|
+
parameters = value_create_modify(command: command)
|
563
624
|
parameters = parameters.symbolize_keys
|
564
625
|
raise 'Missing key: url' unless parameters.key?(:url)
|
565
626
|
uri = URI.parse(parameters[:url])
|
@@ -576,36 +637,6 @@ module Aspera
|
|
576
637
|
return Main.result_status('Gateway terminated')
|
577
638
|
end # case command
|
578
639
|
end # action
|
579
|
-
|
580
|
-
def wizard(params)
|
581
|
-
if params[:prepare]
|
582
|
-
# if not defined by user, generate unique name
|
583
|
-
params[:preset_name] ||= [params[:plugin_sym]].concat(URI.parse(params[:instance_url]).host.gsub(/[^a-z0-9.]/, '').split('.')).join('_')
|
584
|
-
params[:need_private_key] = true
|
585
|
-
return
|
586
|
-
end
|
587
|
-
formatter.display_status('Ask the ascli client id and secret to your Administrator, or ask them to go to:'.red)
|
588
|
-
OpenApplication.instance.uri(params[:instance_url])
|
589
|
-
formatter.display_status('Then: 𓃑 → Admin → Configurations → API clients')
|
590
|
-
formatter.display_status('Create an API client with:')
|
591
|
-
formatter.display_status('- name: ascli')
|
592
|
-
formatter.display_status('- JWT: enabled')
|
593
|
-
formatter.display_status('Then, logged in as user go to your profile:')
|
594
|
-
formatter.display_status('👤 → Account Settings → Preferences -> Public Key in PEM:')
|
595
|
-
formatter.display_status(params[:pub_key_pem])
|
596
|
-
formatter.display_status('Once set, fill in the parameters:')
|
597
|
-
return {
|
598
|
-
preset_value: {
|
599
|
-
url: params[:instance_url],
|
600
|
-
username: options.get_option(:username, mandatory: true),
|
601
|
-
auth: :jwt.to_s,
|
602
|
-
private_key: '@file:' + params[:private_key_path],
|
603
|
-
client_id: options.get_option(:client_id, mandatory: true),
|
604
|
-
client_secret: options.get_option(:client_secret, mandatory: true)
|
605
|
-
},
|
606
|
-
test_args: "#{params[:plugin_sym]} user profile show"
|
607
|
-
}
|
608
|
-
end
|
609
640
|
end # Faspex5
|
610
641
|
end # Plugins
|
611
642
|
end # Cli
|