aspera-cli 4.4.0 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1042 -787
- data/bin/ascli +1 -1
- data/bin/asession +3 -5
- data/docs/Makefile +4 -7
- data/docs/README.erb.md +988 -740
- data/examples/faspex4.rb +4 -6
- data/examples/transfer.rb +2 -2
- data/lib/aspera/aoc.rb +139 -118
- data/lib/aspera/cli/listener/progress_multi.rb +5 -5
- data/lib/aspera/cli/main.rb +64 -34
- data/lib/aspera/cli/manager.rb +19 -20
- data/lib/aspera/cli/plugin.rb +9 -1
- data/lib/aspera/cli/plugins/aoc.rb +156 -143
- data/lib/aspera/cli/plugins/ats.rb +11 -10
- data/lib/aspera/cli/plugins/bss.rb +2 -2
- data/lib/aspera/cli/plugins/config.rb +236 -112
- data/lib/aspera/cli/plugins/faspex.rb +29 -7
- data/lib/aspera/cli/plugins/faspex5.rb +21 -8
- data/lib/aspera/cli/plugins/node.rb +21 -9
- data/lib/aspera/cli/plugins/orchestrator.rb +5 -3
- data/lib/aspera/cli/plugins/preview.rb +2 -2
- data/lib/aspera/cli/plugins/server.rb +3 -3
- data/lib/aspera/cli/plugins/shares.rb +17 -0
- data/lib/aspera/cli/transfer_agent.rb +47 -85
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/environment.rb +4 -4
- data/lib/aspera/fasp/{manager.rb → agent_base.rb} +7 -6
- data/lib/aspera/fasp/{connect.rb → agent_connect.rb} +46 -39
- data/lib/aspera/fasp/{local.rb → agent_direct.rb} +14 -17
- data/lib/aspera/fasp/{http_gw.rb → agent_httpgw.rb} +4 -4
- data/lib/aspera/fasp/{node.rb → agent_node.rb} +25 -8
- data/lib/aspera/fasp/agent_trsdk.rb +106 -0
- data/lib/aspera/fasp/default.rb +17 -0
- data/lib/aspera/fasp/installation.rb +64 -48
- data/lib/aspera/fasp/parameters.rb +7 -3
- data/lib/aspera/faspex_gw.rb +6 -6
- data/lib/aspera/keychain/encrypted_hash.rb +120 -0
- data/lib/aspera/keychain/macos_security.rb +94 -0
- data/lib/aspera/log.rb +45 -32
- data/lib/aspera/node.rb +3 -6
- data/lib/aspera/rest.rb +65 -49
- metadata +68 -27
- data/lib/aspera/api_detector.rb +0 -60
- data/lib/aspera/secrets.rb +0 -20
@@ -2,20 +2,32 @@ require 'aspera/cli/plugins/node'
|
|
2
2
|
require 'aspera/cli/plugins/ats'
|
3
3
|
require 'aspera/cli/basic_auth_plugin'
|
4
4
|
require 'aspera/cli/transfer_agent'
|
5
|
+
require 'aspera/fasp/agent_node'
|
5
6
|
require 'aspera/aoc'
|
6
7
|
require 'aspera/node'
|
7
8
|
require 'aspera/persistency_action_once'
|
8
9
|
require 'aspera/id_generator'
|
9
10
|
require 'securerandom'
|
10
|
-
require 'resolv'
|
11
11
|
require 'date'
|
12
12
|
|
13
13
|
module Aspera
|
14
14
|
module Cli
|
15
15
|
module Plugins
|
16
16
|
class Aoc < BasicAuthPlugin
|
17
|
+
class << self
|
18
|
+
def detect(base_url)
|
19
|
+
api=Rest.new({base_url: base_url})
|
20
|
+
result=api.call({operation: 'GET',subpath: '',headers: {'Accept'=>'text/html'}})
|
21
|
+
if result[:http].body.include?('content="AoC"')
|
22
|
+
return {product: :aoc,version: 'unknown'}
|
23
|
+
end
|
24
|
+
return nil
|
25
|
+
end
|
26
|
+
end
|
17
27
|
# special value for package id
|
18
28
|
VAL_ALL='ALL'
|
29
|
+
ID_AK_ADMIN='ASPERA_ACCESS_KEY_ADMIN'
|
30
|
+
|
19
31
|
def initialize(env)
|
20
32
|
super(env)
|
21
33
|
@default_workspace_id=nil
|
@@ -25,7 +37,6 @@ module Aspera
|
|
25
37
|
@home_node_file=nil
|
26
38
|
@api_aoc=nil
|
27
39
|
@url_token_data=nil
|
28
|
-
@user_info=nil
|
29
40
|
@api_aoc=nil
|
30
41
|
self.options.add_opt_list(:auth,Oauth.auth_types,'OAuth type of authentication')
|
31
42
|
self.options.add_opt_list(:operation,[:push,:pull],'client operation for transfers')
|
@@ -58,32 +69,19 @@ module Aspera
|
|
58
69
|
if @api_aoc.nil?
|
59
70
|
@api_aoc=AoC.new(aoc_params(AoC::API_V1))
|
60
71
|
# add keychain for access key secrets
|
61
|
-
@api_aoc.key_chain=@agents[:
|
72
|
+
@api_aoc.key_chain=@agents[:config]
|
62
73
|
end
|
63
74
|
return @api_aoc
|
64
75
|
end
|
65
76
|
|
66
|
-
# cached user information
|
67
|
-
def c_user_info
|
68
|
-
if @user_info.nil?
|
69
|
-
# get our user's default information
|
70
|
-
# self?embed[]=default_workspace&embed[]=organization
|
71
|
-
@user_info=@api_aoc.read('self')[:data] rescue {
|
72
|
-
'name' => 'unknown',
|
73
|
-
'email' => 'unknown',
|
74
|
-
}
|
75
|
-
end
|
76
|
-
return @user_info
|
77
|
-
end
|
78
|
-
|
79
77
|
# starts transfer using transfer agent
|
80
78
|
def transfer_start(app,direction,node_file,ts_add)
|
81
79
|
ts_add.deep_merge!(AoC.analytics_ts(app,direction,@workspace_id,@workspace_name))
|
82
|
-
ts_add.deep_merge!(
|
80
|
+
ts_add.deep_merge!(@api_aoc.console_ts(app))
|
83
81
|
return self.transfer.start(*@api_aoc.tr_spec(app,direction,node_file,ts_add))
|
84
82
|
end
|
85
83
|
|
86
|
-
NODE4_COMMANDS=[ :browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node, :node_info ]
|
84
|
+
NODE4_COMMANDS=[ :browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node, :node_info ].freeze
|
87
85
|
|
88
86
|
def execute_node_gen4_command(command_repo,top_node_file)
|
89
87
|
case command_repo
|
@@ -96,7 +94,7 @@ module Aspera
|
|
96
94
|
thepath=self.options.get_next_argument('path')
|
97
95
|
node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
|
98
96
|
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER, use_secret: false)
|
99
|
-
return {:
|
97
|
+
return {type: :single_object,data: {
|
100
98
|
url: node_file[:node_info]['url'],
|
101
99
|
username: node_file[:node_info]['access_key'],
|
102
100
|
password: node_api.oauth_token,
|
@@ -114,26 +112,26 @@ module Aspera
|
|
114
112
|
else
|
115
113
|
items=[file_info]
|
116
114
|
end
|
117
|
-
return {:
|
115
|
+
return {type: :object_list,data: items,fields: ['name','type','recursive_size','size','modified_time','access_level']}
|
118
116
|
when :find
|
119
117
|
thepath=self.options.get_next_argument('path')
|
120
118
|
node_file=@api_aoc.resolve_node_file(top_node_file,thepath)
|
121
119
|
test_block=Aspera::Node.file_matcher(self.options.get_option(:value,:optional))
|
122
|
-
return {:
|
120
|
+
return {type: :object_list,data: @api_aoc.find_files(node_file,test_block),fields: ['path']}
|
123
121
|
when :mkdir
|
124
122
|
thepath=self.options.get_next_argument('path')
|
125
123
|
containing_folder_path = thepath.split(AoC::PATH_SEPARATOR)
|
126
124
|
new_folder=containing_folder_path.pop
|
127
125
|
node_file = @api_aoc.resolve_node_file(top_node_file,containing_folder_path.join(AoC::PATH_SEPARATOR))
|
128
126
|
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
129
|
-
result=node_api.create("files/#{node_file[:file_id]}/files",{:
|
127
|
+
result=node_api.create("files/#{node_file[:file_id]}/files",{name: new_folder,type: :folder})[:data]
|
130
128
|
return Main.result_status("created: #{result['name']} (id=#{result['id']})")
|
131
129
|
when :rename
|
132
130
|
thepath=self.options.get_next_argument('source path')
|
133
131
|
newname=self.options.get_next_argument('new name')
|
134
132
|
node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
|
135
133
|
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
136
|
-
result=node_api.update("files/#{node_file[:file_id]}",{:
|
134
|
+
result=node_api.update("files/#{node_file[:file_id]}",{name: newname})[:data]
|
137
135
|
return Main.result_status("renamed #{thepath} to #{newname}")
|
138
136
|
when :delete
|
139
137
|
thepath=self.options.get_next_argument('path')
|
@@ -163,7 +161,13 @@ module Aspera
|
|
163
161
|
client_node_file = @api_aoc.resolve_node_file(client_home_node_file,client_folder)
|
164
162
|
server_node_file = @api_aoc.resolve_node_file(server_home_node_file,server_folder)
|
165
163
|
# force node as transfer agent
|
166
|
-
|
164
|
+
client_node_api=@api_aoc.get_node_api(client_node_file[:node_info],scope: AoC::SCOPE_NODE_USER, use_secret: false)
|
165
|
+
@agents[:transfer].set_agent_instance(Fasp::AgentNode.new({
|
166
|
+
url: client_node_api.params[:base_url],
|
167
|
+
username: client_node_file[:node_info]['access_key'],
|
168
|
+
password: client_node_api.oauth_token,
|
169
|
+
root_id: client_node_file[:file_id]
|
170
|
+
}))
|
167
171
|
# additional node to node TS info
|
168
172
|
add_ts={
|
169
173
|
'remote_access_key' => server_node_file[:node_info]['access_key'],
|
@@ -202,7 +206,7 @@ module Aspera
|
|
202
206
|
file_name = source_paths.first['source']
|
203
207
|
node_file = @api_aoc.resolve_node_file(top_node_file,File.join(source_folder,file_name))
|
204
208
|
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
205
|
-
node_api.call({:
|
209
|
+
node_api.call({operation: 'GET',subpath: "files/#{node_file[:file_id]}/content",save_to_file: File.join(self.transfer.destination_folder('receive'),file_name)})
|
206
210
|
return Main.result_status("downloaded: #{file_name}")
|
207
211
|
when :v3
|
208
212
|
# Note: other common actions are unauthorized with user scope
|
@@ -211,22 +215,22 @@ module Aspera
|
|
211
215
|
node_api=@api_aoc.get_node_api(top_node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
212
216
|
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: node_api)).execute_action(command_legacy)
|
213
217
|
when :file
|
218
|
+
command_node_file=self.options.get_next_command([:show,:permission,:modify])
|
214
219
|
file_path=self.options.get_option(:path,:optional)
|
215
220
|
node_file = if !file_path.nil?
|
216
221
|
@api_aoc.resolve_node_file(top_node_file,file_path) # TODO: allow follow link ?
|
217
222
|
else
|
218
|
-
{node_info: top_node_file[:node_info],file_id: self.
|
223
|
+
{node_info: top_node_file[:node_info],file_id: self.instance_identifier()}
|
219
224
|
end
|
220
225
|
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
221
|
-
command_node_file=self.options.get_next_command([:show,:permission,:modify])
|
222
226
|
case command_node_file
|
223
227
|
when :show
|
224
228
|
items=node_api.read("files/#{node_file[:file_id]}")[:data]
|
225
|
-
return {:
|
229
|
+
return {type: :single_object,data: items}
|
226
230
|
when :modify
|
227
231
|
update_param=self.options.get_next_argument('update data (Hash)')
|
228
232
|
res=node_api.update("files/#{node_file[:file_id]}",update_param)[:data]
|
229
|
-
return {:
|
233
|
+
return {type: :single_object,data: res}
|
230
234
|
when :permission
|
231
235
|
command_perm=self.options.get_next_command([:list,:create])
|
232
236
|
case command_perm
|
@@ -240,11 +244,11 @@ module Aspera
|
|
240
244
|
list_options['inherited']||=false
|
241
245
|
end
|
242
246
|
items=node_api.read('permissions',list_options)[:data]
|
243
|
-
return {:
|
247
|
+
return {type: :object_list,data: items}
|
244
248
|
when :create
|
245
249
|
#create_param=self.options.get_next_argument('creation data (Hash)')
|
246
250
|
set_workspace_info
|
247
|
-
access_id="
|
251
|
+
access_id="#{ID_AK_ADMIN}_WS_#{@workspace_id}"
|
248
252
|
node_file[:node_info]
|
249
253
|
params={
|
250
254
|
'file_id' =>node_file[:file_id], # mandatory
|
@@ -254,23 +258,21 @@ module Aspera
|
|
254
258
|
'tags' =>{'aspera'=>{'files'=>{'workspace'=>{
|
255
259
|
'id' =>@workspace_id,
|
256
260
|
'workspace_name' =>@workspace_name,
|
257
|
-
'user_name'
|
258
|
-
'shared_by_user_id'
|
259
|
-
'shared_by_name'
|
260
|
-
'shared_by_email'
|
261
|
+
'user_name' =>@api_aoc.user_info['name'],
|
262
|
+
'shared_by_user_id'=>@api_aoc.user_info['id'],
|
263
|
+
'shared_by_name' =>@api_aoc.user_info['name'],
|
264
|
+
'shared_by_email' =>@api_aoc.user_info['email'],
|
261
265
|
'shared_with_name' =>access_id,
|
262
266
|
'access_key' =>node_file[:node_info]['access_key'],
|
263
267
|
'node' =>node_file[:node_info]['name']}}}}}
|
264
268
|
item=node_api.create('permissions',params)[:data]
|
265
|
-
return {:
|
269
|
+
return {type: :single_object,data: item}
|
266
270
|
else raise "internal error:shall not reach here (#{command_perm})"
|
267
271
|
end
|
268
272
|
raise 'internal error:shall not reach here'
|
269
273
|
else raise "internal error:shall not reach here (#{command_node_file})"
|
270
274
|
end
|
271
275
|
raise 'internal error:shall not reach here'
|
272
|
-
when :permissions
|
273
|
-
|
274
276
|
end # command_repo
|
275
277
|
raise 'ERR'
|
276
278
|
end # execute_node_gen4_command
|
@@ -297,8 +299,8 @@ module Aspera
|
|
297
299
|
@default_workspace_id=@url_token_data['data']['workspace_id']
|
298
300
|
@persist_ids=[] # TODO : @url_token_data['id'] ?
|
299
301
|
else
|
300
|
-
@default_workspace_id
|
301
|
-
@persist_ids=[
|
302
|
+
@default_workspace_id=@api_aoc.user_info['default_workspace_id']
|
303
|
+
@persist_ids=[@api_aoc.user_info['id']]
|
302
304
|
end
|
303
305
|
|
304
306
|
ws_name=self.options.get_option(:workspace,:optional)
|
@@ -367,7 +369,27 @@ module Aspera
|
|
367
369
|
end
|
368
370
|
result_list.push(one)
|
369
371
|
end
|
370
|
-
return {:
|
372
|
+
return {type: :object_list,data: result_list,fields: [id_result,'status']}
|
373
|
+
end
|
374
|
+
|
375
|
+
NOT_FOUND="not found"
|
376
|
+
|
377
|
+
def lookup_single(entity_type,entity_name,options={})
|
378
|
+
# returns entities whose name contains value (case insensitive)
|
379
|
+
matching_items=@api_aoc.read(entity_type,options.merge({'q'=>entity_name}))[:data]
|
380
|
+
case matching_items.length
|
381
|
+
when 1; return matching_items.first
|
382
|
+
when 0; raise RuntimeError,NOT_FOUND
|
383
|
+
else
|
384
|
+
# multiple case insensitive partial matches, try case insensitive full match
|
385
|
+
# (anyway AoC does not allow creation of 2 entities with same case insensitive name)
|
386
|
+
icase_matches=matching_items.select{|i|i['name'].casecmp?(entity_name)}
|
387
|
+
case icase_matches.length
|
388
|
+
when 1; return icase_matches.first
|
389
|
+
when 0; raise CliBadArgument,"#{entity_type}: multiple case insensitive partial match for: \"#{entity_name}\": #{matching_items.map{|i|i['name']}} but no case insensitive full match. Please be more specific or give exact name."
|
390
|
+
else raise "Two entities cannot have the same case insensitive name: #{icase_matches.map{|i|i['name']}}"
|
391
|
+
end
|
392
|
+
end
|
371
393
|
end
|
372
394
|
|
373
395
|
# package creation params can give just email, and full hash is created
|
@@ -375,36 +397,37 @@ module Aspera
|
|
375
397
|
return unless package_creation.has_key?(recipient_list_field)
|
376
398
|
raise CliBadArgument,"#{recipient_list_field} must be an Array" unless package_creation[recipient_list_field].is_a?(Array)
|
377
399
|
new_user_option=self.options.get_option(:new_user_option,:mandatory)
|
400
|
+
# list with resolved elements
|
378
401
|
resolved_list=[]
|
379
|
-
package_creation[recipient_list_field].each do |
|
380
|
-
case
|
381
|
-
when Hash
|
382
|
-
raise
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
else
|
402
|
+
package_creation[recipient_list_field].each do |short_recipient_info|
|
403
|
+
case short_recipient_info
|
404
|
+
when Hash # native api information, check keys
|
405
|
+
raise "#{recipient_list_field} element shall have fields: id and type" unless short_recipient_info.keys.sort.eql?(['id','type'])
|
406
|
+
when String # need to resolve name to type/id
|
407
|
+
# email: user, else dropbox
|
408
|
+
entity_type=short_recipient_info.include?('@') ? 'contacts' : 'dropboxes'
|
409
|
+
begin
|
410
|
+
full_recipient_info=lookup_single(entity_type,short_recipient_info,{'current_workspace_id'=>@workspace_id})
|
411
|
+
rescue RuntimeError => e
|
412
|
+
raise e unless e.message.eql?(NOT_FOUND)
|
413
|
+
if entity_type.eql?('contacts')
|
414
|
+
full_recipient_info=@api_aoc.create('contacts',{'current_workspace_id'=>@workspace_id,'email'=>short_recipient_info}.merge(new_user_option))[:data]
|
415
|
+
else
|
416
|
+
raise "no such shared inbox in workspace #{@workspace_name}"
|
393
417
|
end
|
394
|
-
|
418
|
+
end
|
419
|
+
if entity_type.eql?('dropboxes')
|
420
|
+
short_recipient_info={'id'=>full_recipient_info['id'],'type'=>'dropbox'}
|
395
421
|
else
|
396
|
-
|
397
|
-
case item_lookup.length
|
398
|
-
when 1; recipient_user_id=item_lookup.first
|
399
|
-
when 0; raise "no such shared inbox in workspace #{@workspace_name}"
|
400
|
-
else raise CliBadArgument,"multiple match for: #{recipient_email_or_info}"
|
401
|
-
end
|
402
|
-
resolved_list.push({'id'=>recipient_user_id['id'],'type'=>'dropbox'})
|
422
|
+
short_recipient_info={'id'=>full_recipient_info['source_id'],'type'=>full_recipient_info['source_type']}
|
403
423
|
end
|
404
|
-
else
|
405
|
-
raise "
|
406
|
-
end
|
424
|
+
else # unexpected extended value, must be String or Hash
|
425
|
+
raise "#{recipient_list_field} item must be a String (email, shared inbox) or Hash (id,type)"
|
426
|
+
end # type of recipient info
|
427
|
+
# add original or resolved recipient info
|
428
|
+
resolved_list.push(short_recipient_info)
|
407
429
|
end
|
430
|
+
# replace with resolved elements
|
408
431
|
package_creation[recipient_list_field]=resolved_list
|
409
432
|
end
|
410
433
|
|
@@ -468,7 +491,7 @@ module Aspera
|
|
468
491
|
case command_auth_prov
|
469
492
|
when :list
|
470
493
|
providers=@api_aoc.read('admin/auth_providers')[:data]
|
471
|
-
return {:
|
494
|
+
return {type: :object_list,data: providers}
|
472
495
|
when :update
|
473
496
|
end
|
474
497
|
when :subscription
|
@@ -523,31 +546,31 @@ module Aspera
|
|
523
546
|
}
|
524
547
|
"
|
525
548
|
result=bss_api.create('graphql',{'variables'=>{'organization_id'=>org['id']},'query'=>graphql_query})[:data]['data']
|
526
|
-
return {:
|
549
|
+
return {type: :single_object,data: result['aoc']['bssSubscription']}
|
527
550
|
when :ats
|
528
551
|
ats_api = Rest.new(@api_aoc.params.deep_merge({
|
529
|
-
:
|
530
|
-
:
|
552
|
+
base_url: @api_aoc.params[:base_url]+'/admin/ats/pub/v1',
|
553
|
+
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
531
554
|
}))
|
532
555
|
return Ats.new(@agents).execute_action_gen(ats_api)
|
533
556
|
when :analytics
|
534
557
|
analytics_api = Rest.new(@api_aoc.params.deep_merge({
|
535
|
-
:
|
536
|
-
:
|
558
|
+
base_url: @api_aoc.params[:base_url].gsub('/api/v1','')+'/analytics/v2',
|
559
|
+
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
537
560
|
}))
|
538
561
|
command_analytics=self.options.get_next_command([ :application_events, :transfers ])
|
539
562
|
case command_analytics
|
540
563
|
when :application_events
|
541
564
|
event_type=command_analytics.to_s
|
542
|
-
events=analytics_api.read("organizations/#{
|
543
|
-
return {:
|
565
|
+
events=analytics_api.read("organizations/#{@api_aoc.user_info['organization_id']}/#{event_type}")[:data][event_type]
|
566
|
+
return {type: :object_list,data: events}
|
544
567
|
when :transfers
|
545
568
|
event_type=command_analytics.to_s
|
546
569
|
filter_resource=self.options.get_option(:name,:optional) || 'organizations'
|
547
570
|
filter_id=self.options.get_option(:id,:optional) || case filter_resource
|
548
|
-
when 'organizations';
|
549
|
-
when 'users';
|
550
|
-
when 'nodes';
|
571
|
+
when 'organizations'; @api_aoc.user_info['organization_id']
|
572
|
+
when 'users'; @api_aoc.user_info['id']
|
573
|
+
when 'nodes'; @api_aoc.user_info['id']
|
551
574
|
else raise 'organizations or users for option --name'
|
552
575
|
end
|
553
576
|
#
|
@@ -575,24 +598,19 @@ module Aspera
|
|
575
598
|
self.config.send_email_template({ev: tr_event})
|
576
599
|
end
|
577
600
|
end
|
578
|
-
return {:
|
601
|
+
return {type: :object_list,data: events}
|
579
602
|
end
|
580
603
|
when :resource
|
581
604
|
resource_type=self.options.get_next_argument('resource',[:self,:organization,:user,:group,:client,:contact,:dropbox,:node,:operation,:package,:saml_configuration, :workspace, :dropbox_membership,:short_link,:workspace_membership,:application,:client_registration_token,:client_access_key,:kms_profile])
|
582
|
-
# get path on API
|
605
|
+
# get path on API, resource type is singular, but api is plural
|
583
606
|
resource_class_path=case resource_type
|
584
|
-
|
585
|
-
|
586
|
-
when :
|
587
|
-
|
588
|
-
when :dropbox
|
589
|
-
|
590
|
-
|
591
|
-
"admin/#{resource_type}s"
|
592
|
-
when :kms_profile
|
593
|
-
"integrations/#{resource_type}s"
|
594
|
-
else
|
595
|
-
resource_type.to_s+'s'
|
607
|
+
# special cases: singleton, in admin, with x
|
608
|
+
when :self,:organization; resource_type
|
609
|
+
when :client_registration_token,:client_access_key; "admin/#{resource_type}s"
|
610
|
+
when :application; 'admin/apps_new'
|
611
|
+
when :dropbox; resource_type.to_s+'es'
|
612
|
+
when :kms_profile; "integrations/#{resource_type}s"
|
613
|
+
else resource_type.to_s+'s'
|
596
614
|
end
|
597
615
|
# build list of supported operations
|
598
616
|
singleton_object=[:self,:organization].include?(resource_type)
|
@@ -607,19 +625,14 @@ module Aspera
|
|
607
625
|
if !singleton_object and !global_operations.include?(command)
|
608
626
|
res_id=self.options.get_option(:id)
|
609
627
|
res_name=self.options.get_option(:name)
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
matching=@api_aoc.read(resource_class_path,{:q=>res_name})[:data]
|
618
|
-
raise CliError,'no resource match name' if matching.empty?
|
619
|
-
raise CliError,"several resources match name (#{matching.join(',')})" unless matching.length.eql?(1)
|
620
|
-
res_id=matching.first['id']
|
628
|
+
raise "Provide id or name, not both" unless res_id.nil? or res_name.nil?
|
629
|
+
# try to find item by name (single partial match or exact match)
|
630
|
+
res_id=lookup_single(resource_class_path,res_name)['id'] if !res_name.nil?
|
631
|
+
# if no name or id option, taken on command line (after command)
|
632
|
+
if res_id.nil?
|
633
|
+
res_id=self.options.get_next_argument('identifier')
|
634
|
+
res_id=lookup_single(resource_class_path,self.options.get_next_argument('identifier'))['id'] if res_id.eql?('name')
|
621
635
|
end
|
622
|
-
raise CliBadArgument,'provide either id or name' if res_id.nil?
|
623
636
|
resource_instance_path="#{resource_class_path}/#{res_id}"
|
624
637
|
end
|
625
638
|
resource_instance_path=resource_class_path if singleton_object
|
@@ -638,7 +651,7 @@ module Aspera
|
|
638
651
|
default_fields=['id']
|
639
652
|
default_query={}
|
640
653
|
case resource_type
|
641
|
-
when :application; default_query={:
|
654
|
+
when :application; default_query={organization_apps: true};default_fields.push('app_type','app_name','available','direct_authorizations_allowed','workspace_authorizations_allowed')
|
642
655
|
when :client,:client_access_key,:dropbox,:group,:package,:saml_configuration,:workspace; default_fields.push('name')
|
643
656
|
when :client_registration_token; default_fields.push('value','data.client_subject_scopes','created_at')
|
644
657
|
when :contact; default_fields=['email','name','source_id','source_type']
|
@@ -651,11 +664,11 @@ module Aspera
|
|
651
664
|
count_msg="Items: #{item_list.length}/#{total_count}"
|
652
665
|
count_msg=count_msg.bg_red unless item_list.length.eql?(total_count.to_i)
|
653
666
|
self.format.display_status(count_msg)
|
654
|
-
return {:
|
667
|
+
return {type: :object_list,data: item_list,fields: default_fields}
|
655
668
|
when :show
|
656
669
|
object=@api_aoc.read(resource_instance_path)[:data]
|
657
670
|
fields=object.keys.select{|k|!k.eql?('certificate')}
|
658
|
-
return { :
|
671
|
+
return { type: :single_object, data: object, fields: fields }
|
659
672
|
when :modify
|
660
673
|
changes=self.options.get_next_argument('modified parameters (hash)')
|
661
674
|
@api_aoc.update(resource_instance_path,changes)
|
@@ -669,19 +682,19 @@ module Aspera
|
|
669
682
|
# special : reads private and generate public
|
670
683
|
the_private_key=self.options.get_next_argument('private_key')
|
671
684
|
the_public_key=OpenSSL::PKey::RSA.new(the_private_key).public_key.to_s
|
672
|
-
@api_aoc.update(resource_instance_path,{:
|
685
|
+
@api_aoc.update(resource_instance_path,{jwt_grant_enabled: true, public_key: the_public_key})
|
673
686
|
return Main.result_success
|
674
687
|
when :v3,:v4
|
675
688
|
res_data=@api_aoc.read(resource_instance_path)[:data]
|
676
689
|
api_node=@api_aoc.get_node_api(res_data)
|
677
690
|
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action if command.eql?(:v3)
|
678
|
-
ak_data=api_node.call({:
|
691
|
+
ak_data=api_node.call({operation: 'GET',subpath: "access_keys/#{res_data['access_key']}",headers: {'Accept'=>'application/json'}})[:data]
|
679
692
|
command_repo=self.options.get_next_command(NODE4_COMMANDS)
|
680
693
|
return execute_node_gen4_command(command_repo,{node_info: res_data, file_id: ak_data['root_file_id']})
|
681
694
|
when :shared_folders
|
682
695
|
read_params = case resource_type
|
683
|
-
when :workspace;{'access_id'=>"
|
684
|
-
when :node;{'include'=>['[]','access_level','permission_count'],'created_by_id'=>
|
696
|
+
when :workspace;{'access_id'=>"#{ID_AK_ADMIN}_WS_#{res_id}",'access_type'=>'user'}
|
697
|
+
when :node;{'include'=>['[]','access_level','permission_count'],'created_by_id'=>ID_AK_ADMIN}
|
685
698
|
else raise 'error'
|
686
699
|
end
|
687
700
|
res_data=@api_aoc.read("#{resource_class_path}/#{res_id}/permissions",read_params)[:data]
|
@@ -690,9 +703,9 @@ module Aspera
|
|
690
703
|
when :workspace;['id','node_id','file_id','node_name','file.path','tags.aspera.files.workspace.share_as']
|
691
704
|
else raise "unexpected resource type #{resource_type}"
|
692
705
|
end
|
693
|
-
return { :
|
706
|
+
return { type: :object_list, data: res_data , fields: fields}
|
694
707
|
when :shared_create
|
695
|
-
# TODO
|
708
|
+
# TODO: finish implementation
|
696
709
|
folder_path=self.options.get_next_argument('folder path in node')
|
697
710
|
user_create_data=self.options.get_next_argument('creation data (Hash)')
|
698
711
|
res_data=@api_aoc.read(resource_instance_path)[:data]
|
@@ -701,7 +714,7 @@ module Aspera
|
|
701
714
|
#node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
702
715
|
#file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
|
703
716
|
|
704
|
-
access_id="
|
717
|
+
access_id="#{ID_AK_ADMIN}_WS_#{@workspace_id}"
|
705
718
|
create_data={
|
706
719
|
'file_id' =>node_file[:file_id],
|
707
720
|
'access_type' =>'user',
|
@@ -711,10 +724,10 @@ module Aspera
|
|
711
724
|
'id' =>@workspace_id,
|
712
725
|
'workspace_name' =>@workspace_name,
|
713
726
|
'share_as' =>File.basename(folder_path),
|
714
|
-
'user_name'
|
715
|
-
'shared_by_user_id'
|
716
|
-
'shared_by_name'
|
717
|
-
'shared_by_email'
|
727
|
+
'user_name' =>@api_aoc.user_info['name'],
|
728
|
+
'shared_by_user_id'=>@api_aoc.user_info['id'],
|
729
|
+
'shared_by_name' =>@api_aoc.user_info['name'],
|
730
|
+
'shared_by_email' =>@api_aoc.user_info['email'],
|
718
731
|
'shared_with_name' =>access_id,
|
719
732
|
'access_key' =>node_file[:node_info]['access_key'],
|
720
733
|
'node' =>node_file[:node_info]['name']}
|
@@ -725,12 +738,12 @@ module Aspera
|
|
725
738
|
else raise 'unknown command'
|
726
739
|
end
|
727
740
|
when :usage_reports
|
728
|
-
return {:
|
741
|
+
return {type: :object_list,data: @api_aoc.read('usage_reports',{workspace_id: @workspace_id})[:data]}
|
729
742
|
end
|
730
743
|
end
|
731
744
|
|
732
745
|
# must be public
|
733
|
-
ACTIONS=[ :reminder, :bearer_token, :organization, :tier_restrictions, :user, :workspace, :packages, :files, :gateway, :admin, :automation, :servers]
|
746
|
+
ACTIONS=[ :reminder, :bearer_token, :organization, :tier_restrictions, :user, :workspace, :packages, :files, :gateway, :admin, :automation, :servers].freeze
|
734
747
|
|
735
748
|
def execute_action
|
736
749
|
command=self.options.get_next_command(ACTIONS)
|
@@ -742,38 +755,38 @@ module Aspera
|
|
742
755
|
Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").create('organization_reminders',{email: user_email})[:data]
|
743
756
|
return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
|
744
757
|
when :bearer_token
|
745
|
-
return {:
|
758
|
+
return {type: :text,data: @api_aoc.oauth_token}
|
746
759
|
when :organization
|
747
|
-
return { :
|
760
|
+
return { type: :single_object, data: @api_aoc.read('organization')[:data] }
|
748
761
|
when :tier_restrictions
|
749
|
-
return { :
|
762
|
+
return { type: :single_object, data: @api_aoc.read('tier_restrictions')[:data] }
|
750
763
|
when :user
|
751
764
|
command=self.options.get_next_command([ :workspaces,:info,:shared_inboxes ])
|
752
765
|
case command
|
753
766
|
when :workspaces
|
754
|
-
return {:
|
767
|
+
return {type: :object_list,data: @api_aoc.read('workspaces')[:data],fields: ['id','name']}
|
755
768
|
# when :settings
|
756
|
-
# return {:
|
769
|
+
# return {type: :object_list,data: @api_aoc.read('client_settings/')[:data]}
|
757
770
|
when :shared_inboxes
|
758
771
|
query=option_url_query(nil)
|
759
772
|
if query.nil?
|
760
773
|
set_workspace_info
|
761
774
|
query={'embed[]'=>'dropbox','workspace_id'=>@workspace_id,'aggregate_permissions_by_dropbox'=>true,'sort'=>'dropbox_name'}
|
762
775
|
end
|
763
|
-
return {:
|
776
|
+
return {type: :object_list,data: @api_aoc.read('dropbox_memberships',query)[:data],fields: ['dropbox_id','dropbox.name']}
|
764
777
|
when :info
|
765
778
|
command=self.options.get_next_command([ :show,:modify ])
|
766
779
|
case command
|
767
780
|
when :show
|
768
|
-
return { :
|
781
|
+
return { type: :single_object, data: @api_aoc.user_info }
|
769
782
|
when :modify
|
770
|
-
@api_aoc.update("users/#{
|
783
|
+
@api_aoc.update("users/#{@api_aoc.user_info['id']}",self.options.get_next_argument('modified parameters (hash)'))
|
771
784
|
return Main.result_status('modified')
|
772
785
|
end
|
773
786
|
end
|
774
787
|
when :workspace # show current workspace parameters
|
775
788
|
set_workspace_info
|
776
|
-
return { :
|
789
|
+
return { type: :single_object, data: @workspace_data }
|
777
790
|
when :packages
|
778
791
|
set_workspace_info if @url_token_data.nil?
|
779
792
|
command_pkg=self.options.get_next_command([ :send, :recv, :list, :show, :delete ])
|
@@ -812,14 +825,14 @@ module Aspera
|
|
812
825
|
# raise exception if at least one error
|
813
826
|
Main.result_transfer(transfer_start(AoC::PACKAGES_APP,'send',node_file,AoC.package_tags(package_info,'upload')))
|
814
827
|
# return all info on package
|
815
|
-
return { :
|
828
|
+
return { type: :single_object, data: package_info}
|
816
829
|
when :recv
|
817
830
|
if !@url_token_data.nil?
|
818
831
|
assert_public_link_types(['view_received_package'])
|
819
832
|
self.options.set_option(:id,@url_token_data['data']['package_id'])
|
820
833
|
end
|
821
834
|
# scalar here
|
822
|
-
ids_to_download=self.
|
835
|
+
ids_to_download=self.instance_identifier()
|
823
836
|
skip_ids_data=[]
|
824
837
|
skip_ids_persistency=nil
|
825
838
|
if self.options.get_option(:once_only,:mandatory)
|
@@ -858,15 +871,15 @@ module Aspera
|
|
858
871
|
when :show
|
859
872
|
package_id=self.options.get_next_argument('package ID')
|
860
873
|
package_info=@api_aoc.read("packages/#{package_id}")[:data]
|
861
|
-
return { :
|
874
|
+
return { type: :single_object, data: package_info }
|
862
875
|
when :list
|
863
876
|
query=option_url_query({'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true})
|
864
877
|
raise 'option must be Hash' unless query.is_a?(Hash)
|
865
878
|
query['workspace_id']||=@workspace_id
|
866
879
|
packages=@api_aoc.read('packages',query)[:data]
|
867
|
-
return {:
|
880
|
+
return {type: :object_list,data: packages,fields: ['id','name','bytes_transferred']}
|
868
881
|
when :delete
|
869
|
-
list_or_one=self.
|
882
|
+
list_or_one=self.instance_identifier()
|
870
883
|
return do_bulk_operation(list_or_one,'deleted')do|id|
|
871
884
|
raise 'expecting String identifier' unless id.is_a?(String) or id.is_a?(Integer)
|
872
885
|
@api_aoc.delete("packages/#{id}")[:data]
|
@@ -876,7 +889,7 @@ module Aspera
|
|
876
889
|
# get workspace related information
|
877
890
|
set_workspace_info
|
878
891
|
set_home_node_file
|
879
|
-
command_repo=self.options.get_next_command(NODE4_COMMANDS
|
892
|
+
command_repo=self.options.get_next_command([NODE4_COMMANDS,:short_link].flatten)
|
880
893
|
case command_repo
|
881
894
|
when *NODE4_COMMANDS; return execute_node_gen4_command(command_repo,@home_node_file)
|
882
895
|
when :short_link
|
@@ -935,8 +948,8 @@ module Aspera
|
|
935
948
|
'workspace_id' =>@workspace_id,
|
936
949
|
'workspace_name' =>@workspace_name,
|
937
950
|
'folder_name' =>'my folder',
|
938
|
-
'created_by_name'
|
939
|
-
'created_by_email'
|
951
|
+
'created_by_name' =>@api_aoc.user_info['name'],
|
952
|
+
'created_by_email'=>@api_aoc.user_info['email'],
|
940
953
|
'access_key' =>node_file[:node_info]['access_key'],
|
941
954
|
'node' =>node_file[:node_info]['host']
|
942
955
|
}
|
@@ -964,18 +977,18 @@ module Aspera
|
|
964
977
|
when *Plugin::ALL_OPS
|
965
978
|
return self.entity_command(wf_command,automation_api,'workflows',nil,:id)
|
966
979
|
when :launch
|
967
|
-
wf_id=self.
|
980
|
+
wf_id=self.instance_identifier()
|
968
981
|
data=automation_api.create("workflows/#{wf_id}/launch",{})[:data]
|
969
|
-
return {:
|
982
|
+
return {type: :single_object,data: data}
|
970
983
|
when :action
|
971
984
|
wf_command=self.options.get_next_command([:list,:create,:show])
|
972
|
-
wf_id=self.
|
985
|
+
wf_id=self.instance_identifier()
|
973
986
|
step=automation_api.create('steps',{'workflow_id'=>wf_id})[:data]
|
974
987
|
automation_api.update("workflows/#{wf_id}",{'step_order'=>[step['id']]})
|
975
988
|
action=automation_api.create('actions',{'step_id'=>step['id'],'type'=>'manual'})[:data]
|
976
989
|
automation_api.update("steps/#{step['id']}",{'action_order'=>[action['id']]})
|
977
990
|
wf=automation_api.read("workflows/#{wf_id}")[:data]
|
978
|
-
return {:
|
991
|
+
return {type: :single_object,data: wf}
|
979
992
|
end
|
980
993
|
end
|
981
994
|
when :gateway
|
@@ -985,15 +998,15 @@ module Aspera
|
|
985
998
|
when :admin
|
986
999
|
return execute_admin_action
|
987
1000
|
when :servers
|
988
|
-
return {:
|
1001
|
+
return {type: :object_list,data: Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
|
989
1002
|
else
|
990
1003
|
raise "internal error: #{command}"
|
991
1004
|
end # action
|
992
1005
|
raise RuntimeError, 'internal error: command shall return'
|
993
1006
|
end
|
994
1007
|
|
995
|
-
private :
|
996
|
-
private_constant :VAL_ALL,:NODE4_COMMANDS
|
1008
|
+
private :aoc_params,:set_workspace_info,:set_home_node_file,:do_bulk_operation,:resolve_package_recipients,:option_url_query,:assert_public_link_types,:execute_admin_action
|
1009
|
+
private_constant :VAL_ALL,:NODE4_COMMANDS, :ID_AK_ADMIN
|
997
1010
|
|
998
1011
|
end # AoC
|
999
1012
|
end # Plugins
|