aspera-cli 4.17.0 → 4.18.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +2 -4
- data/CHANGELOG.md +23 -0
- data/CONTRIBUTING.md +15 -1
- data/README.md +620 -378
- data/bin/ascli +5 -0
- data/bin/asession +2 -2
- data/lib/aspera/agent/alpha.rb +6 -4
- data/lib/aspera/agent/base.rb +9 -6
- data/lib/aspera/agent/connect.rb +4 -4
- data/lib/aspera/agent/direct.rb +56 -37
- data/lib/aspera/agent/httpgw.rb +23 -324
- data/lib/aspera/agent/node.rb +19 -20
- data/lib/aspera/agent/trsdk.rb +19 -20
- data/lib/aspera/api/aoc.rb +17 -14
- data/lib/aspera/api/cos_node.rb +4 -4
- data/lib/aspera/api/httpgw.rb +339 -0
- data/lib/aspera/api/node.rb +34 -21
- data/lib/aspera/ascmd.rb +4 -3
- data/lib/aspera/ascp/installation.rb +15 -7
- data/lib/aspera/ascp/management.rb +2 -2
- data/lib/aspera/cli/basic_auth_plugin.rb +5 -9
- data/lib/aspera/cli/extended_value.rb +12 -6
- data/lib/aspera/cli/formatter.rb +155 -65
- data/lib/aspera/cli/hints.rb +18 -0
- data/lib/aspera/cli/main.rb +22 -29
- data/lib/aspera/cli/manager.rb +53 -36
- data/lib/aspera/cli/plugin.rb +26 -17
- data/lib/aspera/cli/plugin_factory.rb +31 -20
- data/lib/aspera/cli/plugins/alee.rb +14 -2
- data/lib/aspera/cli/plugins/aoc.rb +141 -131
- data/lib/aspera/cli/plugins/ats.rb +1 -1
- data/lib/aspera/cli/plugins/config.rb +52 -46
- data/lib/aspera/cli/plugins/console.rb +8 -5
- data/lib/aspera/cli/plugins/faspex.rb +27 -19
- data/lib/aspera/cli/plugins/faspex5.rb +222 -149
- data/lib/aspera/cli/plugins/faspio.rb +85 -0
- data/lib/aspera/cli/plugins/httpgw.rb +55 -0
- data/lib/aspera/cli/plugins/node.rb +86 -29
- data/lib/aspera/cli/plugins/orchestrator.rb +31 -29
- data/lib/aspera/cli/plugins/preview.rb +6 -2
- data/lib/aspera/cli/plugins/server.rb +5 -5
- data/lib/aspera/cli/plugins/shares.rb +16 -14
- data/lib/aspera/cli/sync_actions.rb +6 -6
- data/lib/aspera/cli/transfer_agent.rb +5 -4
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +7 -6
- data/lib/aspera/faspex_gw.rb +5 -4
- data/lib/aspera/faspex_postproc.rb +2 -2
- data/lib/aspera/log.rb +6 -3
- data/lib/aspera/node_simulator.rb +2 -2
- data/lib/aspera/oauth/base.rb +31 -19
- data/lib/aspera/oauth/factory.rb +12 -13
- data/lib/aspera/oauth/generic.rb +1 -0
- data/lib/aspera/oauth/jwt.rb +18 -15
- data/lib/aspera/oauth/url_json.rb +8 -6
- data/lib/aspera/open_application.rb +5 -7
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/generator.rb +3 -3
- data/lib/aspera/preview/options.rb +3 -3
- data/lib/aspera/preview/terminal.rb +4 -4
- data/lib/aspera/preview/utils.rb +3 -3
- data/lib/aspera/proxy_auto_config.rb +5 -1
- data/lib/aspera/rest.rb +60 -74
- data/lib/aspera/rest_call_error.rb +1 -1
- data/lib/aspera/rest_error_analyzer.rb +2 -2
- data/lib/aspera/rest_errors_aspera.rb +1 -1
- data/lib/aspera/resumer.rb +1 -1
- data/lib/aspera/secret_hider.rb +2 -4
- data/lib/aspera/ssh.rb +1 -1
- data/lib/aspera/transfer/parameters.rb +39 -36
- data/lib/aspera/transfer/spec.rb +2 -0
- data/lib/aspera/transfer/sync.rb +2 -1
- data/lib/aspera/transfer/uri.rb +1 -1
- data/lib/aspera/uri_reader.rb +5 -4
- data/lib/aspera/web_auth.rb +1 -1
- data/lib/aspera/web_server_simple.rb +4 -3
- data.tar.gz.sig +0 -0
- metadata +5 -3
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/plugins/bss.rb +0 -71
@@ -18,7 +18,10 @@ module Aspera
|
|
18
18
|
next unless base_url.start_with?('https://')
|
19
19
|
api = Rest.new(base_url: base_url, redirect_max: 2)
|
20
20
|
test_endpoint = 'login'
|
21
|
-
test_page = api.call(
|
21
|
+
test_page = api.call(
|
22
|
+
operation: 'GET',
|
23
|
+
subpath: test_endpoint,
|
24
|
+
query: {local: true})
|
22
25
|
next unless test_page[:http].body.include?('Aspera Console')
|
23
26
|
version = 'unknown'
|
24
27
|
if (m = test_page[:http].body.match(/\(v([1-9]\..*)\)/))
|
@@ -102,7 +105,7 @@ module Aspera
|
|
102
105
|
end
|
103
106
|
end
|
104
107
|
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -179,7 +179,11 @@ module Aspera
|
|
179
179
|
loop do
|
180
180
|
# get a batch of package information
|
181
181
|
# order: first batch is latest packages, and then in a batch ids are increasing
|
182
|
-
atom_xml = api_v3.call(
|
182
|
+
atom_xml = api_v3.call(
|
183
|
+
operation: 'GET',
|
184
|
+
subpath: "#{mailbox}.atom",
|
185
|
+
headers: {'Accept' => 'application/xml'},
|
186
|
+
query: mailbox_query)[:http].body
|
183
187
|
box_data = XmlSimple.xml_in(atom_xml, {'ForceArray' => %w[entry field link to]})
|
184
188
|
Log.log.debug{Log.dump(:box_data, box_data)}
|
185
189
|
items = box_data.key?('entry') ? box_data['entry'] : []
|
@@ -246,8 +250,9 @@ module Aspera
|
|
246
250
|
package_creation_data = api_public_link.call(
|
247
251
|
operation: 'POST',
|
248
252
|
subpath: create_path,
|
249
|
-
|
250
|
-
|
253
|
+
headers: {'Accept' => 'text/javascript'},
|
254
|
+
body: package_create_params,
|
255
|
+
body_type: :json)[:http].body
|
251
256
|
# get arguments of function call
|
252
257
|
package_creation_data.delete!("\n") # one line
|
253
258
|
package_creation_data.gsub!(/^[^"]+\("\{/, '{') # delete header
|
@@ -308,8 +313,9 @@ module Aspera
|
|
308
313
|
pkg_created = api_v3.call(
|
309
314
|
operation: 'POST',
|
310
315
|
subpath: 'send',
|
311
|
-
|
312
|
-
|
316
|
+
headers: {'Accept' => 'application/json'},
|
317
|
+
body: package_create_params,
|
318
|
+
body_type: :json
|
313
319
|
)[:data]
|
314
320
|
if first_source.key?('id')
|
315
321
|
# no transfer spec if remote source: handled by faspex
|
@@ -380,9 +386,9 @@ module Aspera
|
|
380
386
|
api_public_link = Rest.new(base_url: link_data[:base_url])
|
381
387
|
package_creation_data = api_public_link.call(
|
382
388
|
operation: 'GET',
|
383
|
-
subpath:
|
384
|
-
|
385
|
-
|
389
|
+
subpath: link_data[:subpath],
|
390
|
+
headers: {'Accept' => 'application/xml'},
|
391
|
+
query: {passcode: link_data[:query]['passcode']})
|
386
392
|
if !package_creation_data[:http].body.start_with?('<?xml ')
|
387
393
|
OpenApplication.instance.uri(link_url)
|
388
394
|
raise Cli::Error, 'Unexpected response: package not found ?'
|
@@ -391,7 +397,7 @@ module Aspera
|
|
391
397
|
Log.log.debug{Log.dump(:package_entry, package_entry)}
|
392
398
|
transfer_uri = self.class.get_fasp_uri_from_entry(package_entry)
|
393
399
|
pkg_id_uri = [{id: package_entry['id'], uri: transfer_uri}]
|
394
|
-
end
|
400
|
+
end
|
395
401
|
# prune packages already downloaded
|
396
402
|
# TODO : remove ids from skip not present in inbox to avoid growing too big
|
397
403
|
# skip_ids_data.select!{|id|pkg_id_uri.select{|p|p[:id].eql?(id)}}
|
@@ -411,10 +417,12 @@ module Aspera
|
|
411
417
|
xml_payload =
|
412
418
|
%Q(<?xml version="1.0" encoding="UTF-8"?><url-list xmlns="http://schemas.asperasoft.com/xml/url-list"><url href="#{sanitized}"/></url-list>)
|
413
419
|
transfer_spec['token'] = api_v3.call(
|
414
|
-
operation:
|
415
|
-
subpath:
|
416
|
-
headers:
|
417
|
-
|
420
|
+
operation: 'POST',
|
421
|
+
subpath: 'issue-token',
|
422
|
+
headers: {'Accept' => 'text/plain', 'Content-Type' => 'application/vnd.aspera.url-list+xml'},
|
423
|
+
query: {'direction' => 'down'},
|
424
|
+
body: xml_payload,
|
425
|
+
body_type: :text)[:http].body
|
418
426
|
end
|
419
427
|
transfer_spec['direction'] = Transfer::Spec::DIRECTION_RECEIVE
|
420
428
|
statuses = transfer.start(transfer_spec)
|
@@ -502,9 +510,9 @@ module Aspera
|
|
502
510
|
when :address_book
|
503
511
|
result = api_v3.call(
|
504
512
|
operation: 'GET',
|
505
|
-
subpath:
|
506
|
-
headers:
|
507
|
-
|
513
|
+
subpath: 'address-book',
|
514
|
+
headers: {'Accept' => 'application/json'},
|
515
|
+
query: {'format' => 'json', 'count' => 100_000}
|
508
516
|
)[:data]
|
509
517
|
formatter.display_status("users: #{result['itemsPerPage']}/#{result['totalResults']}, start:#{result['startIndex']}")
|
510
518
|
users = result['entry']
|
@@ -526,9 +534,9 @@ module Aspera
|
|
526
534
|
login_meths = api_v3.call(operation: 'GET', subpath: 'login/new', headers: {'Accept' => 'application/xrds+xml'})[:http].body
|
527
535
|
login_methods = XmlSimple.xml_in(login_meths, {'ForceArray' => false})
|
528
536
|
return {type: :object_list, data: login_methods['XRD']['Service']}
|
529
|
-
end
|
537
|
+
end
|
530
538
|
end
|
531
539
|
end
|
532
540
|
end
|
533
|
-
end
|
534
|
-
end
|
541
|
+
end
|
542
|
+
end
|
@@ -10,7 +10,6 @@ require 'aspera/nagios'
|
|
10
10
|
require 'aspera/environment'
|
11
11
|
require 'aspera/assert'
|
12
12
|
require 'securerandom'
|
13
|
-
require 'tty-spinner'
|
14
13
|
|
15
14
|
module Aspera
|
16
15
|
module Cli
|
@@ -24,8 +23,8 @@ module Aspera
|
|
24
23
|
# Faspex API v5: get transfer spec for connect
|
25
24
|
TRANSFER_CONNECT = 'connect'
|
26
25
|
ADMIN_RESOURCES = %i[
|
27
|
-
accounts contacts jobs workgroups shared_inboxes nodes oauth_clients registrations saml_configs
|
28
|
-
metadata_profiles email_notifications alternate_addresses
|
26
|
+
accounts distribution_lists contacts jobs workgroups shared_inboxes nodes oauth_clients registrations saml_configs
|
27
|
+
metadata_profiles email_notifications alternate_addresses webhooks
|
29
28
|
].freeze
|
30
29
|
# states for jobs not in final state
|
31
30
|
JOB_RUNNING = %w[queued working].freeze
|
@@ -58,7 +57,7 @@ module Aspera
|
|
58
57
|
path_api_detect = "#{PATH_API_V5}/#{PATH_HEALTH}"
|
59
58
|
result = api.read(path_api_detect)
|
60
59
|
next unless result[:http].code.start_with?('2') && result[:http].body.strip.empty?
|
61
|
-
# end is at -1, and
|
60
|
+
# end is at -1, and subtract 1 for "/"
|
62
61
|
url_length = -2 - path_api_detect.length
|
63
62
|
# take redirect if any
|
64
63
|
return {
|
@@ -237,31 +236,27 @@ module Aspera
|
|
237
236
|
end
|
238
237
|
|
239
238
|
def wait_for_job(job_id)
|
240
|
-
spinner = nil
|
241
239
|
loop do
|
242
240
|
status = @api_v5.read("jobs/#{job_id}", {type: :formatted})[:data]
|
243
241
|
return status unless JOB_RUNNING.include?(status['status'])
|
244
|
-
|
245
|
-
spinner = TTY::Spinner.new('[:spinner] :title', format: :classic)
|
246
|
-
spinner.start
|
247
|
-
end
|
248
|
-
spinner.update(title: status['status'])
|
249
|
-
spinner.spin
|
242
|
+
formatter.long_operation_running(status['status'])
|
250
243
|
sleep(0.5)
|
251
244
|
end
|
252
245
|
Aspera.error_unreachable_line
|
253
246
|
end
|
254
247
|
|
255
|
-
# Get a (full or partial) list of all entities of a given type
|
248
|
+
# Get a (full or partial) list of all entities of a given type with query: offset/limit
|
256
249
|
# @param type [String] the type of entity to list (just a name)
|
257
250
|
# @param query [Hash,nil] additional query parameters
|
258
251
|
# @param real_path [String] real path if it's n ot just the type
|
259
252
|
# @param item_list_key [String] key in the result to get the list of items
|
260
|
-
def list_entities(type:, real_path: nil,
|
253
|
+
def list_entities(type:, real_path: nil, item_list_key: nil, query: {})
|
254
|
+
Log.log.trace1{"list_entities t=#{type} p=#{real_path} k=#{item_list_key} q=#{query}"}
|
261
255
|
type = type.to_s if type.is_a?(Symbol)
|
262
256
|
Aspera.assert_type(type, String)
|
257
|
+
Aspera.assert_type(query, Hash)
|
263
258
|
item_list_key = type if item_list_key.nil?
|
264
|
-
|
259
|
+
real_path = type if real_path.nil?
|
265
260
|
result = []
|
266
261
|
offset = 0
|
267
262
|
max_items = query.delete(MAX_ITEMS)
|
@@ -270,7 +265,8 @@ module Aspera
|
|
270
265
|
query = {'limit'=> PER_PAGE_DEFAULT}.merge(query)
|
271
266
|
loop do
|
272
267
|
query['offset'] = offset
|
273
|
-
page_result = @api_v5.read(
|
268
|
+
page_result = @api_v5.read(real_path, query)[:data]
|
269
|
+
Aspera.assert_type(page_result[item_list_key], Array)
|
274
270
|
result.concat(page_result[item_list_key])
|
275
271
|
# reach the limit set by user ?
|
276
272
|
if !max_items.nil? && (result.length >= max_items)
|
@@ -281,12 +277,19 @@ module Aspera
|
|
281
277
|
remain_pages -= 1 unless remain_pages.nil?
|
282
278
|
break if remain_pages == 0
|
283
279
|
offset += page_result[item_list_key].length
|
280
|
+
formatter.long_operation_running
|
284
281
|
end
|
285
282
|
return result
|
286
283
|
end
|
287
284
|
|
288
285
|
# lookup an entity id from its name
|
289
|
-
|
286
|
+
# @param type [String] the type of entity to lookup, by default it is the path, and it is also the field name in result
|
287
|
+
# @param value [String] the value to lookup
|
288
|
+
# @param field [String] the field to match, by default it is 'name'
|
289
|
+
# @param real_path [String] real path if it's not just the type (override type)
|
290
|
+
# @param item_list_key [String] key in the result to get the list of items (override type)
|
291
|
+
# @param query [Hash] additional query parameters
|
292
|
+
def lookup_entity_by_field(type:, value:, field: 'name', real_path: nil, item_list_key: nil, query: :default)
|
290
293
|
if query.eql?(:default)
|
291
294
|
Aspera.assert(field.eql?('name')){'Default query is on name only'}
|
292
295
|
query = {'q'=> value}
|
@@ -381,8 +384,9 @@ module Aspera
|
|
381
384
|
operation: 'POST',
|
382
385
|
subpath: "packages/#{pkg_id}/transfer_spec/download",
|
383
386
|
headers: {'Accept' => 'application/json'},
|
384
|
-
|
385
|
-
|
387
|
+
query: download_params,
|
388
|
+
body: param_file_list,
|
389
|
+
body_type: :json
|
386
390
|
)[:data]
|
387
391
|
# delete flag for Connect Client
|
388
392
|
transfer_spec.delete('authentication')
|
@@ -400,7 +404,7 @@ module Aspera
|
|
400
404
|
# browse a folder
|
401
405
|
# @param browse_endpoint [String] the endpoint to browse
|
402
406
|
def browse_folder(browse_endpoint)
|
403
|
-
|
407
|
+
folders_to_process = [options.get_next_argument('folder path', mandatory: false, default: '/')]
|
404
408
|
query = query_read_delete(default: {})
|
405
409
|
query['filters'] = {} unless query.key?('filters')
|
406
410
|
filters = query.delete('filters')
|
@@ -409,17 +413,16 @@ module Aspera
|
|
409
413
|
max_items = query.delete('max')
|
410
414
|
recursive = query.delete('recursive')
|
411
415
|
all_items = []
|
412
|
-
folders_to_process = [path]
|
413
416
|
until folders_to_process.empty?
|
414
417
|
path = folders_to_process.shift
|
415
|
-
query.delete('iteration_token')
|
416
418
|
loop do
|
417
419
|
response = @api_v5.call(
|
418
420
|
operation: 'POST',
|
419
421
|
subpath: browse_endpoint,
|
420
|
-
headers: {'Accept' => 'application/json'
|
421
|
-
|
422
|
-
|
422
|
+
headers: {'Accept' => 'application/json'},
|
423
|
+
query: query,
|
424
|
+
body: {'path' => path, 'filters' => filters},
|
425
|
+
body_type: :json)
|
423
426
|
all_items.concat(response[:data]['items'])
|
424
427
|
if recursive
|
425
428
|
folders_to_process.concat(response[:data]['items'].select{|i|i['type'].eql?('directory')}.map{|i|i['path']})
|
@@ -431,7 +434,9 @@ module Aspera
|
|
431
434
|
iteration_token = response[:http][HEADER_ITERATION_TOKEN]
|
432
435
|
break if iteration_token.nil? || iteration_token.empty?
|
433
436
|
query['iteration_token'] = iteration_token
|
437
|
+
formatter.long_operation_running(all_items.count)
|
434
438
|
end
|
439
|
+
query.delete('iteration_token')
|
435
440
|
end
|
436
441
|
return {type: :object_list, data: all_items}
|
437
442
|
end
|
@@ -459,9 +464,14 @@ module Aspera
|
|
459
464
|
ids = package_id
|
460
465
|
ids = [ids] unless ids.is_a?(Array)
|
461
466
|
Aspera.assert_type(ids, Array){'Package identifier'}
|
462
|
-
Aspera.assert(ids.all?(String)){
|
467
|
+
Aspera.assert(ids.all?(String)){"Package id(s) shall be String, but have: #{ids.map(&:class).uniq.join(', ')}"}
|
463
468
|
# API returns 204, empty on success
|
464
|
-
@api_v5.call(
|
469
|
+
@api_v5.call(
|
470
|
+
operation: 'DELETE',
|
471
|
+
subpath: 'packages',
|
472
|
+
headers: {'Accept' => 'application/json'},
|
473
|
+
body: {ids: ids},
|
474
|
+
body_type: :json)
|
465
475
|
return Main.result_status('Package(s) deleted')
|
466
476
|
when :receive
|
467
477
|
return package_receive(package_id)
|
@@ -483,8 +493,9 @@ module Aspera
|
|
483
493
|
operation: 'POST',
|
484
494
|
subpath: "packages/#{package['id']}/transfer_spec/upload",
|
485
495
|
headers: {'Accept' => 'application/json'},
|
486
|
-
|
487
|
-
|
496
|
+
query: {transfer_type: TRANSFER_CONNECT},
|
497
|
+
body: {paths: transfer.source_list},
|
498
|
+
body_type: :json
|
488
499
|
)[:data]
|
489
500
|
# well, we asked a TS for connect, but we actually want a generic one
|
490
501
|
transfer_spec.delete('authentication')
|
@@ -492,7 +503,10 @@ module Aspera
|
|
492
503
|
else
|
493
504
|
# send from remote shared folder
|
494
505
|
if (m = shared_folder.match(REGEX_LOOKUP_ID_BY_FIELD))
|
495
|
-
shared_folder = lookup_entity_by_field(
|
506
|
+
shared_folder = lookup_entity_by_field(
|
507
|
+
type: 'shared_folders',
|
508
|
+
field: m[1],
|
509
|
+
value: ExtendedValue.instance.evaluate(m[2]))['id']
|
496
510
|
end
|
497
511
|
transfer_request = {shared_folder_id: shared_folder, paths: transfer.source_list}
|
498
512
|
# start remote transfer and get first status
|
@@ -510,7 +524,174 @@ module Aspera
|
|
510
524
|
data: list_packages_with_filter,
|
511
525
|
fields: %w[id title release_date total_bytes total_files created_time state]
|
512
526
|
}
|
513
|
-
end
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
def execute_resource(res_type)
|
531
|
+
list_key = res_path = res_type.to_s
|
532
|
+
id_as_arg = false
|
533
|
+
display_fields = nil
|
534
|
+
adm_api = @api_v5
|
535
|
+
res_id_query = :default
|
536
|
+
delete_style = nil
|
537
|
+
available_commands = [].concat(Plugin::ALL_OPS)
|
538
|
+
case res_type
|
539
|
+
when :metadata_profiles
|
540
|
+
res_path = 'configuration/metadata_profiles'
|
541
|
+
list_key = 'profiles'
|
542
|
+
when :alternate_addresses
|
543
|
+
res_path = 'configuration/alternate_addresses'
|
544
|
+
when :distribution_lists
|
545
|
+
res_path = 'account/distribution_lists'
|
546
|
+
list_key = 'distribution_lists'
|
547
|
+
delete_style = 'ids'
|
548
|
+
when :email_notifications
|
549
|
+
list_key = false
|
550
|
+
id_as_arg = 'type'
|
551
|
+
when :accounts
|
552
|
+
display_fields = Formatter.all_but('user_profile_data_attributes')
|
553
|
+
when :oauth_clients
|
554
|
+
display_fields = Formatter.all_but('public_key')
|
555
|
+
adm_api = Rest.new(**@api_v5.params.merge(base_url: "#{@faspex5_api_base_url}/#{PATH_AUTH}"))
|
556
|
+
when :shared_inboxes, :workgroups
|
557
|
+
available_commands.push(:members, :saml_groups, :invite_external_collaborator)
|
558
|
+
res_id_query = {'all': true}
|
559
|
+
when :nodes
|
560
|
+
available_commands.push(:shared_folders, :browse)
|
561
|
+
end
|
562
|
+
res_command = options.get_next_command(available_commands)
|
563
|
+
case res_command
|
564
|
+
when *Plugin::ALL_OPS
|
565
|
+
return entity_command(res_command, adm_api, res_path, item_list_key: list_key, display_fields: display_fields, id_as_arg: id_as_arg, delete_style: delete_style) do |field, value|
|
566
|
+
lookup_entity_by_field(
|
567
|
+
type: res_type, value: value, field: field, real_path: res_path, item_list_key: list_key, query: res_id_query)['id']
|
568
|
+
end
|
569
|
+
when :shared_folders
|
570
|
+
node_id = instance_identifier do |field, value|
|
571
|
+
lookup_entity_by_field(type: res_type, field: field, value: value)['id']
|
572
|
+
end
|
573
|
+
sh_path = "#{res_path}/#{node_id}/shared_folders"
|
574
|
+
sh_command = options.get_next_command([:user].concat(Plugin::ALL_OPS))
|
575
|
+
case sh_command
|
576
|
+
when *Plugin::ALL_OPS
|
577
|
+
return entity_command(sh_command, adm_api, sh_path, item_list_key: 'shared_folders') do |field, value|
|
578
|
+
lookup_entity_by_field(type: 'shared_folders', real_path: sh_path, field: field, value: value)['id']
|
579
|
+
end
|
580
|
+
when :user
|
581
|
+
sh_id = instance_identifier do |field, value|
|
582
|
+
lookup_entity_by_field(type: 'shared_folders', real_path: sh_path, field: field, value: value)['id']
|
583
|
+
end
|
584
|
+
user_path = "#{sh_path}/#{sh_id}/custom_access_users"
|
585
|
+
return entity_action(adm_api, user_path, item_list_key: 'users') do |field, value|
|
586
|
+
lookup_entity_by_field(type: 'users', real_path: user_path, field: field, value: value)['id']
|
587
|
+
end
|
588
|
+
|
589
|
+
end
|
590
|
+
when :browse
|
591
|
+
return browse_folder("#{res_path}/#{instance_identifier}/browse")
|
592
|
+
when :invite_external_collaborator
|
593
|
+
shared_inbox_id = instance_identifier { |field, value| lookup_entity_by_field(type: res_type.to_s, field: field, value: value, query: res_id_query)['id']}
|
594
|
+
creation_payload = value_create_modify(command: res_command, type: [Hash, String])
|
595
|
+
creation_payload = {'email_address' => creation_payload} if creation_payload.is_a?(String)
|
596
|
+
res_path = "#{res_type}/#{shared_inbox_id}/external_collaborator"
|
597
|
+
result = adm_api.create(res_path, creation_payload)[:data]
|
598
|
+
formatter.display_status(result['message'])
|
599
|
+
result = lookup_entity_by_field(
|
600
|
+
type: 'members',
|
601
|
+
real_path: "#{res_type}/#{shared_inbox_id}/members",
|
602
|
+
value: creation_payload['email_address'],
|
603
|
+
query: {})
|
604
|
+
return {type: :single_object, data: result}
|
605
|
+
when :members, :saml_groups
|
606
|
+
res_id = instance_identifier { |field, value| lookup_entity_by_field(type: res_type.to_s, field: field, value: value, query: res_id_query)['id']}
|
607
|
+
res_prefix = "#{res_type}/#{res_id}"
|
608
|
+
res_path = "#{res_prefix}/#{res_command}"
|
609
|
+
list_key = res_command.to_s
|
610
|
+
list_key = 'groups' if res_command.eql?(:saml_groups)
|
611
|
+
sub_command = options.get_next_command(%i[create list modify delete])
|
612
|
+
if sub_command.eql?(:create) && options.get_option(:value).nil?
|
613
|
+
raise "use option 'value' to provide saml group_id and access (refer to API)" unless res_command.eql?(:members)
|
614
|
+
# first arg is one user name or list of users
|
615
|
+
users = options.get_next_argument('user id, %name:, or Array')
|
616
|
+
users = [users] unless users.is_a?(Array)
|
617
|
+
users = users.map do |user|
|
618
|
+
if (m = user.match(REGEX_LOOKUP_ID_BY_FIELD))
|
619
|
+
lookup_entity_by_field(
|
620
|
+
type: 'accounts',
|
621
|
+
field: m[1],
|
622
|
+
value: ExtendedValue.instance.evaluate(m[2]),
|
623
|
+
query: {type: Rest.array_params(%w{local_user saml_user self_registered_user external_user})})['id']
|
624
|
+
else
|
625
|
+
# it's the user id (not member id...)
|
626
|
+
user
|
627
|
+
end
|
628
|
+
end
|
629
|
+
access = options.get_next_argument('level', mandatory: false, expected: %i[submit_only standard shared_inbox_admin], default: :standard)
|
630
|
+
# TODO: unshift to command line parameters instead of using deprecated option "value"
|
631
|
+
options.set_option(:value, {user: users.map{|u|{id: u, access: access}}})
|
632
|
+
end
|
633
|
+
return entity_command(sub_command, adm_api, res_path, item_list_key: list_key) do |field, value|
|
634
|
+
lookup_entity_by_field(
|
635
|
+
type: 'accounts',
|
636
|
+
field: field,
|
637
|
+
value: value,
|
638
|
+
query: {type: Rest.array_params(%w{local_user saml_user self_registered_user external_user})})['id']
|
639
|
+
end
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
643
|
+
def execute_admin
|
644
|
+
command = options.get_next_command(%i[configuration smtp resource events clean_deleted].concat(ADMIN_RESOURCES).freeze)
|
645
|
+
case command
|
646
|
+
when :resource
|
647
|
+
# resource is will be deprecated
|
648
|
+
Log.log.warn('resource command is deprecated (4.18), directly use the specific command instead')
|
649
|
+
return execute_resource(options.get_next_command(ADMIN_RESOURCES))
|
650
|
+
when *ADMIN_RESOURCES
|
651
|
+
return execute_resource(command)
|
652
|
+
when :clean_deleted
|
653
|
+
delete_data = value_create_modify(command: command, default: {days_before_deleting_package_records: 365})
|
654
|
+
res = @api_v5.create('internal/packages/clean_deleted', delete_data)
|
655
|
+
return {type: :single_object, data: res[:data]}
|
656
|
+
when :events
|
657
|
+
event_type = options.get_next_command(%i[application webhook])
|
658
|
+
case event_type
|
659
|
+
when :application
|
660
|
+
return {type: :object_list, data: list_entities(type: 'application_events'), fields: %w[event_type created_at application user.name]}
|
661
|
+
when :webhook
|
662
|
+
return {type: :object_list, data: list_entities(type: 'all_webhooks_events', item_list_key: 'events')}
|
663
|
+
end
|
664
|
+
when :configuration
|
665
|
+
conf_path = 'configuration'
|
666
|
+
conf_cmd = options.get_next_command(%i[show modify])
|
667
|
+
case conf_cmd
|
668
|
+
when :show
|
669
|
+
return { type: :single_object, data: @api_v5.read(conf_path)[:data] }
|
670
|
+
when :modify
|
671
|
+
return { type: :single_object, data: @api_v5.update(conf_path, value_create_modify(command: conf_cmd))[:data] }
|
672
|
+
end
|
673
|
+
when :smtp
|
674
|
+
smtp_path = 'configuration/smtp'
|
675
|
+
smtp_cmd = options.get_next_command(%i[show create modify delete test])
|
676
|
+
case smtp_cmd
|
677
|
+
when :show
|
678
|
+
return { type: :single_object, data: @api_v5.read(smtp_path)[:data] }
|
679
|
+
when :create
|
680
|
+
return { type: :single_object, data: @api_v5.create(smtp_path, value_create_modify(command: smtp_cmd))[:data] }
|
681
|
+
when :modify
|
682
|
+
return { type: :single_object, data: @api_v5.update(smtp_path, value_create_modify(command: smtp_cmd))[:data] }
|
683
|
+
when :delete
|
684
|
+
@api_v5.delete(smtp_path)[:data]
|
685
|
+
return Main.result_status('SMTP configuration deleted')
|
686
|
+
when :test
|
687
|
+
test_data = options.get_next_argument('Email or test data, see API')
|
688
|
+
test_data = {test_email_recipient: test_data} if test_data.is_a?(String)
|
689
|
+
creation = @api_v5.create(File.join(smtp_path, 'test'), test_data)[:data]
|
690
|
+
result = wait_for_job(creation['job_id'])
|
691
|
+
result['serialized_args'] = JSON.parse(result['serialized_args']) rescue result['serialized_args']
|
692
|
+
return { type: :single_object, data: result }
|
693
|
+
end
|
694
|
+
end
|
514
695
|
end
|
515
696
|
|
516
697
|
ACTIONS = %i[health version user bearer_token packages shared_folders admin gateway postprocessing invitations].freeze
|
@@ -546,7 +727,7 @@ module Aspera
|
|
546
727
|
end
|
547
728
|
end
|
548
729
|
when :bearer_token
|
549
|
-
return {type: :text, data: @api_v5.
|
730
|
+
return {type: :text, data: @api_v5.oauth.token}
|
550
731
|
when :packages
|
551
732
|
return package_action
|
552
733
|
when :shared_folders
|
@@ -566,117 +747,7 @@ module Aspera
|
|
566
747
|
return browse_folder("nodes/#{node['node_id']}/shared_folders/#{shared_folder_id}/browse")
|
567
748
|
end
|
568
749
|
when :admin
|
569
|
-
|
570
|
-
when :resource
|
571
|
-
res_type = options.get_next_command(ADMIN_RESOURCES)
|
572
|
-
res_path = list_key = res_type.to_s
|
573
|
-
id_as_arg = false
|
574
|
-
display_fields = nil
|
575
|
-
adm_api = @api_v5
|
576
|
-
special_query = :default
|
577
|
-
available_commands = [].concat(Plugin::ALL_OPS)
|
578
|
-
case res_type
|
579
|
-
when :metadata_profiles
|
580
|
-
res_path = 'configuration/metadata_profiles'
|
581
|
-
list_key = 'profiles'
|
582
|
-
when :alternate_addresses
|
583
|
-
res_path = 'configuration/alternate_addresses'
|
584
|
-
when :email_notifications
|
585
|
-
list_key = false
|
586
|
-
id_as_arg = 'type'
|
587
|
-
when :accounts
|
588
|
-
display_fields = Formatter.all_but('user_profile_data_attributes')
|
589
|
-
when :oauth_clients
|
590
|
-
display_fields = Formatter.all_but('public_key')
|
591
|
-
adm_api = Rest.new(**@api_v5.params.merge(base_url: "#{@faspex5_api_base_url}/#{PATH_AUTH}"))
|
592
|
-
when :shared_inboxes, :workgroups
|
593
|
-
available_commands.push(:members, :saml_groups, :invite_external_collaborator)
|
594
|
-
special_query = {'all': true}
|
595
|
-
when :nodes
|
596
|
-
available_commands.push(:shared_folders, :browse)
|
597
|
-
end
|
598
|
-
res_command = options.get_next_command(available_commands)
|
599
|
-
case res_command
|
600
|
-
when *Plugin::ALL_OPS
|
601
|
-
return entity_command(res_command, adm_api, res_path, item_list_key: list_key, display_fields: display_fields, id_as_arg: id_as_arg) do |field, value|
|
602
|
-
lookup_entity_by_field(
|
603
|
-
type: res_type, real_path: res_path, field: field, value: value, query: special_query)['id']
|
604
|
-
end
|
605
|
-
when :shared_folders
|
606
|
-
node_id = instance_identifier do |field, value|
|
607
|
-
lookup_entity_by_field(type: res_type.to_s, field: field, value: value)['id']
|
608
|
-
end
|
609
|
-
sh_path = "#{res_path}/#{node_id}/shared_folders"
|
610
|
-
return entity_action(adm_api, sh_path, item_list_key: 'shared_folders') do |field, value|
|
611
|
-
lookup_entity_by_field(
|
612
|
-
type: 'shared_folders', real_path: sh_path, field: field, value: value)['id']
|
613
|
-
end
|
614
|
-
when :browse
|
615
|
-
return browse_folder("#{res_path}/#{instance_identifier}/browse")
|
616
|
-
when :invite_external_collaborator
|
617
|
-
shared_inbox_id = instance_identifier { |field, value| lookup_entity_by_field(type: res_type.to_s, field: field, value: value)['id']}
|
618
|
-
creation_payload = value_create_modify(command: res_command, type: [Hash, String])
|
619
|
-
creation_payload = {'email_address' => creation_payload} if creation_payload.is_a?(String)
|
620
|
-
res_path = "#{res_type}/#{shared_inbox_id}/external_collaborator"
|
621
|
-
result = adm_api.create(res_path, creation_payload)[:data]
|
622
|
-
formatter.display_status(result['message'])
|
623
|
-
result = lookup_entity_by_field(
|
624
|
-
type: 'members', real_path: "#{res_type}/#{shared_inbox_id}/members", value: creation_payload['email_address'],
|
625
|
-
query: {})
|
626
|
-
return {type: :single_object, data: result}
|
627
|
-
when :members, :saml_groups
|
628
|
-
res_id = instance_identifier { |field, value| lookup_entity_by_field(type: res_type.to_s, field: field, value: value)['id']}
|
629
|
-
res_prefix = "#{res_type}/#{res_id}"
|
630
|
-
res_path = "#{res_prefix}/#{res_command}"
|
631
|
-
list_key = res_command.to_s
|
632
|
-
list_key = 'groups' if res_command.eql?(:saml_groups)
|
633
|
-
sub_command = options.get_next_command(%i[create list modify delete])
|
634
|
-
if sub_command.eql?(:create) && options.get_option(:value).nil?
|
635
|
-
raise "use option 'value' to provide saml group_id and access (refer to API)" unless res_command.eql?(:members)
|
636
|
-
# first arg is one user name or list of users
|
637
|
-
users = options.get_next_argument('user id, or email, or list of')
|
638
|
-
users = [users] unless users.is_a?(Array)
|
639
|
-
users = users.map do |user|
|
640
|
-
if (m = user.match(REGEX_LOOKUP_ID_BY_FIELD))
|
641
|
-
lookup_entity_by_field(
|
642
|
-
type: 'accounts', field: m[1], value: m[2],
|
643
|
-
query: {type: Rest.array_params(%w{local_user saml_user self_registered_user external_user})})['id']
|
644
|
-
else
|
645
|
-
# it's the user id (not member id...)
|
646
|
-
user
|
647
|
-
end
|
648
|
-
end
|
649
|
-
access = options.get_next_argument('level', mandatory: false, expected: %i[submit_only standard shared_inbox_admin], default: :standard)
|
650
|
-
# TODO: unshift to command line parameters instead of using deprecated option "value"
|
651
|
-
options.set_option(:value, {user: users.map{|u|{id: u, access: access}}})
|
652
|
-
end
|
653
|
-
return entity_command(sub_command, adm_api, res_path, item_list_key: list_key) do |field, value|
|
654
|
-
lookup_entity_by_field(
|
655
|
-
type: 'accounts', field: field, value: value,
|
656
|
-
query: {type: Rest.array_params(%w{local_user saml_user self_registered_user external_user})})['id']
|
657
|
-
end
|
658
|
-
end
|
659
|
-
when :smtp
|
660
|
-
smtp_path = 'configuration/smtp'
|
661
|
-
smtp_cmd = options.get_next_command(%i[show create modify delete test])
|
662
|
-
case smtp_cmd
|
663
|
-
when :show
|
664
|
-
return { type: :single_object, data: @api_v5.read(smtp_path)[:data] }
|
665
|
-
when :create
|
666
|
-
return { type: :single_object, data: @api_v5.create(smtp_path, value_create_modify(command: smtp_cmd))[:data] }
|
667
|
-
when :modify
|
668
|
-
return { type: :single_object, data: @api_v5.update(smtp_path, value_create_modify(command: smtp_cmd))[:data] }
|
669
|
-
when :delete
|
670
|
-
return { type: :single_object, data: @api_v5.delete(smtp_path)[:data] }
|
671
|
-
when :test
|
672
|
-
test_data = options.get_next_argument('Email or test data, see API')
|
673
|
-
test_data = {test_email_recipient: test_data} if test_data.is_a?(String)
|
674
|
-
creation = @api_v5.create(File.join(smtp_path, 'test'), test_data)[:data]
|
675
|
-
result = wait_for_job(creation['job_id'])
|
676
|
-
result['serialized_args'] = JSON.parse(result['serialized_args']) rescue result['serialized_args']
|
677
|
-
return { type: :single_object, data: result }
|
678
|
-
end
|
679
|
-
end
|
750
|
+
return execute_admin
|
680
751
|
when :invitations
|
681
752
|
invitation_endpoint = 'invitations'
|
682
753
|
invitation_command = options.get_next_command(%i[resend].concat(Plugin::ALL_OPS))
|
@@ -692,7 +763,9 @@ module Aspera
|
|
692
763
|
else
|
693
764
|
return entity_command(
|
694
765
|
invitation_command, @api_v5, invitation_endpoint, item_list_key: invitation_endpoint,
|
695
|
-
display_fields: %w[id public recipient_type recipient_name email_address])
|
766
|
+
display_fields: %w[id public recipient_type recipient_name email_address]) do |field, value|
|
767
|
+
lookup_entity_by_field(type: invitation_endpoint, field: field, value: value, query: {})['id']
|
768
|
+
end
|
696
769
|
end
|
697
770
|
when :gateway
|
698
771
|
require 'aspera/faspex_gw'
|
@@ -714,9 +787,9 @@ module Aspera
|
|
714
787
|
server.mount(uri.path, Faspex4PostProcServlet, parameters[:processing])
|
715
788
|
server.start
|
716
789
|
return Main.result_status('Gateway terminated')
|
717
|
-
end
|
718
|
-
end
|
719
|
-
end
|
720
|
-
end
|
721
|
-
end
|
722
|
-
end
|
790
|
+
end
|
791
|
+
end
|
792
|
+
end
|
793
|
+
end
|
794
|
+
end
|
795
|
+
end
|