aspera-cli 4.22.0 → 4.24.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 +405 -364
- data/CONTRIBUTING.md +86 -29
- data/README.md +1856 -961
- data/bin/ascli +2 -1
- data/bin/asession +4 -4
- data/lib/aspera/agent/base.rb +4 -0
- data/lib/aspera/agent/connect.rb +20 -18
- data/lib/aspera/agent/desktop.rb +14 -11
- data/lib/aspera/agent/direct.rb +39 -31
- data/lib/aspera/agent/httpgw.rb +2 -2
- data/lib/aspera/agent/node.rb +9 -11
- data/lib/aspera/agent/transferd.rb +18 -11
- data/lib/aspera/api/aoc.rb +53 -43
- data/lib/aspera/api/cos_node.rb +7 -5
- data/lib/aspera/api/httpgw.rb +23 -22
- data/lib/aspera/api/node.rb +104 -22
- data/lib/aspera/ascmd.rb +35 -21
- data/lib/aspera/ascp/installation.rb +43 -43
- data/lib/aspera/ascp/management.rb +5 -4
- data/lib/aspera/assert.rb +55 -24
- data/lib/aspera/cli/basic_auth_plugin.rb +8 -7
- data/lib/aspera/cli/error.rb +1 -1
- data/lib/aspera/cli/extended_value.rb +28 -29
- data/lib/aspera/cli/formatter.rb +191 -168
- data/lib/aspera/cli/hints.rb +38 -4
- data/lib/aspera/cli/main.rb +139 -108
- data/lib/aspera/cli/manager.rb +51 -31
- data/lib/aspera/cli/plugin.rb +149 -78
- data/lib/aspera/cli/plugin_factory.rb +2 -2
- data/lib/aspera/cli/plugins/aoc.rb +217 -88
- data/lib/aspera/cli/plugins/ats.rb +15 -13
- data/lib/aspera/cli/plugins/config.rb +105 -227
- data/lib/aspera/cli/plugins/console.rb +49 -18
- data/lib/aspera/cli/plugins/cos.rb +4 -4
- data/lib/aspera/cli/plugins/faspex.rb +45 -51
- data/lib/aspera/cli/plugins/faspex5.rb +162 -163
- data/lib/aspera/cli/plugins/faspio.rb +6 -5
- data/lib/aspera/cli/plugins/httpgw.rb +2 -2
- data/lib/aspera/cli/plugins/node.rb +233 -247
- data/lib/aspera/cli/plugins/orchestrator.rb +10 -14
- data/lib/aspera/cli/plugins/preview.rb +26 -29
- data/lib/aspera/cli/plugins/server.rb +29 -28
- data/lib/aspera/cli/plugins/shares.rb +40 -28
- data/lib/aspera/cli/sync_actions.rb +101 -80
- data/lib/aspera/cli/transfer_agent.rb +55 -58
- data/lib/aspera/cli/transfer_progress.rb +29 -20
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +160 -0
- data/lib/aspera/colors.rb +13 -8
- data/lib/aspera/command_line_builder.rb +28 -22
- data/lib/aspera/command_line_converter.rb +31 -0
- data/lib/aspera/data_repository.rb +1 -0
- data/lib/aspera/environment.rb +144 -100
- data/lib/aspera/faspex_gw.rb +1 -1
- data/lib/aspera/faspex_postproc.rb +3 -2
- data/lib/aspera/hash_ext.rb +1 -1
- data/lib/aspera/id_generator.rb +10 -10
- data/lib/aspera/keychain/base.rb +18 -0
- data/lib/aspera/keychain/encrypted_hash.rb +6 -12
- data/lib/aspera/keychain/factory.rb +9 -3
- data/lib/aspera/keychain/hashicorp_vault.rb +9 -6
- data/lib/aspera/keychain/macos_security.rb +13 -13
- data/lib/aspera/log.rb +70 -20
- data/lib/aspera/nagios.rb +5 -6
- data/lib/aspera/node_simulator.rb +12 -7
- data/lib/aspera/oauth/base.rb +6 -2
- data/lib/aspera/oauth/factory.rb +25 -18
- data/lib/aspera/oauth/jwt.rb +13 -1
- data/lib/aspera/oauth/url_json.rb +3 -3
- data/lib/aspera/oauth/web.rb +5 -3
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/file_types.rb +43 -35
- data/lib/aspera/preview/generator.rb +26 -13
- data/lib/aspera/preview/terminal.rb +10 -7
- data/lib/aspera/preview/utils.rb +11 -9
- data/lib/aspera/products/connect.rb +2 -1
- data/lib/aspera/products/desktop.rb +1 -1
- data/lib/aspera/products/other.rb +2 -2
- data/lib/aspera/products/transferd.rb +8 -6
- data/lib/aspera/proxy_auto_config.rb +1 -1
- data/lib/aspera/rest.rb +46 -28
- data/lib/aspera/rest_call_error.rb +1 -1
- data/lib/aspera/rest_error_analyzer.rb +1 -0
- data/lib/aspera/resumer.rb +1 -1
- data/lib/aspera/secret_hider.rb +46 -40
- data/lib/aspera/ssh.rb +14 -4
- data/lib/aspera/sync/args.schema.yaml +102 -0
- data/lib/aspera/sync/conf.schema.yaml +701 -0
- data/lib/aspera/sync/database.rb +83 -0
- data/lib/aspera/{transfer/sync.rb → sync/operations.rb} +145 -68
- data/lib/aspera/temp_file_manager.rb +4 -2
- data/lib/aspera/timer_limiter.rb +7 -5
- data/lib/aspera/transfer/error.rb +1 -1
- data/lib/aspera/transfer/error_info.rb +1 -2
- data/lib/aspera/transfer/faux_file.rb +11 -10
- data/lib/aspera/transfer/parameters.rb +6 -5
- data/lib/aspera/transfer/spec.rb +15 -1
- data/lib/aspera/transfer/spec.schema.yaml +316 -293
- data/lib/aspera/transfer/spec_doc.rb +34 -16
- data/lib/aspera/transfer/uri.rb +5 -5
- data/lib/aspera/uri_reader.rb +14 -10
- data/lib/aspera/web_auth.rb +2 -2
- data/lib/aspera/web_server_simple.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +15 -15
- metadata.gz.sig +0 -0
- data/examples/dascli +0 -30
- data/examples/get_proto_file.rb +0 -8
- data/examples/proxy.pac +0 -60
- data/lib/aspera/transfer/convert.rb +0 -29
- data/lib/aspera/transfer/sync_instance.schema.yaml +0 -13
- data/lib/aspera/transfer/sync_session.schema.yaml +0 -79
@@ -35,13 +35,40 @@ module Aspera
|
|
35
35
|
PATH_AUTH = 'auth'
|
36
36
|
PATH_HEALTH = 'configuration/ping'
|
37
37
|
PATH_API_DETECT = "#{PATH_API_V5}/#{PATH_HEALTH}"
|
38
|
-
PER_PAGE_DEFAULT = 100
|
39
38
|
# OAuth methods supported
|
40
39
|
STD_AUTH_TYPES = %i[web jwt boot].freeze
|
41
40
|
HEADER_ITERATION_TOKEN = 'X-Aspera-Next-Iteration-Token'
|
42
41
|
HEADER_FASPEX_VERSION = 'X-IBM-Aspera'
|
43
|
-
|
44
|
-
|
42
|
+
EMAIL_NOTIF_LIST = %w[
|
43
|
+
welcome_email
|
44
|
+
forgot_password
|
45
|
+
package_received
|
46
|
+
package_received_cc
|
47
|
+
package_sent_cc
|
48
|
+
package_downloaded
|
49
|
+
package_downloaded_cc
|
50
|
+
workgroup_package
|
51
|
+
upload_result
|
52
|
+
upload_result_cc
|
53
|
+
relay_started_cc
|
54
|
+
relay_finished_cc
|
55
|
+
relay_error_cc
|
56
|
+
shared_inbox_invitation
|
57
|
+
shared_inbox_submit
|
58
|
+
personal_invitation
|
59
|
+
personal_submit
|
60
|
+
account_approved
|
61
|
+
account_denied
|
62
|
+
package_file_processing_failed_sender
|
63
|
+
package_file_processing_failed_recipient
|
64
|
+
relay_failed_admin
|
65
|
+
relay_failed
|
66
|
+
admin_sync_failed
|
67
|
+
sync_failed
|
68
|
+
account_exist
|
69
|
+
mfa_code
|
70
|
+
]
|
71
|
+
private_constant :JOB_RUNNING, :RECIPIENT_TYPES, :PACKAGE_TERMINATED, :PATH_HEALTH, :API_LIST_MAILBOX_TYPES, :PACKAGE_SEND_FROM_REMOTE_SOURCE, :STD_AUTH_TYPES, :HEADER_ITERATION_TOKEN, :HEADER_FASPEX_VERSION, :EMAIL_NOTIF_LIST
|
45
72
|
class << self
|
46
73
|
def application_name
|
47
74
|
'Faspex'
|
@@ -71,7 +98,7 @@ module Aspera
|
|
71
98
|
Log.log.debug{"detect error: #{e}"}
|
72
99
|
end
|
73
100
|
raise error if error
|
74
|
-
return
|
101
|
+
return
|
75
102
|
end
|
76
103
|
|
77
104
|
# @param object [Plugin] An instance of this class
|
@@ -93,10 +120,11 @@ module Aspera
|
|
93
120
|
formatter.display_status('- name: ascli')
|
94
121
|
formatter.display_status('- JWT: enabled')
|
95
122
|
formatter.display_status("Then, logged in as #{wiz_username.red} go to your profile:")
|
96
|
-
formatter.display_status('👤 → Account Settings → Preferences
|
123
|
+
formatter.display_status('👤 → Account Settings → Preferences → Public Key in PEM:')
|
97
124
|
formatter.display_status(pub_key_pem)
|
98
125
|
formatter.display_status('Once set, fill in the parameters:')
|
99
126
|
end
|
127
|
+
return {preset_value: {}, test_args: ''} if options.get_option(:test_mode)
|
100
128
|
return {
|
101
129
|
preset_value: {
|
102
130
|
url: instance_url,
|
@@ -116,7 +144,7 @@ module Aspera
|
|
116
144
|
end
|
117
145
|
end
|
118
146
|
|
119
|
-
def initialize(**
|
147
|
+
def initialize(**_)
|
120
148
|
super
|
121
149
|
options.declare(:client_id, 'OAuth client identifier')
|
122
150
|
options.declare(:client_secret, 'OAuth client secret')
|
@@ -140,10 +168,10 @@ module Aspera
|
|
140
168
|
# resolve any redirect
|
141
169
|
@faspex5_api_base_url = Rest.new(base_url: @faspex5_api_base_url, redirect_max: 3).call(operation: 'GET')[:http].uri.to_s
|
142
170
|
encoded_context = Rest.query_to_h(URI.parse(@faspex5_api_base_url).query)['context']
|
143
|
-
raise 'Bad faspex5 public link, missing context in query' if encoded_context.nil?
|
171
|
+
raise BadArgument, 'Bad faspex5 public link, missing context in query' if encoded_context.nil?
|
144
172
|
# public link information (allowed usage)
|
145
173
|
@pub_link_context = JSON.parse(Base64.decode64(encoded_context))
|
146
|
-
Log.
|
174
|
+
Log.dump(:@pub_link_context, @pub_link_context, level: :trace1)
|
147
175
|
# ok, we have the additional parameters, get the base url
|
148
176
|
@faspex5_api_base_url = @faspex5_api_base_url.gsub(%r{/public/.*}, '').gsub(/\?.*/, '')
|
149
177
|
@api_v5 = Rest.new(
|
@@ -166,7 +194,8 @@ module Aspera
|
|
166
194
|
grant_method: :web,
|
167
195
|
client_id: options.get_option(:client_id, mandatory: true),
|
168
196
|
redirect_uri: options.get_option(:redirect_uri, mandatory: true)
|
169
|
-
}
|
197
|
+
}
|
198
|
+
)
|
170
199
|
when :jwt
|
171
200
|
app_client_id = options.get_option(:client_id, mandatory: true)
|
172
201
|
@api_v5 = Rest.new(
|
@@ -183,7 +212,8 @@ module Aspera
|
|
183
212
|
},
|
184
213
|
private_key_obj: OpenSSL::PKey::RSA.new(options.get_option(:private_key, mandatory: true), options.get_option(:passphrase)),
|
185
214
|
headers: {typ: 'JWT'}
|
186
|
-
}
|
215
|
+
}
|
216
|
+
)
|
187
217
|
else Aspera.error_unexpected_value(auth_type)
|
188
218
|
end
|
189
219
|
# in case user wants to use HTTPGW tell transfer agent how to get address
|
@@ -223,7 +253,7 @@ module Aspera
|
|
223
253
|
# user asked to not follow
|
224
254
|
return status if status_list.nil?
|
225
255
|
if status['upload_status'].eql?('submitted')
|
226
|
-
config.progress_bar&.event(:
|
256
|
+
config.progress_bar&.event(:sessions_init, session_id: nil, info: status['upload_status'])
|
227
257
|
elsif !total_sent
|
228
258
|
config.progress_bar&.event(:session_start, session_id: id)
|
229
259
|
config.progress_bar&.event(:session_size, session_id: id, info: status['bytes_total'].to_i)
|
@@ -232,7 +262,8 @@ module Aspera
|
|
232
262
|
config.progress_bar&.event(:transfer, session_id: id, info: status['bytes_written'].to_i)
|
233
263
|
end
|
234
264
|
if status_list.include?(status['upload_status'])
|
235
|
-
config.progress_bar&.event(:
|
265
|
+
config.progress_bar&.event(:session_end, session_id: id)
|
266
|
+
config.progress_bar&.event(:end)
|
236
267
|
return status
|
237
268
|
end
|
238
269
|
sleep(1.0)
|
@@ -253,82 +284,25 @@ module Aspera
|
|
253
284
|
return result
|
254
285
|
end
|
255
286
|
|
256
|
-
# Get a (full or partial) list of all entities of a given type with query: offset/limit
|
257
|
-
# @param type [String] the type of entity to list (just a name)
|
258
|
-
# @param query [Hash,nil] additional query parameters
|
259
|
-
# @param real_path [String] real path if it's n ot just the type
|
260
|
-
# @param item_list_key [String] key in the result to get the list of items
|
261
|
-
def list_entities(type:, real_path: nil, item_list_key: nil, query: nil)
|
262
|
-
Log.log.trace1{"list_entities t=#{type} p=#{real_path} k=#{item_list_key} q=#{query}"}
|
263
|
-
type = type.to_s if type.is_a?(Symbol)
|
264
|
-
query = {} if query.nil?
|
265
|
-
Aspera.assert_type(type, String)
|
266
|
-
Aspera.assert_type(query, Hash)
|
267
|
-
item_list_key = type if item_list_key.nil?
|
268
|
-
real_path = type if real_path.nil?
|
269
|
-
result = []
|
270
|
-
offset = 0
|
271
|
-
max_items = query.delete(MAX_ITEMS)
|
272
|
-
remain_pages = query.delete(MAX_PAGES)
|
273
|
-
# merge default parameters, by default 100 per page
|
274
|
-
query = {'limit'=> PER_PAGE_DEFAULT}.merge(query)
|
275
|
-
loop do
|
276
|
-
query['offset'] = offset
|
277
|
-
page_result = @api_v5.read(real_path, query)
|
278
|
-
Aspera.assert_type(page_result[item_list_key], Array)
|
279
|
-
result.concat(page_result[item_list_key])
|
280
|
-
# reach the limit set by user ?
|
281
|
-
if !max_items.nil? && (result.length >= max_items)
|
282
|
-
result = result.slice(0, max_items)
|
283
|
-
break
|
284
|
-
end
|
285
|
-
break if result.length >= page_result['total_count']
|
286
|
-
remain_pages -= 1 unless remain_pages.nil?
|
287
|
-
break if remain_pages == 0
|
288
|
-
offset += page_result[item_list_key].length
|
289
|
-
formatter.long_operation_running
|
290
|
-
end
|
291
|
-
formatter.long_operation_terminated
|
292
|
-
return result
|
293
|
-
end
|
294
|
-
|
295
|
-
# lookup an entity id from its name
|
296
|
-
# @param type [String] the type of entity to lookup, by default it is the path, and it is also the field name in result
|
297
|
-
# @param value [String] the value to lookup
|
298
|
-
# @param field [String] the field to match, by default it is 'name'
|
299
|
-
# @param real_path [String] real path if it's not just the type (override type)
|
300
|
-
# @param item_list_key [String] key in the result to get the list of items (override type)
|
301
|
-
# @param query [Hash] additional query parameters
|
302
|
-
def lookup_entity_by_field(type:, value:, field: 'name', real_path: nil, item_list_key: nil, query: :default)
|
303
|
-
if query.eql?(:default)
|
304
|
-
Aspera.assert(field.eql?('name')){'Default query is on name only'}
|
305
|
-
query = {'q'=> value}
|
306
|
-
end
|
307
|
-
found = list_entities(type: type, real_path: real_path, query: query, item_list_key: item_list_key).select{ |i| i[field].eql?(value)}
|
308
|
-
case found.length
|
309
|
-
when 0 then raise "No #{type} with #{field} = #{value}"
|
310
|
-
when 1 then return found.first
|
311
|
-
else raise "Found #{found.length} #{real_path} with #{field} = #{value}"
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
287
|
# list all packages with optional filter
|
316
288
|
def list_packages_with_filter(query: {})
|
317
289
|
filter = options.get_next_argument('filter', mandatory: false, validation: Proc, default: ->(_x){true})
|
318
290
|
# translate box name to API prefix (with ending slash)
|
319
291
|
box = options.get_option(:box)
|
320
|
-
|
292
|
+
entity =
|
321
293
|
case box
|
322
294
|
when SpecialValues::ALL then 'packages' # only admin can list all packages globally
|
323
295
|
when *API_LIST_MAILBOX_TYPES then "#{box}/packages"
|
324
296
|
else
|
325
297
|
group_type = options.get_option(:group_type)
|
326
|
-
"#{group_type}/#{lookup_entity_by_field(
|
298
|
+
"#{group_type}/#{lookup_entity_by_field(api: @api_v5, entity: group_type, value: box)['id']}/packages"
|
327
299
|
end
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
300
|
+
list, total = list_entities_limit_offset_total_count(
|
301
|
+
api: @api_v5,
|
302
|
+
entity: entity,
|
303
|
+
query: query_read_delete(default: query)
|
304
|
+
)
|
305
|
+
return list.select(&filter), total
|
332
306
|
end
|
333
307
|
|
334
308
|
def package_receive(package_ids)
|
@@ -344,22 +318,23 @@ module Aspera
|
|
344
318
|
options.get_option(:url, mandatory: true),
|
345
319
|
options.get_option(:username, mandatory: true),
|
346
320
|
options.get_option(:box, mandatory: true)
|
347
|
-
])
|
321
|
+
])
|
322
|
+
)
|
348
323
|
end
|
349
324
|
packages = []
|
350
325
|
case package_ids
|
351
326
|
when SpecialValues::INIT
|
352
327
|
Aspera.assert(skip_ids_persistency){'Only with option once_only'}
|
353
|
-
skip_ids_persistency.data.clear.concat(list_packages_with_filter.map{ |p| p['id']})
|
328
|
+
skip_ids_persistency.data.clear.concat(list_packages_with_filter.first.map{ |p| p['id']})
|
354
329
|
skip_ids_persistency.save
|
355
330
|
return Main.result_status("Initialized skip for #{skip_ids_persistency.data.count} package(s)")
|
356
331
|
when SpecialValues::ALL
|
357
332
|
# TODO: if packages have same name, they will overwrite ?
|
358
|
-
packages = list_packages_with_filter(query: {'status' => 'completed'})
|
359
|
-
Log.
|
360
|
-
Log.
|
333
|
+
packages = list_packages_with_filter(query: {'status' => 'completed'}).first
|
334
|
+
Log.dump(:package_ids, level: :trace1){packages.map{ |p| p['id']}}
|
335
|
+
Log.dump(:skip_ids, skip_ids_persistency.data, level: :trace1)
|
361
336
|
packages.reject!{ |p| skip_ids_persistency.data.include?(p['id'])} if skip_ids_persistency
|
362
|
-
Log.
|
337
|
+
Log.dump(:package_ids, level: :trace1){packages.map{ |p| p['id']}}
|
363
338
|
else
|
364
339
|
# a single id was provided, or a list of ids
|
365
340
|
package_ids = [package_ids] unless package_ids.is_a?(Array)
|
@@ -384,7 +359,7 @@ module Aspera
|
|
384
359
|
when /outbox/ then download_params[:type] = 'sent'
|
385
360
|
when *API_LIST_MAILBOX_TYPES then nil # nothing to do
|
386
361
|
else # shared inbox / workgroup
|
387
|
-
download_params[:recipient_workgroup_id] = lookup_entity_by_field(
|
362
|
+
download_params[:recipient_workgroup_id] = lookup_entity_by_field(api: @api_v5, entity: options.get_option(:group_type), value: box)['id']
|
388
363
|
end
|
389
364
|
packages.each do |package|
|
390
365
|
pkg_id = package['id']
|
@@ -448,17 +423,13 @@ module Aspera
|
|
448
423
|
all_items = all_items.slice(0, max_items) if all_items.count > max_items
|
449
424
|
break
|
450
425
|
end
|
451
|
-
if recursive
|
452
|
-
folders_to_process.concat(response[:data]['items'].select{ |i| i['type'].eql?('directory')}.map{ |i| i['path']})
|
453
|
-
end
|
426
|
+
folders_to_process.concat(response[:data]['items'].select{ |i| i['type'].eql?('directory')}.map{ |i| i['path']}) if recursive
|
454
427
|
if use_paging
|
455
428
|
iteration_token = response[:http][HEADER_ITERATION_TOKEN]
|
456
429
|
break if iteration_token.nil? || iteration_token.empty?
|
457
430
|
query['iteration_token'] = iteration_token
|
458
431
|
else
|
459
|
-
if total_count.nil?
|
460
|
-
total_count = response[:data]['total_count']
|
461
|
-
end
|
432
|
+
total_count = response[:data]['total_count'] if total_count.nil?
|
462
433
|
break if response[:data]['item_count'].eql?(0)
|
463
434
|
query['offset'] += response[:data]['item_count']
|
464
435
|
end
|
@@ -484,7 +455,7 @@ module Aspera
|
|
484
455
|
location = case options.get_option(:box)
|
485
456
|
when 'inbox' then 'received'
|
486
457
|
when 'outbox' then 'sent'
|
487
|
-
else raise 'Browse only available for inbox and outbox'
|
458
|
+
else raise BadArgument, 'Browse only available for inbox and outbox'
|
488
459
|
end
|
489
460
|
return browse_folder("packages/#{package_id}/files/#{location}")
|
490
461
|
when :status
|
@@ -536,9 +507,11 @@ module Aspera
|
|
536
507
|
# send from remote shared folder
|
537
508
|
if (m = shared_folder.match(REGEX_LOOKUP_ID_BY_FIELD))
|
538
509
|
shared_folder = lookup_entity_by_field(
|
539
|
-
|
510
|
+
api: @api_v5,
|
511
|
+
entity: 'shared_folders',
|
540
512
|
field: m[1],
|
541
|
-
value: ExtendedValue.instance.evaluate(m[2])
|
513
|
+
value: ExtendedValue.instance.evaluate(m[2])
|
514
|
+
)['id']
|
542
515
|
end
|
543
516
|
transfer_request = {shared_folder_id: shared_folder, paths: transfer.source_list}
|
544
517
|
# start remote transfer and get first status
|
@@ -551,100 +524,102 @@ module Aspera
|
|
551
524
|
return Main.result_single_object(result)
|
552
525
|
end
|
553
526
|
when :list
|
554
|
-
|
555
|
-
|
556
|
-
data: list_packages_with_filter,
|
557
|
-
fields: %w[id title release_date total_bytes total_files created_time state]
|
558
|
-
}
|
527
|
+
list, total = list_packages_with_filter
|
528
|
+
return Main.result_object_list(list, total: total, fields: %w[id title release_date total_bytes total_files created_time state])
|
559
529
|
end
|
560
530
|
end
|
561
531
|
|
562
|
-
def execute_resource(
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
532
|
+
def execute_resource(res_sym)
|
533
|
+
exec_args = {
|
534
|
+
api: @api_v5,
|
535
|
+
entity: res_sym.to_s,
|
536
|
+
tclo: true
|
537
|
+
}
|
567
538
|
res_id_query = :default
|
568
|
-
|
569
|
-
|
570
|
-
case res_type
|
539
|
+
available_commands = Plugin::ALL_OPS
|
540
|
+
case res_sym
|
571
541
|
when :metadata_profiles
|
572
|
-
|
573
|
-
|
542
|
+
exec_args[:entity] = 'configuration/metadata_profiles'
|
543
|
+
exec_args[:items_key] = 'profiles'
|
574
544
|
when :alternate_addresses
|
575
|
-
|
545
|
+
exec_args[:entity] = 'configuration/alternate_addresses'
|
576
546
|
when :distribution_lists
|
577
|
-
|
578
|
-
|
579
|
-
delete_style = 'ids'
|
547
|
+
exec_args[:entity] = 'account/distribution_lists'
|
548
|
+
exec_args[:delete_style] = 'ids'
|
580
549
|
when :email_notifications
|
581
|
-
|
582
|
-
id_as_arg = 'type'
|
550
|
+
exec_args.delete(:items_key)
|
551
|
+
exec_args[:id_as_arg] = 'type'
|
583
552
|
when :accounts
|
584
|
-
display_fields = Formatter.all_but('user_profile_data_attributes')
|
585
|
-
available_commands
|
553
|
+
exec_args[:display_fields] = Formatter.all_but('user_profile_data_attributes')
|
554
|
+
available_commands += [:reset_password]
|
586
555
|
when :oauth_clients
|
587
|
-
display_fields = Formatter.all_but('public_key')
|
588
|
-
|
556
|
+
exec_args[:display_fields] = Formatter.all_but('public_key')
|
557
|
+
exec_args[:api] = Rest.new(**@api_v5.params, base_url: "#{@faspex5_api_base_url}/#{PATH_AUTH}")
|
558
|
+
exec_args[:list_query] = {'expand': true, 'no_api_path': true, 'client_types[]': 'public'}
|
589
559
|
when :shared_inboxes, :workgroups
|
590
|
-
available_commands
|
560
|
+
available_commands += %i[members saml_groups invite_external_collaborator]
|
591
561
|
res_id_query = {'all': true}
|
592
562
|
when :nodes
|
593
|
-
available_commands
|
563
|
+
available_commands += %i[shared_folders browse]
|
594
564
|
end
|
595
565
|
res_command = options.get_next_command(available_commands)
|
566
|
+
return Main.result_value_list(EMAIL_NOTIF_LIST, name: 'email_id') if res_command.eql?(:list) && res_sym.eql?(:email_notifications)
|
596
567
|
case res_command
|
597
568
|
when *Plugin::ALL_OPS
|
598
|
-
return
|
599
|
-
|
600
|
-
delete_style: delete_style) do |field, value|
|
601
|
-
lookup_entity_by_field(
|
602
|
-
type: res_type, value: value, field: field, real_path: res_path, item_list_key: list_key, query: res_id_query)['id']
|
569
|
+
return entity_execute(command: res_command, **exec_args) do |field, value|
|
570
|
+
lookup_entity_by_field(api: @api_v5, entity: exec_args[:entity], value: value, field: field, items_key: exec_args[:items_key], query: res_id_query)['id']
|
603
571
|
end
|
604
572
|
when :shared_folders
|
573
|
+
# nodes
|
605
574
|
node_id = instance_identifier do |field, value|
|
606
|
-
lookup_entity_by_field(
|
575
|
+
lookup_entity_by_field(api: @api_v5, entity: 'nodes', field: field, value: value)['id']
|
607
576
|
end
|
608
|
-
|
609
|
-
sh_command = options.get_next_command([:user]
|
577
|
+
shfld_entity = "nodes/#{node_id}/shared_folders"
|
578
|
+
sh_command = options.get_next_command(Plugin::ALL_OPS + [:user])
|
610
579
|
case sh_command
|
611
580
|
when *Plugin::ALL_OPS
|
612
|
-
return
|
613
|
-
|
581
|
+
return entity_execute(
|
582
|
+
api: @api_v5,
|
583
|
+
entity: shfld_entity,
|
584
|
+
command: sh_command
|
585
|
+
) do |field, value|
|
586
|
+
lookup_entity_by_field(api: @api_v5, entity: shfld_entity, field: field, value: value)['id']
|
614
587
|
end
|
615
588
|
when :user
|
616
589
|
sh_id = instance_identifier do |field, value|
|
617
|
-
lookup_entity_by_field(
|
590
|
+
lookup_entity_by_field(api: @api_v5, entity: shfld_entity, field: field, value: value)['id']
|
618
591
|
end
|
619
|
-
user_path = "#{
|
620
|
-
return
|
621
|
-
lookup_entity_by_field(
|
592
|
+
user_path = "#{shfld_entity}/#{sh_id}/custom_access_users"
|
593
|
+
return entity_execute(api: @api_v5, entity: user_path, items_key: 'users') do |field, value|
|
594
|
+
lookup_entity_by_field(api: @api_v5, entity: user_path, items_key: 'users', field: field, value: value)['id']
|
622
595
|
end
|
623
596
|
|
624
597
|
end
|
625
598
|
when :browse
|
599
|
+
# nodes
|
626
600
|
node_id = instance_identifier do |field, value|
|
627
|
-
lookup_entity_by_field(
|
628
|
-
type: res_type, value: value, field: field, real_path: res_path, item_list_key: list_key, query: res_id_query)['id']
|
601
|
+
lookup_entity_by_field(api: @api_v5, entity: 'nodes', value: value, field: field)['id']
|
629
602
|
end
|
630
|
-
return browse_folder("
|
603
|
+
return browse_folder("nodes/#{node_id}/browse")
|
631
604
|
when :invite_external_collaborator
|
632
|
-
|
605
|
+
# :shared_inboxes, :workgroups
|
606
|
+
shared_inbox_id = instance_identifier{ |field, value| lookup_entity_by_field(api: @api_v5, entity: res_sym.to_s, field: field, value: value, query: res_id_query)['id']}
|
633
607
|
creation_payload = value_create_modify(command: res_command, type: [Hash, String])
|
634
608
|
creation_payload = {'email_address' => creation_payload} if creation_payload.is_a?(String)
|
635
|
-
|
636
|
-
result = adm_api.create(res_path, creation_payload)
|
609
|
+
result = @api_v5.create("#{res_sym}/#{shared_inbox_id}/external_collaborator", creation_payload)
|
637
610
|
formatter.display_status(result['message'])
|
638
611
|
result = lookup_entity_by_field(
|
639
|
-
|
640
|
-
|
612
|
+
api: @api_v5,
|
613
|
+
entity: "#{res_sym}/#{shared_inbox_id}/members",
|
614
|
+
items_key: 'members',
|
641
615
|
value: creation_payload['email_address'],
|
642
|
-
query: {}
|
616
|
+
query: {}
|
617
|
+
)
|
643
618
|
return Main.result_single_object(result)
|
644
619
|
when :members, :saml_groups
|
645
|
-
|
646
|
-
|
647
|
-
res_path = "#{
|
620
|
+
# :shared_inboxes, :workgroups
|
621
|
+
res_id = instance_identifier{ |field, value| lookup_entity_by_field(api: @api_v5, entity: res_sym.to_s, field: field, value: value, query: res_id_query)['id']}
|
622
|
+
res_path = "#{res_sym}/#{res_id}/#{res_command}"
|
648
623
|
list_key = res_command.to_s
|
649
624
|
list_key = 'groups' if res_command.eql?(:saml_groups)
|
650
625
|
sub_command = options.get_next_command(%i[create list modify delete])
|
@@ -655,10 +630,12 @@ module Aspera
|
|
655
630
|
users = users.map do |user|
|
656
631
|
if (m = user.match(REGEX_LOOKUP_ID_BY_FIELD))
|
657
632
|
lookup_entity_by_field(
|
658
|
-
|
633
|
+
api: @api_v5,
|
634
|
+
entity: 'accounts',
|
659
635
|
field: m[1],
|
660
636
|
value: ExtendedValue.instance.evaluate(m[2]),
|
661
|
-
query: {type: Rest.array_params(%w{local_user saml_user self_registered_user external_user})}
|
637
|
+
query: {type: Rest.array_params(%w{local_user saml_user self_registered_user external_user})}
|
638
|
+
)['id']
|
662
639
|
else
|
663
640
|
# it's the user id (not member id...)
|
664
641
|
user
|
@@ -667,16 +644,24 @@ module Aspera
|
|
667
644
|
access = options.get_next_argument('level', mandatory: false, accept_list: %i[submit_only standard shared_inbox_admin], default: :standard)
|
668
645
|
options.unshift_next_argument({user: users.map{ |u| {id: u, access: access}}})
|
669
646
|
end
|
670
|
-
return
|
647
|
+
return entity_execute(
|
648
|
+
api: @api_v5,
|
649
|
+
entity: res_path,
|
650
|
+
command: sub_command,
|
651
|
+
items_key: list_key
|
652
|
+
) do |field, value|
|
671
653
|
lookup_entity_by_field(
|
672
|
-
|
654
|
+
api: @api_v5,
|
655
|
+
entity: 'accounts',
|
673
656
|
field: field,
|
674
657
|
value: value,
|
675
|
-
query: {type: Rest.array_params(%w{local_user saml_user self_registered_user external_user})}
|
658
|
+
query: {type: Rest.array_params(%w{local_user saml_user self_registered_user external_user})}
|
659
|
+
)['id']
|
676
660
|
end
|
677
661
|
when :reset_password
|
678
|
-
|
679
|
-
|
662
|
+
# :accounts
|
663
|
+
contact_id = instance_identifier{ |field, value| lookup_entity_by_field(api: @api_v5, entity: 'accounts', field: field, value: value, query: res_id_query)['id']}
|
664
|
+
@api_v5.create("accounts/#{contact_id}/reset_password", {})
|
680
665
|
return Main.result_status('password reset, user shall check email')
|
681
666
|
end
|
682
667
|
Aspera.error_unreachable_line
|
@@ -700,12 +685,21 @@ module Aspera
|
|
700
685
|
event_type = options.get_next_command(%i[application webhook])
|
701
686
|
case event_type
|
702
687
|
when :application
|
703
|
-
|
704
|
-
|
705
|
-
|
688
|
+
list, total = list_entities_limit_offset_total_count(
|
689
|
+
api: @api_v5,
|
690
|
+
entity: 'application_events',
|
691
|
+
query: query_read_delete
|
692
|
+
)
|
693
|
+
|
694
|
+
return Main.result_object_list(list, total: total, fields: %w[event_type created_at application user.name])
|
706
695
|
when :webhook
|
707
|
-
|
708
|
-
|
696
|
+
list, total = list_entities_limit_offset_total_count(
|
697
|
+
api: @api_v5,
|
698
|
+
entity: 'all_webhooks_events',
|
699
|
+
query: query_read_delete,
|
700
|
+
items_key: 'events'
|
701
|
+
)
|
702
|
+
return Main.result_object_list(list, total: total)
|
709
703
|
end
|
710
704
|
when :configuration
|
711
705
|
conf_path = 'configuration'
|
@@ -717,6 +711,7 @@ module Aspera
|
|
717
711
|
return Main.result_single_object(@api_v5.update(conf_path, value_create_modify(command: conf_cmd)))
|
718
712
|
end
|
719
713
|
when :smtp
|
714
|
+
# only one SMTP config
|
720
715
|
smtp_path = 'configuration/smtp'
|
721
716
|
smtp_cmd = options.get_next_command(%i[show create modify delete test])
|
722
717
|
case smtp_cmd
|
@@ -807,11 +802,15 @@ module Aspera
|
|
807
802
|
@api_v5.create("#{invitation_endpoint}/#{instance_identifier}/resend")
|
808
803
|
return Main.result_status('Invitation resent')
|
809
804
|
else
|
810
|
-
return
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
805
|
+
return entity_execute(
|
806
|
+
api: @api_v5,
|
807
|
+
entity: invitation_endpoint,
|
808
|
+
command: invitation_command,
|
809
|
+
items_key: invitation_endpoint,
|
810
|
+
display_fields: %w[id public recipient_type recipient_name email_address]
|
811
|
+
) do |field, value|
|
812
|
+
lookup_entity_by_field(api: @api_v5, entity: invitation_endpoint, field: field, value: value, query: {})['id']
|
813
|
+
end
|
815
814
|
end
|
816
815
|
when :gateway
|
817
816
|
require 'aspera/faspex_gw'
|
@@ -17,8 +17,8 @@ module Aspera
|
|
17
17
|
api = Rest.new(base_url: base_url)
|
18
18
|
ping_result = api.call(operation: 'GET', subpath: 'ping', headers: {'Accept' => Rest::MIME_JSON})
|
19
19
|
server_type = ping_result[:http]['Server']
|
20
|
-
return
|
21
|
-
return
|
20
|
+
return unless ping_result[:data].is_a?(Hash) && ping_result[:data].empty?
|
21
|
+
return unless server_type.is_a?(String) && server_type.include?('faspio')
|
22
22
|
return {
|
23
23
|
version: server_type.gsub(%r{^.*/}, ''),
|
24
24
|
url: base_url
|
@@ -39,7 +39,7 @@ module Aspera
|
|
39
39
|
end
|
40
40
|
ACTIONS = %i[health bridges].freeze
|
41
41
|
|
42
|
-
def initialize(**
|
42
|
+
def initialize(**_)
|
43
43
|
super
|
44
44
|
options.declare(:auth, 'OAuth type of authentication', values: %i[jwt basic])
|
45
45
|
options.declare(:client_id, 'OAuth client identifier')
|
@@ -70,7 +70,8 @@ module Aspera
|
|
70
70
|
},
|
71
71
|
private_key_obj: OpenSSL::PKey::RSA.new(options.get_option(:private_key, mandatory: true), options.get_option(:passphrase)),
|
72
72
|
headers: {typ: 'JWT'}
|
73
|
-
}
|
73
|
+
}
|
74
|
+
)
|
74
75
|
end
|
75
76
|
command = options.get_next_command(ACTIONS)
|
76
77
|
case command
|
@@ -88,7 +89,7 @@ module Aspera
|
|
88
89
|
end
|
89
90
|
return nagios.result
|
90
91
|
when :bridges
|
91
|
-
return
|
92
|
+
return entity_execute(api: api, entity: 'bridges')
|
92
93
|
end
|
93
94
|
end
|
94
95
|
end
|
@@ -20,7 +20,7 @@ module Aspera
|
|
20
20
|
url: api.base_url,
|
21
21
|
version: api_info['version']
|
22
22
|
} if api_info.is_a?(Hash) && api_info.key?('download_endpoint')
|
23
|
-
return
|
23
|
+
return
|
24
24
|
end
|
25
25
|
|
26
26
|
# @param object [Plugin] An instance of this class
|
@@ -37,7 +37,7 @@ module Aspera
|
|
37
37
|
end
|
38
38
|
ACTIONS = %i[health info].freeze
|
39
39
|
|
40
|
-
def initialize(**
|
40
|
+
def initialize(**_)
|
41
41
|
super
|
42
42
|
options.declare(:url, 'URL of application, e.g. https://app.example.com/aspera/app')
|
43
43
|
options.parse_options!
|