aspera-cli 4.12.0 → 4.14.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 +45 -5
- data/CONTRIBUTING.md +113 -22
- data/README.md +1289 -754
- data/bin/ascli +3 -3
- data/examples/dascli +1 -1
- data/examples/rubyc +24 -0
- data/lib/aspera/aoc.rb +63 -74
- data/lib/aspera/ascmd.rb +5 -3
- data/lib/aspera/cli/basic_auth_plugin.rb +6 -6
- data/lib/aspera/cli/extended_value.rb +24 -37
- data/lib/aspera/cli/formatter.rb +23 -25
- data/lib/aspera/cli/info.rb +2 -4
- data/lib/aspera/cli/main.rb +27 -27
- data/lib/aspera/cli/manager.rb +143 -120
- data/lib/aspera/cli/plugin.rb +88 -43
- data/lib/aspera/cli/plugins/alee.rb +2 -2
- data/lib/aspera/cli/plugins/aoc.rb +235 -104
- data/lib/aspera/cli/plugins/ats.rb +16 -18
- data/lib/aspera/cli/plugins/bss.rb +3 -3
- data/lib/aspera/cli/plugins/config.rb +190 -373
- data/lib/aspera/cli/plugins/console.rb +4 -6
- data/lib/aspera/cli/plugins/cos.rb +12 -13
- data/lib/aspera/cli/plugins/faspex.rb +21 -21
- data/lib/aspera/cli/plugins/faspex5.rb +399 -150
- data/lib/aspera/cli/plugins/node.rb +260 -174
- data/lib/aspera/cli/plugins/orchestrator.rb +15 -18
- data/lib/aspera/cli/plugins/preview.rb +40 -62
- data/lib/aspera/cli/plugins/server.rb +33 -16
- data/lib/aspera/cli/plugins/shares.rb +24 -33
- data/lib/aspera/cli/plugins/sync.rb +6 -6
- data/lib/aspera/cli/transfer_agent.rb +47 -30
- data/lib/aspera/cli/version.rb +2 -1
- data/lib/aspera/colors.rb +9 -7
- data/lib/aspera/command_line_builder.rb +2 -1
- data/lib/aspera/cos_node.rb +1 -1
- data/lib/aspera/data/6 +0 -0
- data/lib/aspera/environment.rb +7 -3
- data/lib/aspera/fasp/agent_connect.rb +6 -1
- data/lib/aspera/fasp/agent_direct.rb +17 -17
- data/lib/aspera/fasp/agent_httpgw.rb +138 -60
- data/lib/aspera/fasp/agent_node.rb +14 -4
- data/lib/aspera/fasp/agent_trsdk.rb +2 -0
- data/lib/aspera/fasp/error_info.rb +2 -0
- data/lib/aspera/fasp/installation.rb +19 -19
- data/lib/aspera/fasp/parameters.rb +29 -20
- data/lib/aspera/fasp/parameters.yaml +5 -2
- data/lib/aspera/fasp/resume_policy.rb +3 -3
- data/lib/aspera/fasp/transfer_spec.rb +8 -5
- data/lib/aspera/fasp/uri.rb +23 -21
- data/lib/aspera/faspex_gw.rb +1 -0
- data/lib/aspera/faspex_postproc.rb +3 -3
- data/lib/aspera/hash_ext.rb +12 -2
- data/lib/aspera/keychain/macos_security.rb +13 -13
- data/lib/aspera/log.rb +1 -0
- data/lib/aspera/node.rb +73 -84
- data/lib/aspera/oauth.rb +4 -3
- data/lib/aspera/persistency_action_once.rb +1 -1
- data/lib/aspera/preview/file_types.rb +8 -6
- data/lib/aspera/preview/generator.rb +23 -11
- data/lib/aspera/preview/options.rb +3 -2
- data/lib/aspera/preview/terminal.rb +80 -0
- data/lib/aspera/preview/utils.rb +11 -11
- data/lib/aspera/proxy_auto_config.js +2 -2
- data/lib/aspera/rest.rb +42 -4
- data/lib/aspera/rest_call_error.rb +3 -1
- data/lib/aspera/secret_hider.rb +10 -5
- data/lib/aspera/ssh.rb +1 -1
- data/lib/aspera/sync.rb +41 -33
- data/lib/aspera/web_server_simple.rb +22 -18
- data.tar.gz.sig +0 -0
- metadata +40 -48
- metadata.gz.sig +0 -0
- data/docs/test_env.conf +0 -179
- data/examples/aoc.rb +0 -30
- data/examples/faspex4.rb +0 -94
- data/examples/node.rb +0 -96
- data/examples/server.rb +0 -93
- data/lib/aspera/data/7 +0 -0
@@ -23,7 +23,10 @@ module Aspera
|
|
23
23
|
# either in standard domain, or product name in page
|
24
24
|
if URI.parse(base_url).host.end_with?(Aspera::AoC::PROD_DOMAIN) ||
|
25
25
|
api.call({operation: 'GET', redirect_max: 1, headers: {'Accept' => 'text/html'}})[:http].body.include?(Aspera::AoC::PRODUCT_NAME)
|
26
|
-
return {
|
26
|
+
return {
|
27
|
+
version: 'SaaS',
|
28
|
+
name: 'Aspera on Cloud'
|
29
|
+
}
|
27
30
|
end
|
28
31
|
return nil
|
29
32
|
end
|
@@ -50,6 +53,7 @@ module Aspera
|
|
50
53
|
client_registration_token
|
51
54
|
client_access_key
|
52
55
|
kms_profile].freeze
|
56
|
+
# TODO: remove this and use %name: instead
|
53
57
|
ENTITY_NAME_SPECIFIER = 'name'
|
54
58
|
PACKAGE_QUERY_DEFAULT = {'archived' => false, 'exclude_dropbox_packages' => true, 'has_content' => true, 'received' => true}.freeze
|
55
59
|
|
@@ -58,28 +62,23 @@ module Aspera
|
|
58
62
|
@cache_workspace_info = nil
|
59
63
|
@cache_home_node_file = nil
|
60
64
|
@cache_api_aoc = nil
|
61
|
-
options.
|
62
|
-
options.
|
63
|
-
options.
|
64
|
-
options.
|
65
|
-
options.
|
66
|
-
options.
|
67
|
-
options.
|
68
|
-
options.
|
69
|
-
options.
|
70
|
-
|
71
|
-
options.
|
72
|
-
options.
|
73
|
-
options.
|
74
|
-
options.
|
75
|
-
options.
|
76
|
-
options.set_option(:operation, :push)
|
77
|
-
options.set_option(:auth, :jwt)
|
78
|
-
options.set_option(:scope, AoC::SCOPE_FILES_USER)
|
79
|
-
options.set_option(:private_key, '@file:' + env[:private_key_path]) if env[:private_key_path].is_a?(String)
|
80
|
-
options.set_option(:workspace, :default)
|
65
|
+
options.declare(:auth, 'OAuth type of authentication', values: Oauth::STD_AUTH_TYPES, default: :jwt)
|
66
|
+
options.declare(:operation, 'Client operation for transfers', values: %i[push pull], default: :push)
|
67
|
+
options.declare(:client_id, 'OAuth API client identifier')
|
68
|
+
options.declare(:client_secret, 'OAuth API client secret')
|
69
|
+
options.declare(:redirect_uri, 'OAuth API client redirect URI')
|
70
|
+
options.declare(:private_key, 'OAuth JWT RSA private key PEM value (prefix file path with @file:)')
|
71
|
+
options.declare(:scope, 'OAuth scope for AoC API calls', default: AoC::SCOPE_FILES_USER)
|
72
|
+
options.declare(:passphrase, 'RSA private key passphrase')
|
73
|
+
options.declare(:workspace, 'Name of workspace', default: :default)
|
74
|
+
# TODO: remove this and use %name: instead
|
75
|
+
options.declare(:name, "Resource name (prefer to use keyword #{ENTITY_NAME_SPECIFIER})")
|
76
|
+
options.declare(:link, 'Public link to shared resource')
|
77
|
+
options.declare(:new_user_option, 'New user creation option for unknown package recipients')
|
78
|
+
options.declare(:from_folder, 'Source folder for Folder-to-Folder transfer')
|
79
|
+
options.declare(:validate_metadata, 'Validate shared inbox metadata', values: :bool, default: true)
|
81
80
|
options.parse_options!
|
82
|
-
# add node plugin options
|
81
|
+
# add node plugin options (TODO: check needed ? if yes, tell why)
|
83
82
|
Node.new(env.merge({man_only: true, skip_basic_auth_options: true}))
|
84
83
|
end
|
85
84
|
|
@@ -114,7 +113,7 @@ module Aspera
|
|
114
113
|
Log.log.debug('Using default workspace'.green)
|
115
114
|
raise CliError, 'No default workspace defined for user, please specify workspace' if default_workspace_id.nil?
|
116
115
|
default_workspace_id
|
117
|
-
when String then aoc_api.
|
116
|
+
when String then aoc_api.lookup_by_name('workspaces', ws_name)['id']
|
118
117
|
when NilClass then nil
|
119
118
|
else raise CliError, 'unexpected value type for workspace'
|
120
119
|
end
|
@@ -142,6 +141,13 @@ module Aspera
|
|
142
141
|
end
|
143
142
|
home_node_id ||= current_workspace_info['home_node_id'] || current_workspace_info['node_id']
|
144
143
|
home_file_id ||= current_workspace_info['home_file_id']
|
144
|
+
if home_node_id.to_s.empty?
|
145
|
+
# not part of any workspace, but has some folder shared
|
146
|
+
user_info = aoc_api.current_user_info(exception: true)
|
147
|
+
home_node_id = user_info['read_only_home_node_id']
|
148
|
+
home_file_id = user_info['read_only_home_file_id']
|
149
|
+
end
|
150
|
+
|
145
151
|
raise "Cannot get user's home node id, check your default workspace or specify one" if home_node_id.to_s.empty?
|
146
152
|
@cache_home_node_file = {
|
147
153
|
node_id: home_node_id,
|
@@ -157,11 +163,11 @@ module Aspera
|
|
157
163
|
l_res_name = options.get_option(:name)
|
158
164
|
raise 'Provide either option id or name, not both' unless l_res_id.nil? || l_res_name.nil?
|
159
165
|
# try to find item by name (single partial match or exact match)
|
160
|
-
l_res_id = aoc_api.
|
166
|
+
l_res_id = aoc_api.lookup_by_name(resource_class_path, l_res_name)['id'] unless l_res_name.nil?
|
161
167
|
# if no name or id option, taken on command line (after command)
|
162
168
|
if l_res_id.nil?
|
163
169
|
l_res_id = options.get_next_argument('identifier')
|
164
|
-
l_res_id = aoc_api.
|
170
|
+
l_res_id = aoc_api.lookup_by_name(resource_class_path, options.get_next_argument('identifier'))['id'] if l_res_id.eql?(ENTITY_NAME_SPECIFIER)
|
165
171
|
end
|
166
172
|
return l_res_id
|
167
173
|
end
|
@@ -214,7 +220,12 @@ module Aspera
|
|
214
220
|
# @param file_id [String] root file id for the operation (can be AK root, or other, e.g. package, or link)
|
215
221
|
# @param scope [String] node scope, or nil (admin)
|
216
222
|
def execute_nodegen4_command(command_repo, node_id, file_id: nil, scope: nil)
|
217
|
-
top_node_api = aoc_api.node_api_from(
|
223
|
+
top_node_api = aoc_api.node_api_from(
|
224
|
+
node_id: node_id,
|
225
|
+
workspace_id: current_workspace_info['id'],
|
226
|
+
workspace_name: current_workspace_info['name'],
|
227
|
+
scope: scope
|
228
|
+
)
|
218
229
|
file_id = top_node_api.read("access_keys/#{top_node_api.app_info[:node_info]['access_key']}")[:data]['root_file_id'] if file_id.nil?
|
219
230
|
node_plugin = Node.new(@agents.merge(
|
220
231
|
skip_basic_auth_options: true,
|
@@ -228,15 +239,15 @@ module Aspera
|
|
228
239
|
# server side is protocol server
|
229
240
|
# in same workspace
|
230
241
|
# default is push
|
231
|
-
case options.get_option(:operation,
|
242
|
+
case options.get_option(:operation, mandatory: true)
|
232
243
|
when :push
|
233
244
|
client_direction = Fasp::TransferSpec::DIRECTION_SEND
|
234
|
-
client_folder = options.get_option(:from_folder,
|
245
|
+
client_folder = options.get_option(:from_folder, mandatory: true)
|
235
246
|
server_folder = transfer.destination_folder(client_direction)
|
236
247
|
when :pull
|
237
248
|
client_direction = Fasp::TransferSpec::DIRECTION_RECEIVE
|
238
249
|
client_folder = transfer.destination_folder(client_direction)
|
239
|
-
server_folder = options.get_option(:from_folder,
|
250
|
+
server_folder = options.get_option(:from_folder, mandatory: true)
|
240
251
|
end
|
241
252
|
client_apfid = top_node_api.resolve_api_fid(file_id, client_folder)
|
242
253
|
server_apfid = top_node_api.resolve_api_fid(file_id, server_folder)
|
@@ -359,12 +370,12 @@ module Aspera
|
|
359
370
|
filter = options.get_option(:query) || {}
|
360
371
|
raise 'query must be Hash' unless filter.is_a?(Hash)
|
361
372
|
filter['limit'] ||= 100
|
362
|
-
if options.get_option(:once_only,
|
373
|
+
if options.get_option(:once_only, mandatory: true)
|
363
374
|
saved_date = []
|
364
375
|
start_date_persistency = PersistencyActionOnce.new(
|
365
376
|
manager: @agents[:persistency],
|
366
377
|
data: saved_date,
|
367
|
-
ids: IdGenerator.from_list(['aoc_ana_date', options.get_option(:url,
|
378
|
+
ids: IdGenerator.from_list(['aoc_ana_date', options.get_option(:url, mandatory: true), current_workspace_info['name']].push(
|
368
379
|
filter_resource,
|
369
380
|
filter_id)))
|
370
381
|
start_date_time = saved_date.first
|
@@ -375,7 +386,7 @@ module Aspera
|
|
375
386
|
filter['start_time'] = start_date_time unless start_date_time.nil?
|
376
387
|
filter['stop_time'] = stop_date_time
|
377
388
|
end
|
378
|
-
events = analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",
|
389
|
+
events = analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}", query_read_delete(default: filter))[:data][event_type]
|
379
390
|
start_date_persistency&.save
|
380
391
|
if !options.get_option(:notif_to).nil?
|
381
392
|
events.each do |tr_event|
|
@@ -439,10 +450,8 @@ module Aspera
|
|
439
450
|
when :group_membership then default_fields.push(*%w[group_id member_type member_id])
|
440
451
|
when :workspace_membership then default_fields.push(*%w[workspace_id member_type member_id])
|
441
452
|
end
|
442
|
-
items = read_with_paging(resource_class_path,
|
443
|
-
|
444
|
-
count_msg = count_msg.bg_red unless items[:list].length.eql?(items[:total].to_i)
|
445
|
-
formatter.display_status(count_msg)
|
453
|
+
items = read_with_paging(resource_class_path, query_read_delete(default: default_query))
|
454
|
+
formatter.display_item_count(items[:list].length, items[:total])
|
446
455
|
return {type: :object_list, data: items[:list], fields: default_fields}
|
447
456
|
when :show
|
448
457
|
object = aoc_api.read(resource_instance_path)[:data]
|
@@ -481,7 +490,7 @@ module Aspera
|
|
481
490
|
case command
|
482
491
|
when :reminder
|
483
492
|
# send an email reminder with list of orgs
|
484
|
-
user_email = options.get_option(:username,
|
493
|
+
user_email = options.get_option(:username, mandatory: true)
|
485
494
|
Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").create('organization_reminders', {email: user_email})[:data]
|
486
495
|
return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
|
487
496
|
when :servers
|
@@ -518,7 +527,7 @@ module Aspera
|
|
518
527
|
when :shared_inboxes
|
519
528
|
case options.get_next_command(%i[list show])
|
520
529
|
when :list
|
521
|
-
query =
|
530
|
+
query = query_read_delete
|
522
531
|
if query.nil?
|
523
532
|
query = {'embed[]' => 'dropbox', 'aggregate_permissions_by_dropbox' => true, 'sort' => 'dropbox_name'}
|
524
533
|
query['workspace_id'] = current_workspace_info['id'] unless current_workspace_info['id'].eql?(:undefined)
|
@@ -528,8 +537,7 @@ module Aspera
|
|
528
537
|
return {type: :single_object, data: aoc_api.read(get_resource_path_from_args('dropboxes'), query)[:data]}
|
529
538
|
end
|
530
539
|
when :send
|
531
|
-
package_data =
|
532
|
-
raise CliBadArgument, 'value must be hash, refer to doc' unless package_data.is_a?(Hash)
|
540
|
+
package_data = value_create_modify(command: package_command, type: Hash)
|
533
541
|
new_user_option = options.get_option(:new_user_option)
|
534
542
|
option_validate = options.get_option(:validate_metadata)
|
535
543
|
# works for both normal usr auth and link auth
|
@@ -557,20 +565,20 @@ module Aspera
|
|
557
565
|
ids_to_download = instance_identifier
|
558
566
|
skip_ids_data = []
|
559
567
|
skip_ids_persistency = nil
|
560
|
-
if options.get_option(:once_only,
|
568
|
+
if options.get_option(:once_only, mandatory: true)
|
561
569
|
skip_ids_persistency = PersistencyActionOnce.new(
|
562
570
|
manager: @agents[:persistency],
|
563
571
|
data: skip_ids_data,
|
564
|
-
id: IdGenerator.from_list(['aoc_recv', options.get_option(:url,
|
572
|
+
id: IdGenerator.from_list(['aoc_recv', options.get_option(:url, mandatory: true),
|
565
573
|
current_workspace_info['id']].concat(aoc_api.additional_persistence_ids)))
|
566
574
|
end
|
567
575
|
if VAL_ALL.eql?(ids_to_download)
|
568
|
-
query =
|
576
|
+
query = query_read_delete(default: PACKAGE_QUERY_DEFAULT)
|
569
577
|
raise 'option query must be Hash' unless query.is_a?(Hash)
|
570
578
|
if query.key?('dropbox_name')
|
571
579
|
# convenience: specify name instead of id
|
572
580
|
raise 'not both dropbox_name and dropbox_id' if query.key?('dropbox_id')
|
573
|
-
query['dropbox_id'] = aoc_api.
|
581
|
+
query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query['dropbox_name'])['id']
|
574
582
|
query.delete('dropbox_name')
|
575
583
|
end
|
576
584
|
query['workspace_id'] ||= current_workspace_info['id'] unless current_workspace_info['id'].eql?(:undefined)
|
@@ -588,7 +596,11 @@ module Aspera
|
|
588
596
|
ids_to_download.each do |package_id|
|
589
597
|
package_info = aoc_api.read("packages/#{package_id}")[:data]
|
590
598
|
formatter.display_status("downloading package: #{package_info['name']}")
|
591
|
-
package_node_api = aoc_api.node_api_from(
|
599
|
+
package_node_api = aoc_api.node_api_from(
|
600
|
+
node_id: package_info['node_id'],
|
601
|
+
workspace_id: current_workspace_info['id'],
|
602
|
+
workspace_name: current_workspace_info['name'],
|
603
|
+
package_info: package_info)
|
592
604
|
statuses = transfer.start(
|
593
605
|
package_node_api.transfer_spec_gen4(
|
594
606
|
package_info['contents_file_id'],
|
@@ -609,12 +621,12 @@ module Aspera
|
|
609
621
|
return { type: :single_object, data: package_info }
|
610
622
|
when :list
|
611
623
|
display_fields = %w[id name bytes_transferred]
|
612
|
-
query =
|
624
|
+
query = query_read_delete(default: PACKAGE_QUERY_DEFAULT)
|
613
625
|
raise 'option query must be Hash' unless query.is_a?(Hash)
|
614
626
|
if query.key?('dropbox_name')
|
615
627
|
# convenience: specify name instead of id
|
616
628
|
raise 'not both dropbox_name and dropbox_id' if query.key?('dropbox_id')
|
617
|
-
query['dropbox_id'] = aoc_api.
|
629
|
+
query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query['dropbox_name'])['id']
|
618
630
|
query.delete('dropbox_name')
|
619
631
|
end
|
620
632
|
if current_workspace_info['id'].eql?(:undefined)
|
@@ -641,72 +653,111 @@ module Aspera
|
|
641
653
|
when *NODE4_EXT_COMMANDS
|
642
654
|
return execute_nodegen4_command(command_repo, home_info[:node_id], file_id: home_info[:file_id], scope: AoC::SCOPE_NODE_USER)
|
643
655
|
when :short_link
|
644
|
-
#
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
656
|
+
# execute action on AoC API
|
657
|
+
short_link_command = options.get_next_command(%i[create delete list])
|
658
|
+
folder_dest = options.get_next_argument('path')
|
659
|
+
link_type = options.get_next_argument('link type', expected: %i[public private])
|
660
|
+
home_node_api = aoc_api.node_api_from(
|
661
|
+
node_id: home_info[:node_id],
|
662
|
+
workspace_id: current_workspace_info['id'],
|
663
|
+
workspace_name: current_workspace_info['name'])
|
664
|
+
shared_apfid = home_node_api.resolve_api_fid(home_info[:file_id], folder_dest)
|
665
|
+
folder_info = {
|
666
|
+
node_id: shared_apfid[:api].app_info[:node_info]['id'],
|
667
|
+
file_id: shared_apfid[:file_id],
|
668
|
+
workspace_id: current_workspace_info['id']
|
669
|
+
}
|
670
|
+
purpose = case link_type
|
671
|
+
when :public then 'token_auth_redirection'
|
672
|
+
when :private then 'shared_folder_auth_link'
|
673
|
+
else raise 'internal error'
|
652
674
|
end
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
node_id: shared_apfid[:api].app_info[:node_info]['id'],
|
661
|
-
workspace_id: current_workspace_info['id']
|
675
|
+
case short_link_command
|
676
|
+
when :delete
|
677
|
+
one_id = instance_identifier
|
678
|
+
folder_info.delete(:workspace_id)
|
679
|
+
delete_params = {
|
680
|
+
edit_access: true,
|
681
|
+
json_query: folder_info.to_json
|
662
682
|
}
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
683
|
+
aoc_api.delete("short_links/#{one_id}", delete_params)
|
684
|
+
if link_type.eql?(:public)
|
685
|
+
# TODO: get permission id..
|
686
|
+
# shared_apfid[:api].delete('permissions', {ids: })[:data]
|
687
|
+
end
|
688
|
+
return Main.result_status('deleted')
|
689
|
+
when :list
|
690
|
+
query = if link_type.eql?(:private)
|
691
|
+
folder_info
|
692
|
+
else
|
693
|
+
{
|
694
|
+
url_token_data: {
|
695
|
+
data: folder_info,
|
696
|
+
purpose: 'view_shared_file'
|
697
|
+
}
|
698
|
+
}
|
699
|
+
end
|
700
|
+
list_params = {
|
701
|
+
json_query: query.to_json,
|
702
|
+
edit_access: true,
|
703
|
+
purpose: purpose,
|
704
|
+
# embed: 'updated_by_user',
|
705
|
+
sort: '-created_at'
|
706
|
+
}
|
707
|
+
result = aoc_api.read('short_links', list_params)[:data]
|
708
|
+
result.each{|i|i.delete('data')}
|
709
|
+
return {type: :object_list, data: result}
|
710
|
+
when :create
|
711
|
+
creation_params = {
|
712
|
+
purpose: purpose,
|
713
|
+
user_selected_name: nil
|
714
|
+
}
|
715
|
+
case link_type
|
716
|
+
when :private
|
717
|
+
creation_params[:data] = folder_info
|
718
|
+
when :public
|
719
|
+
creation_params[:expires_at] = nil
|
720
|
+
creation_params[:password_enabled] = false
|
721
|
+
folder_info[:name] = ''
|
722
|
+
creation_params[:data] = {
|
672
723
|
aoc: true,
|
673
724
|
url_token_data: {
|
674
|
-
data:
|
725
|
+
data: folder_info,
|
675
726
|
purpose: 'view_shared_file'
|
676
727
|
}
|
677
728
|
}
|
678
|
-
value_option['user_selected_name'] = nil
|
679
|
-
else
|
680
|
-
raise 'purpose must be one of: token_auth_redirection or shared_folder_auth_link'
|
681
729
|
end
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
'
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
730
|
+
result_create_short_link = aoc_api.create('short_links', creation_params)[:data]
|
731
|
+
# public: Creation: permission on node
|
732
|
+
if link_type.eql?(:public)
|
733
|
+
# TODO: merge with node permissions ?
|
734
|
+
# TODO: access level as arg
|
735
|
+
access_levels = Aspera::Node::ACCESS_LEVELS # ['delete','list','mkdir','preview','read','rename','write']
|
736
|
+
folder_name = File.basename(folder_dest)
|
737
|
+
perm_data = {
|
738
|
+
'file_id' => shared_apfid[:file_id],
|
739
|
+
'access_id' => result_create_short_link['resource_id'],
|
740
|
+
'access_type' => 'user',
|
741
|
+
'access_levels' => access_levels,
|
742
|
+
'tags' => {
|
743
|
+
'url_token' => true,
|
744
|
+
'workspace_id' => current_workspace_info['id'],
|
745
|
+
'workspace_name' => current_workspace_info['name'],
|
746
|
+
'folder_name' => folder_name,
|
747
|
+
'created_by_name' => aoc_api.current_user_info['name'],
|
748
|
+
'created_by_email' => aoc_api.current_user_info['email'],
|
749
|
+
'access_key' => shared_apfid[:api].app_info[:node_info]['access_key'],
|
750
|
+
'node' => shared_apfid[:api].app_info[:node_info]['host']
|
751
|
+
}
|
702
752
|
}
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
753
|
+
created_data = shared_apfid[:api].create('permissions', perm_data)[:data]
|
754
|
+
aoc_api.permissions_send_event(created_data: created_data, app_info: shared_apfid[:api].app_info)
|
755
|
+
# TODO: event ?
|
756
|
+
end
|
757
|
+
return {type: :single_object, data: result_create_short_link}
|
758
|
+
end # short_link command
|
708
759
|
end # files command
|
709
|
-
|
760
|
+
raise 'Error: shall not reach this line'
|
710
761
|
when :automation
|
711
762
|
Log.log.warn('BETA: work under progress')
|
712
763
|
# automation api is not in the same place
|
@@ -743,7 +794,7 @@ module Aspera
|
|
743
794
|
return execute_admin_action
|
744
795
|
when :gateway
|
745
796
|
require 'aspera/faspex_gw'
|
746
|
-
url =
|
797
|
+
url = value_create_modify(type: String)
|
747
798
|
uri = URI.parse(url)
|
748
799
|
server = WebServerSimple.new(uri)
|
749
800
|
server.mount(uri.path, Faspex4GWServlet, aoc_api, current_workspace_info['id'])
|
@@ -759,6 +810,86 @@ module Aspera
|
|
759
810
|
raise 'internal error: command shall return'
|
760
811
|
end
|
761
812
|
|
813
|
+
# @param [Hash] params : plugin_sym, instance_url
|
814
|
+
# @return [Hash] :preset_value, :test_args
|
815
|
+
def wizard(params)
|
816
|
+
if params[:prepare]
|
817
|
+
organization = AoC.parse_url(params[:instance_url]).first
|
818
|
+
# if not defined by user, generate name
|
819
|
+
params[:preset_name] ||= [params[:plugin_sym], organization].join('_')
|
820
|
+
params[:need_private_key] = true
|
821
|
+
return
|
822
|
+
end
|
823
|
+
options.set_option(:private_key, '@file:' + params[:private_key_path])
|
824
|
+
# make username mandatory for jwt, this triggers interactive input
|
825
|
+
options.get_option(:username, mandatory: true)
|
826
|
+
auto_set_pub_key = false
|
827
|
+
auto_set_jwt = false
|
828
|
+
use_browser_authentication = false
|
829
|
+
if options.get_option(:use_generic_client)
|
830
|
+
formatter.display_status('Using global client_id.')
|
831
|
+
formatter.display_status('Please Login to your Aspera on Cloud instance.'.red)
|
832
|
+
formatter.display_status('Navigate to your "Account Settings"'.red)
|
833
|
+
formatter.display_status('Check or update the value of "Public Key" to be:'.red.blink)
|
834
|
+
formatter.display_status(params[:pub_key_pem])
|
835
|
+
if !options.get_option(:test_mode)
|
836
|
+
formatter.display_status('Once updated or validated, press enter.')
|
837
|
+
OpenApplication.instance.uri(params[:instance_url])
|
838
|
+
$stdin.gets
|
839
|
+
end
|
840
|
+
else
|
841
|
+
formatter.display_status('Using organization specific client_id.')
|
842
|
+
if options.get_option(:client_id).nil? || options.get_option(:client_secret).nil?
|
843
|
+
formatter.display_status('Please login to your Aspera on Cloud instance.'.red)
|
844
|
+
formatter.display_status('Go to: Apps->Admin->Organization->Integrations')
|
845
|
+
formatter.display_status('Create or check if there is an existing integration named:')
|
846
|
+
formatter.display_status("- name: #{@info[:name]}")
|
847
|
+
formatter.display_status("- redirect uri: #{DEFAULT_REDIRECT}")
|
848
|
+
formatter.display_status('- origin: localhost')
|
849
|
+
formatter.display_status('Once created or identified,')
|
850
|
+
formatter.display_status('Please enter:'.red)
|
851
|
+
end
|
852
|
+
OpenApplication.instance.uri("#{params[:instance_url]}/#{AOC_PATH_API_CLIENTS}")
|
853
|
+
options.get_option(:client_id, mandatory: true)
|
854
|
+
options.get_option(:client_secret, mandatory: true)
|
855
|
+
use_browser_authentication = true
|
856
|
+
end
|
857
|
+
if use_browser_authentication
|
858
|
+
formatter.display_status('We will use web authentication to bootstrap.')
|
859
|
+
auto_set_pub_key = true
|
860
|
+
auto_set_jwt = true
|
861
|
+
aoc_api.oauth.generic_parameters[:grant_method] = :web
|
862
|
+
aoc_api.oauth.generic_parameters[:scope] = AoC::SCOPE_FILES_ADMIN
|
863
|
+
aoc_api.oauth.specific_parameters[:redirect_uri] = DEFAULT_REDIRECT
|
864
|
+
end
|
865
|
+
myself = aoc_api.read('self')[:data]
|
866
|
+
if auto_set_pub_key
|
867
|
+
raise CliError, 'Public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? || option_override
|
868
|
+
formatter.display_status('Updating profile with new key')
|
869
|
+
aoc_api.update("users/#{myself['id']}", {'public_key' => params[:pub_key_pem]})
|
870
|
+
end
|
871
|
+
if auto_set_jwt
|
872
|
+
formatter.display_status('Enabling JWT for client')
|
873
|
+
aoc_api.update("clients/#{options.get_option(:client_id)}", {'jwt_grant_enabled' => true, 'explicit_authorization_required' => false})
|
874
|
+
end
|
875
|
+
formatter.display_status("Creating new config preset: #{params[:preset_name]}")
|
876
|
+
preset_result = {
|
877
|
+
url: params[:instance_url],
|
878
|
+
username: myself['email'],
|
879
|
+
auth: :jwt.to_s,
|
880
|
+
private_key: '@file:' + params[:private_key_path]
|
881
|
+
}.stringify_keys
|
882
|
+
# set only if non nil
|
883
|
+
%i[client_id client_secret].each do |s|
|
884
|
+
o = options.get_option(s)
|
885
|
+
preset_result[s.to_s] = o unless o.nil?
|
886
|
+
end
|
887
|
+
return {
|
888
|
+
preset_value: preset_result,
|
889
|
+
test_args: "#{params[:plugin_sym]} user profile show"
|
890
|
+
}
|
891
|
+
end
|
892
|
+
|
762
893
|
private :aoc_params,
|
763
894
|
:home_info,
|
764
895
|
:assert_public_link_types,
|
@@ -7,25 +7,24 @@ module Aspera
|
|
7
7
|
module Cli
|
8
8
|
module Plugins
|
9
9
|
# Access Aspera Transfer Service
|
10
|
-
# https://52.44.83.163/docs/
|
11
10
|
# https://developer.ibm.com/aspera/docs/ats-api-reference/creating-ats-api-keys/
|
12
11
|
class Ats < Aspera::Cli::Plugin
|
13
12
|
def initialize(env)
|
14
13
|
super(env)
|
15
|
-
options.
|
16
|
-
options.
|
17
|
-
options.
|
18
|
-
options.
|
19
|
-
options.
|
20
|
-
options.
|
21
|
-
options.
|
14
|
+
options.declare(:ibm_api_key, 'IBM API key, see https://cloud.ibm.com/iam/apikeys')
|
15
|
+
options.declare(:instance, 'ATS instance in ibm cloud')
|
16
|
+
options.declare(:ats_key, 'ATS key identifier (ats_xxx)')
|
17
|
+
options.declare(:ats_secret, 'ATS key secret')
|
18
|
+
options.declare(:params, 'Parameters access key creation (@json:)')
|
19
|
+
options.declare(:cloud, 'Cloud provider')
|
20
|
+
options.declare(:region, 'Cloud region')
|
22
21
|
options.parse_options!
|
23
22
|
end
|
24
23
|
|
25
24
|
def server_by_cloud_region
|
26
25
|
# TODO: provide list ?
|
27
|
-
cloud = options.get_option(:cloud,
|
28
|
-
region = options.get_option(:region,
|
26
|
+
cloud = options.get_option(:cloud, mandatory: true).upcase
|
27
|
+
region = options.get_option(:region, mandatory: true)
|
29
28
|
return @ats_api_pub.read("servers/#{cloud}/#{region}")[:data]
|
30
29
|
end
|
31
30
|
|
@@ -36,8 +35,8 @@ module Aspera
|
|
36
35
|
base_url: AtsApi.base_url + '/pub/v1',
|
37
36
|
auth: {
|
38
37
|
type: :basic,
|
39
|
-
username: options.get_option(:ats_key,
|
40
|
-
password: options.get_option(:ats_secret,
|
38
|
+
username: options.get_option(:ats_key, mandatory: true),
|
39
|
+
password: options.get_option(:ats_secret, mandatory: true)}
|
41
40
|
})
|
42
41
|
end
|
43
42
|
|
@@ -90,7 +89,7 @@ module Aspera
|
|
90
89
|
res = ats_api_pub_v1.read("access_keys/#{access_key_id}")
|
91
90
|
return {type: :single_object, data: res[:data]}
|
92
91
|
when :modify
|
93
|
-
params =
|
92
|
+
params = value_create_modify(command: command, type: Hash)
|
94
93
|
params['id'] = access_key_id
|
95
94
|
ats_api_pub_v1.update("access_keys/#{access_key_id}", params)
|
96
95
|
return Main.result_status('modified')
|
@@ -138,7 +137,7 @@ module Aspera
|
|
138
137
|
when :list
|
139
138
|
return {type: :object_list, data: @ats_api_pub.all_servers, fields: %w[id cloud region]}
|
140
139
|
when :show
|
141
|
-
if options.get_option(:cloud) || options.get_option(:region
|
140
|
+
if options.get_option(:cloud) || options.get_option(:region)
|
142
141
|
server_data = server_by_cloud_region
|
143
142
|
else
|
144
143
|
server_id = instance_identifier
|
@@ -161,7 +160,7 @@ module Aspera
|
|
161
160
|
generic: {
|
162
161
|
grant_type: 'urn:ibm:params:oauth:grant-type:apikey',
|
163
162
|
response_type: 'cloud_iam',
|
164
|
-
apikey: options.get_option(:ibm_api_key,
|
163
|
+
apikey: options.get_option(:ibm_api_key, mandatory: true)
|
165
164
|
}}})
|
166
165
|
end
|
167
166
|
|
@@ -187,8 +186,7 @@ module Aspera
|
|
187
186
|
Log.log.warn{"more instances remaining: #{instances['remaining']}"} unless instances['remaining'].to_i.eql?(0)
|
188
187
|
return {type: :value_list, data: instances['data'], name: 'instance'}
|
189
188
|
when :create
|
190
|
-
|
191
|
-
created_key = ats_ibm_api.create('api_keys', create_value)[:data]
|
189
|
+
created_key = ats_ibm_api.create('api_keys', value_create_modify(command: command, default: {}, type: Hash))[:data]
|
192
190
|
return {type: :single_object, data: created_key}
|
193
191
|
when :list # list known api keys in ATS (this require an api_key ...)
|
194
192
|
res = ats_ibm_api.read('api_keys', {'offset' => 0, 'max_results' => 1000})
|
@@ -221,7 +219,7 @@ module Aspera
|
|
221
219
|
when :api_key # manage credential to access ATS API
|
222
220
|
return execute_action_api_key
|
223
221
|
when :aws_trust_policy
|
224
|
-
res = ats_api_pub_v1.read('aws/trustpolicy', {region: options.get_option(:region,
|
222
|
+
res = ats_api_pub_v1.read('aws/trustpolicy', {region: options.get_option(:region, mandatory: true)})[:data]
|
225
223
|
return {type: :single_object, data: res}
|
226
224
|
else raise 'ERROR'
|
227
225
|
end
|
@@ -23,7 +23,7 @@ module Aspera
|
|
23
23
|
|
24
24
|
def execute_action
|
25
25
|
if @api_bss.nil?
|
26
|
-
key = options.get_option(:password,
|
26
|
+
key = options.get_option(:password, mandatory: true)
|
27
27
|
@api_bss = Rest.new(
|
28
28
|
base_url: 'https://dashboard.bss.asperasoft.com/platform',
|
29
29
|
headers: {cookie: "_dashboard_key=#{key}"})
|
@@ -35,8 +35,8 @@ module Aspera
|
|
35
35
|
object = 'bssSubscriptions'
|
36
36
|
case command
|
37
37
|
when :find
|
38
|
-
query = options.get_option(:query,
|
39
|
-
value =
|
38
|
+
query = options.get_option(:query, mandatory: true) # AOC_ORGANIZATION_QUERY AOC_USER_EMAIL
|
39
|
+
value = value_create_modify(command: command)
|
40
40
|
request = {
|
41
41
|
'variables' => {'filter' => {'key' => query, 'value' => value}},
|
42
42
|
'query' => "query($filter: BssSubscriptionFilter!) {#{object}(filter: $filter) { #{all_fields('bssSubscriptions')} } }"
|