aspera-cli 4.2.1 → 4.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1580 -946
- data/bin/ascli +1 -1
- data/bin/asession +3 -5
- data/docs/Makefile +8 -11
- data/docs/README.erb.md +1521 -829
- data/docs/doc_tools.rb +58 -0
- data/docs/test_env.conf +3 -1
- data/examples/faspex4.rb +28 -19
- data/examples/transfer.rb +2 -2
- data/lib/aspera/aoc.rb +157 -134
- data/lib/aspera/cli/listener/progress_multi.rb +5 -5
- data/lib/aspera/cli/main.rb +106 -48
- data/lib/aspera/cli/manager.rb +19 -20
- data/lib/aspera/cli/plugin.rb +22 -7
- data/lib/aspera/cli/plugins/aoc.rb +260 -208
- 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 +360 -189
- data/lib/aspera/cli/plugins/faspex.rb +119 -56
- data/lib/aspera/cli/plugins/faspex5.rb +32 -17
- data/lib/aspera/cli/plugins/node.rb +72 -31
- data/lib/aspera/cli/plugins/orchestrator.rb +5 -3
- data/lib/aspera/cli/plugins/preview.rb +94 -68
- data/lib/aspera/cli/plugins/server.rb +16 -5
- data/lib/aspera/cli/plugins/shares.rb +17 -0
- data/lib/aspera/cli/transfer_agent.rb +64 -82
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +48 -31
- data/lib/aspera/cos_node.rb +4 -3
- 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} +42 -38
- data/lib/aspera/fasp/{http_gw.rb → agent_httpgw.rb} +50 -29
- data/lib/aspera/fasp/{node.rb → agent_node.rb} +43 -4
- 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 +78 -91
- data/lib/aspera/fasp/parameters.yaml +531 -0
- data/lib/aspera/fasp/uri.rb +1 -1
- data/lib/aspera/faspex_gw.rb +12 -11
- data/lib/aspera/id_generator.rb +22 -0
- 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 +9 -4
- data/lib/aspera/oauth.rb +116 -100
- data/lib/aspera/persistency_action_once.rb +11 -7
- data/lib/aspera/persistency_folder.rb +6 -26
- data/lib/aspera/rest.rb +66 -50
- data/lib/aspera/sync.rb +40 -35
- data/lib/aspera/timer_limiter.rb +22 -0
- metadata +86 -29
- data/docs/transfer_spec.html +0 -99
- data/lib/aspera/api_detector.rb +0 -60
- data/lib/aspera/fasp/aoc.rb +0 -24
- data/lib/aspera/secrets.rb +0 -20
@@ -2,19 +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'
|
9
|
+
require 'aspera/id_generator'
|
8
10
|
require 'securerandom'
|
9
|
-
require 'resolv'
|
10
11
|
require 'date'
|
11
12
|
|
12
13
|
module Aspera
|
13
14
|
module Cli
|
14
15
|
module Plugins
|
15
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
|
16
27
|
# special value for package id
|
17
28
|
VAL_ALL='ALL'
|
29
|
+
ID_AK_ADMIN='ASPERA_ACCESS_KEY_ADMIN'
|
30
|
+
|
18
31
|
def initialize(env)
|
19
32
|
super(env)
|
20
33
|
@default_workspace_id=nil
|
@@ -24,7 +37,6 @@ module Aspera
|
|
24
37
|
@home_node_file=nil
|
25
38
|
@api_aoc=nil
|
26
39
|
@url_token_data=nil
|
27
|
-
@user_info=nil
|
28
40
|
@api_aoc=nil
|
29
41
|
self.options.add_opt_list(:auth,Oauth.auth_types,'OAuth type of authentication')
|
30
42
|
self.options.add_opt_list(:operation,[:push,:pull],'client operation for transfers')
|
@@ -39,7 +51,6 @@ module Aspera
|
|
39
51
|
self.options.add_opt_simple(:new_user_option,'new user creation option')
|
40
52
|
self.options.add_opt_simple(:from_folder,'share to share source folder')
|
41
53
|
self.options.add_opt_simple(:scope,'OAuth scope for AoC API calls')
|
42
|
-
self.options.add_opt_simple(:notify,'notify users that file was received')
|
43
54
|
self.options.add_opt_boolean(:bulk,'bulk operation')
|
44
55
|
self.options.add_opt_boolean(:default_ports,'use standard FASP ports or get from node api')
|
45
56
|
self.options.set_option(:bulk,:no)
|
@@ -58,44 +69,41 @@ 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 ]
|
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
|
90
88
|
when :bearer_token_node
|
91
89
|
thepath=self.options.get_next_argument('path')
|
92
90
|
node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
|
93
|
-
node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
|
91
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER, use_secret: false)
|
94
92
|
return Main.result_status(node_api.oauth_token)
|
93
|
+
when :node_info
|
94
|
+
thepath=self.options.get_next_argument('path')
|
95
|
+
node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
|
96
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER, use_secret: false)
|
97
|
+
return {type: :single_object,data: {
|
98
|
+
url: node_file[:node_info]['url'],
|
99
|
+
username: node_file[:node_info]['access_key'],
|
100
|
+
password: node_api.oauth_token,
|
101
|
+
root_id: node_file[:file_id]
|
102
|
+
}}
|
95
103
|
when :browse
|
96
104
|
thepath=self.options.get_next_argument('path')
|
97
105
|
node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
|
98
|
-
node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
|
106
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
99
107
|
file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
|
100
108
|
if file_info['type'].eql?('folder')
|
101
109
|
result=node_api.read("files/#{node_file[:file_id]}/files",self.options.get_option(:value,:optional))
|
@@ -104,33 +112,33 @@ module Aspera
|
|
104
112
|
else
|
105
113
|
items=[file_info]
|
106
114
|
end
|
107
|
-
return {:
|
115
|
+
return {type: :object_list,data: items,fields: ['name','type','recursive_size','size','modified_time','access_level']}
|
108
116
|
when :find
|
109
117
|
thepath=self.options.get_next_argument('path')
|
110
118
|
node_file=@api_aoc.resolve_node_file(top_node_file,thepath)
|
111
119
|
test_block=Aspera::Node.file_matcher(self.options.get_option(:value,:optional))
|
112
|
-
return {:
|
120
|
+
return {type: :object_list,data: @api_aoc.find_files(node_file,test_block),fields: ['path']}
|
113
121
|
when :mkdir
|
114
122
|
thepath=self.options.get_next_argument('path')
|
115
123
|
containing_folder_path = thepath.split(AoC::PATH_SEPARATOR)
|
116
124
|
new_folder=containing_folder_path.pop
|
117
125
|
node_file = @api_aoc.resolve_node_file(top_node_file,containing_folder_path.join(AoC::PATH_SEPARATOR))
|
118
|
-
node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
|
119
|
-
result=node_api.create("files/#{node_file[:file_id]}/files",{:
|
126
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
127
|
+
result=node_api.create("files/#{node_file[:file_id]}/files",{name: new_folder,type: :folder})[:data]
|
120
128
|
return Main.result_status("created: #{result['name']} (id=#{result['id']})")
|
121
129
|
when :rename
|
122
130
|
thepath=self.options.get_next_argument('source path')
|
123
131
|
newname=self.options.get_next_argument('new name')
|
124
132
|
node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
|
125
|
-
node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
|
126
|
-
result=node_api.update("files/#{node_file[:file_id]}",{:
|
133
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
134
|
+
result=node_api.update("files/#{node_file[:file_id]}",{name: newname})[:data]
|
127
135
|
return Main.result_status("renamed #{thepath} to #{newname}")
|
128
136
|
when :delete
|
129
137
|
thepath=self.options.get_next_argument('path')
|
130
138
|
return do_bulk_operation(thepath,'deleted','path') do |l_path|
|
131
139
|
raise "expecting String (path), got #{l_path.class.name} (#{l_path})" unless l_path.is_a?(String)
|
132
140
|
node_file = @api_aoc.resolve_node_file(top_node_file,l_path)
|
133
|
-
node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
|
141
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
134
142
|
result=node_api.delete("files/#{node_file[:file_id]}")[:data]
|
135
143
|
{'path'=>l_path}
|
136
144
|
end
|
@@ -153,7 +161,13 @@ module Aspera
|
|
153
161
|
client_node_file = @api_aoc.resolve_node_file(client_home_node_file,client_folder)
|
154
162
|
server_node_file = @api_aoc.resolve_node_file(server_home_node_file,server_folder)
|
155
163
|
# force node as transfer agent
|
156
|
-
|
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
|
+
}))
|
157
171
|
# additional node to node TS info
|
158
172
|
add_ts={
|
159
173
|
'remote_access_key' => server_node_file[:node_info]['access_key'],
|
@@ -191,37 +205,37 @@ module Aspera
|
|
191
205
|
raise CliBadArgument,'one file at a time only in HTTP mode' if source_paths.length > 1
|
192
206
|
file_name = source_paths.first['source']
|
193
207
|
node_file = @api_aoc.resolve_node_file(top_node_file,File.join(source_folder,file_name))
|
194
|
-
node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
|
195
|
-
node_api.call({:
|
208
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
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)})
|
196
210
|
return Main.result_status("downloaded: #{file_name}")
|
197
211
|
when :v3
|
198
|
-
# Note: other
|
212
|
+
# Note: other common actions are unauthorized with user scope
|
199
213
|
command_legacy=self.options.get_next_command(Node::SIMPLE_ACTIONS)
|
200
214
|
# TODO: shall we support all methods here ? what if there is a link ?
|
201
|
-
node_api=@api_aoc.get_node_api(top_node_file[:node_info],AoC::SCOPE_NODE_USER)
|
215
|
+
node_api=@api_aoc.get_node_api(top_node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
202
216
|
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: node_api)).execute_action(command_legacy)
|
203
217
|
when :file
|
218
|
+
command_node_file=self.options.get_next_command([:show,:permission,:modify])
|
204
219
|
file_path=self.options.get_option(:path,:optional)
|
205
220
|
node_file = if !file_path.nil?
|
206
221
|
@api_aoc.resolve_node_file(top_node_file,file_path) # TODO: allow follow link ?
|
207
222
|
else
|
208
|
-
{node_info: top_node_file[:node_info],file_id: self.
|
223
|
+
{node_info: top_node_file[:node_info],file_id: self.instance_identifier()}
|
209
224
|
end
|
210
|
-
node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
|
211
|
-
command_node_file=self.options.get_next_command([:show,:permission,:modify])
|
225
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
212
226
|
case command_node_file
|
213
227
|
when :show
|
214
228
|
items=node_api.read("files/#{node_file[:file_id]}")[:data]
|
215
|
-
return {:
|
229
|
+
return {type: :single_object,data: items}
|
216
230
|
when :modify
|
217
|
-
update_param=self.options.get_next_argument(
|
231
|
+
update_param=self.options.get_next_argument('update data (Hash)')
|
218
232
|
res=node_api.update("files/#{node_file[:file_id]}",update_param)[:data]
|
219
|
-
return {:
|
233
|
+
return {type: :single_object,data: res}
|
220
234
|
when :permission
|
221
235
|
command_perm=self.options.get_next_command([:list,:create])
|
222
236
|
case command_perm
|
223
237
|
when :list
|
224
|
-
# generic options : TODO: as arg ?
|
238
|
+
# generic options : TODO: as arg ? option_url_query
|
225
239
|
list_options||={'include'=>['[]','access_level','permission_count']}
|
226
240
|
# special value: ALL will show all permissions
|
227
241
|
if !VAL_ALL.eql?(node_file[:file_id])
|
@@ -229,13 +243,12 @@ module Aspera
|
|
229
243
|
list_options['file_id']=node_file[:file_id]
|
230
244
|
list_options['inherited']||=false
|
231
245
|
end
|
232
|
-
#option_url_query
|
233
246
|
items=node_api.read('permissions',list_options)[:data]
|
234
|
-
return {:
|
247
|
+
return {type: :object_list,data: items}
|
235
248
|
when :create
|
236
|
-
#create_param=self.options.get_next_argument(
|
249
|
+
#create_param=self.options.get_next_argument('creation data (Hash)')
|
237
250
|
set_workspace_info
|
238
|
-
access_id="
|
251
|
+
access_id="#{ID_AK_ADMIN}_WS_#{@workspace_id}"
|
239
252
|
node_file[:node_info]
|
240
253
|
params={
|
241
254
|
'file_id' =>node_file[:file_id], # mandatory
|
@@ -245,25 +258,23 @@ module Aspera
|
|
245
258
|
'tags' =>{'aspera'=>{'files'=>{'workspace'=>{
|
246
259
|
'id' =>@workspace_id,
|
247
260
|
'workspace_name' =>@workspace_name,
|
248
|
-
'user_name'
|
249
|
-
'shared_by_user_id'
|
250
|
-
'shared_by_name'
|
251
|
-
'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'],
|
252
265
|
'shared_with_name' =>access_id,
|
253
266
|
'access_key' =>node_file[:node_info]['access_key'],
|
254
267
|
'node' =>node_file[:node_info]['name']}}}}}
|
255
268
|
item=node_api.create('permissions',params)[:data]
|
256
|
-
return {:
|
269
|
+
return {type: :single_object,data: item}
|
257
270
|
else raise "internal error:shall not reach here (#{command_perm})"
|
258
271
|
end
|
259
|
-
raise
|
272
|
+
raise 'internal error:shall not reach here'
|
260
273
|
else raise "internal error:shall not reach here (#{command_node_file})"
|
261
274
|
end
|
262
|
-
raise
|
263
|
-
when :permissions
|
264
|
-
|
275
|
+
raise 'internal error:shall not reach here'
|
265
276
|
end # command_repo
|
266
|
-
raise
|
277
|
+
raise 'ERR'
|
267
278
|
end # execute_node_gen4_command
|
268
279
|
|
269
280
|
# build constructor option list for AoC based on options of CLI
|
@@ -288,21 +299,21 @@ module Aspera
|
|
288
299
|
@default_workspace_id=@url_token_data['data']['workspace_id']
|
289
300
|
@persist_ids=[] # TODO : @url_token_data['id'] ?
|
290
301
|
else
|
291
|
-
@default_workspace_id
|
292
|
-
@persist_ids=[
|
302
|
+
@default_workspace_id=@api_aoc.user_info['default_workspace_id']
|
303
|
+
@persist_ids=[@api_aoc.user_info['id']]
|
293
304
|
end
|
294
305
|
|
295
306
|
ws_name=self.options.get_option(:workspace,:optional)
|
296
307
|
if ws_name.nil?
|
297
|
-
Log.log.debug(
|
308
|
+
Log.log.debug('using default workspace'.green)
|
298
309
|
if @default_workspace_id.eql?(nil)
|
299
|
-
raise CliError,
|
310
|
+
raise CliError,'no default workspace defined for user, please specify workspace'
|
300
311
|
end
|
301
312
|
# get default workspace
|
302
313
|
@workspace_id=@default_workspace_id
|
303
314
|
else
|
304
315
|
# lookup another workspace
|
305
|
-
wss=@api_aoc.read(
|
316
|
+
wss=@api_aoc.read('workspaces',{'q'=>ws_name})[:data]
|
306
317
|
wss=wss.select { |i| i['name'].eql?(ws_name) }
|
307
318
|
case wss.length
|
308
319
|
when 0
|
@@ -310,14 +321,14 @@ module Aspera
|
|
310
321
|
when 1
|
311
322
|
@workspace_id=wss.first['id']
|
312
323
|
else
|
313
|
-
raise
|
324
|
+
raise 'unexpected case'
|
314
325
|
end
|
315
326
|
end
|
316
327
|
@workspace_data=@api_aoc.read("workspaces/#{@workspace_id}")[:data]
|
317
328
|
Log.log.debug("workspace_id=#{@workspace_id},@workspace_data=#{@workspace_data}".red)
|
318
329
|
|
319
330
|
@workspace_name||=@workspace_data['name']
|
320
|
-
Log.log.info(
|
331
|
+
Log.log.info('current workspace is '+@workspace_name.red)
|
321
332
|
|
322
333
|
# display workspace
|
323
334
|
self.format.display_status("Current Workspace: #{@workspace_name.red}#{@workspace_id == @default_workspace_id ? ' (default)' : ''}")
|
@@ -333,7 +344,7 @@ module Aspera
|
|
333
344
|
end
|
334
345
|
home_node_id||=@workspace_data['home_node_id']||@workspace_data['node_id']
|
335
346
|
home_file_id||=@workspace_data['home_file_id']
|
336
|
-
raise
|
347
|
+
raise 'node_id must be defined' if home_node_id.to_s.empty?
|
337
348
|
@home_node_file={
|
338
349
|
node_info: @api_aoc.read("nodes/#{home_node_id}")[:data],
|
339
350
|
file_id: home_file_id
|
@@ -345,7 +356,7 @@ module Aspera
|
|
345
356
|
|
346
357
|
def do_bulk_operation(ids_or_one,success_msg,id_result='id',&do_action)
|
347
358
|
ids_or_one=[ids_or_one] unless self.options.get_option(:bulk)
|
348
|
-
raise
|
359
|
+
raise 'expecting Array' unless ids_or_one.is_a?(Array)
|
349
360
|
result_list=[]
|
350
361
|
ids_or_one.each do |id|
|
351
362
|
one={id_result=>id}
|
@@ -358,7 +369,27 @@ module Aspera
|
|
358
369
|
end
|
359
370
|
result_list.push(one)
|
360
371
|
end
|
361
|
-
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
|
362
393
|
end
|
363
394
|
|
364
395
|
# package creation params can give just email, and full hash is created
|
@@ -366,42 +397,44 @@ module Aspera
|
|
366
397
|
return unless package_creation.has_key?(recipient_list_field)
|
367
398
|
raise CliBadArgument,"#{recipient_list_field} must be an Array" unless package_creation[recipient_list_field].is_a?(Array)
|
368
399
|
new_user_option=self.options.get_option(:new_user_option,:mandatory)
|
400
|
+
# list with resolved elements
|
369
401
|
resolved_list=[]
|
370
|
-
package_creation[recipient_list_field].each do |
|
371
|
-
case
|
372
|
-
when Hash
|
373
|
-
raise
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
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}"
|
384
417
|
end
|
385
|
-
|
418
|
+
end
|
419
|
+
if entity_type.eql?('dropboxes')
|
420
|
+
short_recipient_info={'id'=>full_recipient_info['id'],'type'=>'dropbox'}
|
386
421
|
else
|
387
|
-
|
388
|
-
case item_lookup.length
|
389
|
-
when 1; recipient_user_id=item_lookup.first
|
390
|
-
when 0; raise "no such shared inbox in workspace #{@workspace_name}"
|
391
|
-
else raise CliBadArgument,"multiple match for: #{recipient_email_or_info}"
|
392
|
-
end
|
393
|
-
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']}
|
394
423
|
end
|
395
|
-
else
|
396
|
-
raise "
|
397
|
-
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)
|
398
429
|
end
|
430
|
+
# replace with resolved elements
|
399
431
|
package_creation[recipient_list_field]=resolved_list
|
400
432
|
end
|
401
433
|
|
402
434
|
# private
|
403
435
|
def option_url_query(default)
|
404
|
-
query=self.options.get_option(:query,:optional)
|
436
|
+
query=self.options.get_option(:query,:optional)
|
437
|
+
query=default if query.nil?
|
405
438
|
Log.log.debug("Query=#{query}".bg_red)
|
406
439
|
begin
|
407
440
|
# check it is suitable
|
@@ -418,6 +451,37 @@ module Aspera
|
|
418
451
|
end
|
419
452
|
end
|
420
453
|
|
454
|
+
# Call @api_aoc.read with same parameters, but use paging if necessary to get all results
|
455
|
+
def read_with_paging(resource_class_path,base_query)
|
456
|
+
raise "Query must be Hash" unless base_query.is_a?(Hash)
|
457
|
+
# set default large page if user does not specify own parameters. AoC Caps to 1000 anyway
|
458
|
+
base_query['per_page']=1000 unless base_query.has_key?('per_page')
|
459
|
+
max_items=base_query[MAX_ITEMS]
|
460
|
+
base_query.delete(MAX_ITEMS)
|
461
|
+
max_pages=base_query[MAX_PAGES]
|
462
|
+
base_query.delete(MAX_PAGES)
|
463
|
+
item_list=[]
|
464
|
+
total_count=nil
|
465
|
+
current_page=base_query['page']
|
466
|
+
current_page=1 if current_page.nil?
|
467
|
+
page_count=0
|
468
|
+
loop do
|
469
|
+
query=base_query.clone
|
470
|
+
query['page']=current_page
|
471
|
+
result=@api_aoc.read(resource_class_path,query)
|
472
|
+
total_count=result[:http]['X-Total-Count']
|
473
|
+
page_count+=1
|
474
|
+
current_page+=1
|
475
|
+
add_items=result[:data]
|
476
|
+
break if add_items.empty?
|
477
|
+
# append new items to full list
|
478
|
+
item_list += add_items
|
479
|
+
break if !max_pages.nil? and page_count > max_pages
|
480
|
+
break if !max_items.nil? and item_list.count > max_items
|
481
|
+
end
|
482
|
+
return item_list,total_count
|
483
|
+
end
|
484
|
+
|
421
485
|
def execute_admin_action
|
422
486
|
@api_aoc.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
|
423
487
|
command_admin=self.options.get_next_command([ :ats, :resource, :usage_reports, :analytics, :subscription, :auth_providers ])
|
@@ -427,7 +491,7 @@ module Aspera
|
|
427
491
|
case command_auth_prov
|
428
492
|
when :list
|
429
493
|
providers=@api_aoc.read('admin/auth_providers')[:data]
|
430
|
-
return {:
|
494
|
+
return {type: :object_list,data: providers}
|
431
495
|
when :update
|
432
496
|
end
|
433
497
|
when :subscription
|
@@ -482,43 +546,43 @@ module Aspera
|
|
482
546
|
}
|
483
547
|
"
|
484
548
|
result=bss_api.create('graphql',{'variables'=>{'organization_id'=>org['id']},'query'=>graphql_query})[:data]['data']
|
485
|
-
return {:
|
549
|
+
return {type: :single_object,data: result['aoc']['bssSubscription']}
|
486
550
|
when :ats
|
487
551
|
ats_api = Rest.new(@api_aoc.params.deep_merge({
|
488
|
-
:
|
489
|
-
:
|
552
|
+
base_url: @api_aoc.params[:base_url]+'/admin/ats/pub/v1',
|
553
|
+
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
490
554
|
}))
|
491
555
|
return Ats.new(@agents).execute_action_gen(ats_api)
|
492
556
|
when :analytics
|
493
557
|
analytics_api = Rest.new(@api_aoc.params.deep_merge({
|
494
|
-
:
|
495
|
-
:
|
558
|
+
base_url: @api_aoc.params[:base_url].gsub('/api/v1','')+'/analytics/v2',
|
559
|
+
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
496
560
|
}))
|
497
561
|
command_analytics=self.options.get_next_command([ :application_events, :transfers ])
|
498
562
|
case command_analytics
|
499
563
|
when :application_events
|
500
564
|
event_type=command_analytics.to_s
|
501
|
-
events=analytics_api.read("organizations/#{
|
502
|
-
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}
|
503
567
|
when :transfers
|
504
568
|
event_type=command_analytics.to_s
|
505
569
|
filter_resource=self.options.get_option(:name,:optional) || 'organizations'
|
506
570
|
filter_id=self.options.get_option(:id,:optional) || case filter_resource
|
507
|
-
when 'organizations';
|
508
|
-
when 'users';
|
509
|
-
when 'nodes';
|
510
|
-
else raise
|
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']
|
574
|
+
else raise 'organizations or users for option --name'
|
511
575
|
end
|
512
576
|
#
|
513
577
|
filter=self.options.get_option(:query,:optional) || {}
|
514
|
-
raise
|
578
|
+
raise 'query must be Hash' unless filter.is_a?(Hash)
|
515
579
|
filter['limit']||=100
|
516
580
|
if self.options.get_option(:once_only,:mandatory)
|
517
581
|
saved_date=[]
|
518
582
|
startdate_persistency=PersistencyActionOnce.new(
|
519
583
|
manager: @agents[:persistency],
|
520
584
|
data: saved_date,
|
521
|
-
ids:
|
585
|
+
ids: IdGenerator.from_list(['aoc_ana_date',self.options.get_option(:url,:mandatory),@workspace_name].push(filter_resource,filter_id)))
|
522
586
|
start_datetime=saved_date.first
|
523
587
|
stop_datetime=Time.now.utc.strftime('%FT%T.%LZ')
|
524
588
|
#Log.log().error("start: #{start_datetime}")
|
@@ -527,38 +591,26 @@ module Aspera
|
|
527
591
|
filter['start_time'] = start_datetime unless start_datetime.nil?
|
528
592
|
filter['stop_time'] = stop_datetime
|
529
593
|
end
|
530
|
-
notification=self.options.get_option(:notify,:optional)
|
531
594
|
events=analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",option_url_query(filter))[:data][event_type]
|
532
595
|
startdate_persistency.save unless startdate_persistency.nil?
|
533
|
-
if !
|
534
|
-
|
535
|
-
|
536
|
-
email_to_send={}
|
537
|
-
notification.each do |k,v|
|
538
|
-
email_to_send[k.to_sym]=ERB.new(v).result(binding)
|
539
|
-
end
|
540
|
-
Log.log().error("send email: #{email_to_send}")
|
541
|
-
self.config.send_email(email_to_send)
|
596
|
+
if !self.options.get_option(:notif_to,:optional).nil?
|
597
|
+
events.each do |tr_event|
|
598
|
+
self.config.send_email_template({ev: tr_event})
|
542
599
|
end
|
543
600
|
end
|
544
|
-
return {:
|
601
|
+
return {type: :object_list,data: events}
|
545
602
|
end
|
546
603
|
when :resource
|
547
|
-
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,:
|
548
|
-
# get path on API
|
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])
|
605
|
+
# get path on API, resource type is singular, but api is plural
|
549
606
|
resource_class_path=case resource_type
|
550
|
-
|
551
|
-
|
552
|
-
when :
|
553
|
-
|
554
|
-
when :dropbox
|
555
|
-
|
556
|
-
|
557
|
-
"admin/#{resource_type}s"
|
558
|
-
when :kms_profile
|
559
|
-
"integrations/#{resource_type}s"
|
560
|
-
else
|
561
|
-
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'
|
562
614
|
end
|
563
615
|
# build list of supported operations
|
564
616
|
singleton_object=[:self,:organization].include?(resource_type)
|
@@ -573,19 +625,14 @@ module Aspera
|
|
573
625
|
if !singleton_object and !global_operations.include?(command)
|
574
626
|
res_id=self.options.get_option(:id)
|
575
627
|
res_name=self.options.get_option(:name)
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
matching=@api_aoc.read(resource_class_path,{:q=>res_name})[:data]
|
584
|
-
raise CliError,"no resource match name" if matching.empty?
|
585
|
-
raise CliError,"several resources match name (#{matching.join(',')})" unless matching.length.eql?(1)
|
586
|
-
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')
|
587
635
|
end
|
588
|
-
raise CliBadArgument,"provide either id or name" if res_id.nil?
|
589
636
|
resource_instance_path="#{resource_class_path}/#{res_id}"
|
590
637
|
end
|
591
638
|
resource_instance_path=resource_class_path if singleton_object
|
@@ -595,30 +642,33 @@ module Aspera
|
|
595
642
|
id_result='token' if resource_class_path.eql?('admin/client_registration_tokens')
|
596
643
|
# TODO: report inconsistency: creation url is !=, and does not return id.
|
597
644
|
resource_class_path='admin/client_registration/token' if resource_class_path.eql?('admin/client_registration_tokens')
|
598
|
-
list_or_one=self.options.get_next_argument(
|
645
|
+
list_or_one=self.options.get_next_argument('creation data (Hash)')
|
599
646
|
return do_bulk_operation(list_or_one,'created',id_result)do|params|
|
600
|
-
raise
|
647
|
+
raise 'expecting Hash' unless params.is_a?(Hash)
|
601
648
|
@api_aoc.create(resource_class_path,params)[:data]
|
602
649
|
end
|
603
650
|
when :list
|
604
|
-
default_fields=['id'
|
605
|
-
|
651
|
+
default_fields=['id']
|
652
|
+
default_query={}
|
606
653
|
case resource_type
|
607
|
-
when :
|
654
|
+
when :application; default_query={organization_apps: true};default_fields.push('app_type','app_name','available','direct_authorizations_allowed','workspace_authorizations_allowed')
|
655
|
+
when :client,:client_access_key,:dropbox,:group,:package,:saml_configuration,:workspace; default_fields.push('name')
|
656
|
+
when :client_registration_token; default_fields.push('value','data.client_subject_scopes','created_at')
|
657
|
+
when :contact; default_fields=['email','name','source_id','source_type']
|
658
|
+
when :node; default_fields.push('name','host','access_key')
|
608
659
|
when :operation; default_fields=nil
|
609
|
-
when :
|
610
|
-
when :
|
611
|
-
when :client_registration_token; default_fields=['id','value','data.client_subject_scopes','created_at']
|
660
|
+
when :short_link; default_fields.push('short_url','data.url_token_data.purpose')
|
661
|
+
when :user; default_fields.push('name','email')
|
612
662
|
end
|
613
|
-
|
614
|
-
count_msg="Items: #{
|
615
|
-
count_msg=count_msg.bg_red unless
|
663
|
+
item_list,total_count=read_with_paging(resource_class_path,option_url_query(default_query))
|
664
|
+
count_msg="Items: #{item_list.length}/#{total_count}"
|
665
|
+
count_msg=count_msg.bg_red unless item_list.length.eql?(total_count.to_i)
|
616
666
|
self.format.display_status(count_msg)
|
617
|
-
return {:
|
667
|
+
return {type: :object_list,data: item_list,fields: default_fields}
|
618
668
|
when :show
|
619
669
|
object=@api_aoc.read(resource_instance_path)[:data]
|
620
670
|
fields=object.keys.select{|k|!k.eql?('certificate')}
|
621
|
-
return { :
|
671
|
+
return { type: :single_object, data: object, fields: fields }
|
622
672
|
when :modify
|
623
673
|
changes=self.options.get_next_argument('modified parameters (hash)')
|
624
674
|
@api_aoc.update(resource_instance_path,changes)
|
@@ -632,20 +682,20 @@ module Aspera
|
|
632
682
|
# special : reads private and generate public
|
633
683
|
the_private_key=self.options.get_next_argument('private_key')
|
634
684
|
the_public_key=OpenSSL::PKey::RSA.new(the_private_key).public_key.to_s
|
635
|
-
@api_aoc.update(resource_instance_path,{:
|
685
|
+
@api_aoc.update(resource_instance_path,{jwt_grant_enabled: true, public_key: the_public_key})
|
636
686
|
return Main.result_success
|
637
687
|
when :v3,:v4
|
638
688
|
res_data=@api_aoc.read(resource_instance_path)[:data]
|
639
689
|
api_node=@api_aoc.get_node_api(res_data)
|
640
690
|
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action if command.eql?(:v3)
|
641
|
-
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]
|
642
692
|
command_repo=self.options.get_next_command(NODE4_COMMANDS)
|
643
693
|
return execute_node_gen4_command(command_repo,{node_info: res_data, file_id: ak_data['root_file_id']})
|
644
694
|
when :shared_folders
|
645
695
|
read_params = case resource_type
|
646
|
-
when :workspace;{'access_id'=>"
|
647
|
-
when :node;{'include'=>['[]','access_level','permission_count'],'created_by_id'=>
|
648
|
-
else raise
|
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}
|
698
|
+
else raise 'error'
|
649
699
|
end
|
650
700
|
res_data=@api_aoc.read("#{resource_class_path}/#{res_id}/permissions",read_params)[:data]
|
651
701
|
fields=case resource_type
|
@@ -653,18 +703,18 @@ module Aspera
|
|
653
703
|
when :workspace;['id','node_id','file_id','node_name','file.path','tags.aspera.files.workspace.share_as']
|
654
704
|
else raise "unexpected resource type #{resource_type}"
|
655
705
|
end
|
656
|
-
return { :
|
706
|
+
return { type: :object_list, data: res_data , fields: fields}
|
657
707
|
when :shared_create
|
658
|
-
# TODO
|
708
|
+
# TODO: finish implementation
|
659
709
|
folder_path=self.options.get_next_argument('folder path in node')
|
660
710
|
user_create_data=self.options.get_next_argument('creation data (Hash)')
|
661
711
|
res_data=@api_aoc.read(resource_instance_path)[:data]
|
662
712
|
node_file = @api_aoc.resolve_node_file({node_info: res_data, file_id: ak_data['root_file_id']},folder_path)
|
663
713
|
|
664
|
-
#node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
|
714
|
+
#node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
665
715
|
#file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
|
666
716
|
|
667
|
-
access_id="
|
717
|
+
access_id="#{ID_AK_ADMIN}_WS_#{@workspace_id}"
|
668
718
|
create_data={
|
669
719
|
'file_id' =>node_file[:file_id],
|
670
720
|
'access_type' =>'user',
|
@@ -674,10 +724,10 @@ module Aspera
|
|
674
724
|
'id' =>@workspace_id,
|
675
725
|
'workspace_name' =>@workspace_name,
|
676
726
|
'share_as' =>File.basename(folder_path),
|
677
|
-
'user_name'
|
678
|
-
'shared_by_user_id'
|
679
|
-
'shared_by_name'
|
680
|
-
'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'],
|
681
731
|
'shared_with_name' =>access_id,
|
682
732
|
'access_key' =>node_file[:node_info]['access_key'],
|
683
733
|
'node' =>node_file[:node_info]['name']}
|
@@ -685,15 +735,15 @@ module Aspera
|
|
685
735
|
create_data.deep_merge!(user_create_data)
|
686
736
|
Log.dump(:data,create_data)
|
687
737
|
raise :ERROR
|
688
|
-
else raise
|
738
|
+
else raise 'unknown command'
|
689
739
|
end
|
690
740
|
when :usage_reports
|
691
|
-
return {:
|
741
|
+
return {type: :object_list,data: @api_aoc.read('usage_reports',{workspace_id: @workspace_id})[:data]}
|
692
742
|
end
|
693
743
|
end
|
694
744
|
|
695
745
|
# must be public
|
696
|
-
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
|
697
747
|
|
698
748
|
def execute_action
|
699
749
|
command=self.options.get_next_command(ACTIONS)
|
@@ -705,38 +755,38 @@ module Aspera
|
|
705
755
|
Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").create('organization_reminders',{email: user_email})[:data]
|
706
756
|
return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
|
707
757
|
when :bearer_token
|
708
|
-
return {:
|
758
|
+
return {type: :text,data: @api_aoc.oauth_token}
|
709
759
|
when :organization
|
710
|
-
return { :
|
760
|
+
return { type: :single_object, data: @api_aoc.read('organization')[:data] }
|
711
761
|
when :tier_restrictions
|
712
|
-
return { :
|
762
|
+
return { type: :single_object, data: @api_aoc.read('tier_restrictions')[:data] }
|
713
763
|
when :user
|
714
764
|
command=self.options.get_next_command([ :workspaces,:info,:shared_inboxes ])
|
715
765
|
case command
|
716
766
|
when :workspaces
|
717
|
-
return {:
|
767
|
+
return {type: :object_list,data: @api_aoc.read('workspaces')[:data],fields: ['id','name']}
|
718
768
|
# when :settings
|
719
|
-
# return {:
|
769
|
+
# return {type: :object_list,data: @api_aoc.read('client_settings/')[:data]}
|
720
770
|
when :shared_inboxes
|
721
771
|
query=option_url_query(nil)
|
722
772
|
if query.nil?
|
723
773
|
set_workspace_info
|
724
774
|
query={'embed[]'=>'dropbox','workspace_id'=>@workspace_id,'aggregate_permissions_by_dropbox'=>true,'sort'=>'dropbox_name'}
|
725
775
|
end
|
726
|
-
return {:
|
776
|
+
return {type: :object_list,data: @api_aoc.read('dropbox_memberships',query)[:data],fields: ['dropbox_id','dropbox.name']}
|
727
777
|
when :info
|
728
778
|
command=self.options.get_next_command([ :show,:modify ])
|
729
779
|
case command
|
730
780
|
when :show
|
731
|
-
return { :
|
781
|
+
return { type: :single_object, data: @api_aoc.user_info }
|
732
782
|
when :modify
|
733
|
-
@api_aoc.update("users/#{
|
783
|
+
@api_aoc.update("users/#{@api_aoc.user_info['id']}",self.options.get_next_argument('modified parameters (hash)'))
|
734
784
|
return Main.result_status('modified')
|
735
785
|
end
|
736
786
|
end
|
737
787
|
when :workspace # show current workspace parameters
|
738
788
|
set_workspace_info
|
739
|
-
return { :
|
789
|
+
return { type: :single_object, data: @workspace_data }
|
740
790
|
when :packages
|
741
791
|
set_workspace_info if @url_token_data.nil?
|
742
792
|
command_pkg=self.options.get_next_command([ :send, :recv, :list, :show, :delete ])
|
@@ -761,7 +811,7 @@ module Aspera
|
|
761
811
|
resolve_package_recipients(package_creation,'recipients')
|
762
812
|
resolve_package_recipients(package_creation,'bcc_recipients')
|
763
813
|
|
764
|
-
# create a new package
|
814
|
+
# create a new package container
|
765
815
|
package_info=@api_aoc.create('packages',package_creation)[:data]
|
766
816
|
|
767
817
|
# get node information for the node on which package must be created
|
@@ -772,24 +822,24 @@ module Aspera
|
|
772
822
|
|
773
823
|
# execute transfer
|
774
824
|
node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
|
775
|
-
# raise
|
825
|
+
# raise exception if at least one error
|
776
826
|
Main.result_transfer(transfer_start(AoC::PACKAGES_APP,'send',node_file,AoC.package_tags(package_info,'upload')))
|
777
827
|
# return all info on package
|
778
|
-
return { :
|
828
|
+
return { type: :single_object, data: package_info}
|
779
829
|
when :recv
|
780
830
|
if !@url_token_data.nil?
|
781
831
|
assert_public_link_types(['view_received_package'])
|
782
832
|
self.options.set_option(:id,@url_token_data['data']['package_id'])
|
783
833
|
end
|
784
834
|
# scalar here
|
785
|
-
ids_to_download=self.
|
835
|
+
ids_to_download=self.instance_identifier()
|
786
836
|
skip_ids_data=[]
|
787
837
|
skip_ids_persistency=nil
|
788
838
|
if self.options.get_option(:once_only,:mandatory)
|
789
839
|
skip_ids_persistency=PersistencyActionOnce.new(
|
790
840
|
manager: @agents[:persistency],
|
791
841
|
data: skip_ids_data,
|
792
|
-
|
842
|
+
id: IdGenerator.from_list(['aoc_recv',self.options.get_option(:url,:mandatory),@workspace_id].push(*@persist_ids)))
|
793
843
|
end
|
794
844
|
if ids_to_download.eql?(VAL_ALL)
|
795
845
|
# get list of packages in inbox
|
@@ -810,24 +860,26 @@ module Aspera
|
|
810
860
|
add_ts={'paths'=>[{'source'=>'.'}]}
|
811
861
|
node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
|
812
862
|
statuses=transfer_start(AoC::PACKAGES_APP,'receive',node_file,AoC.package_tags(package_info,'download').merge(add_ts))
|
813
|
-
result_transfer.push({'package'=>package_id,
|
863
|
+
result_transfer.push({'package'=>package_id,Main::STATUS_FIELD=>statuses})
|
814
864
|
# update skip list only if all transfer sessions completed
|
815
865
|
if TransferAgent.session_status(statuses).eql?(:success)
|
816
866
|
skip_ids_data.push(package_id)
|
817
867
|
skip_ids_persistency.save unless skip_ids_persistency.nil?
|
818
868
|
end
|
819
869
|
end
|
820
|
-
return
|
870
|
+
return Main.result_transfer_multiple(result_transfer)
|
821
871
|
when :show
|
822
872
|
package_id=self.options.get_next_argument('package ID')
|
823
873
|
package_info=@api_aoc.read("packages/#{package_id}")[:data]
|
824
|
-
return { :
|
874
|
+
return { type: :single_object, data: package_info }
|
825
875
|
when :list
|
826
|
-
|
827
|
-
|
828
|
-
|
876
|
+
query=option_url_query({'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true})
|
877
|
+
raise 'option must be Hash' unless query.is_a?(Hash)
|
878
|
+
query['workspace_id']||=@workspace_id
|
879
|
+
packages=@api_aoc.read('packages',query)[:data]
|
880
|
+
return {type: :object_list,data: packages,fields: ['id','name','bytes_transferred']}
|
829
881
|
when :delete
|
830
|
-
list_or_one=self.
|
882
|
+
list_or_one=self.instance_identifier()
|
831
883
|
return do_bulk_operation(list_or_one,'deleted')do|id|
|
832
884
|
raise 'expecting String identifier' unless id.is_a?(String) or id.is_a?(Integer)
|
833
885
|
@api_aoc.delete("packages/#{id}")[:data]
|
@@ -837,7 +889,7 @@ module Aspera
|
|
837
889
|
# get workspace related information
|
838
890
|
set_workspace_info
|
839
891
|
set_home_node_file
|
840
|
-
command_repo=self.options.get_next_command(NODE4_COMMANDS
|
892
|
+
command_repo=self.options.get_next_command([NODE4_COMMANDS,:short_link].flatten)
|
841
893
|
case command_repo
|
842
894
|
when *NODE4_COMMANDS; return execute_node_gen4_command(command_repo,@home_node_file)
|
843
895
|
when :short_link
|
@@ -883,7 +935,7 @@ module Aspera
|
|
883
935
|
end
|
884
936
|
result=self.entity_action(@api_aoc,'short_links',nil,:id,'self')
|
885
937
|
if result[:data].is_a?(Hash) and result[:data].has_key?('created_at') and result[:data]['resource_type'].eql?('UrlToken')
|
886
|
-
node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
|
938
|
+
node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
|
887
939
|
# TODO: access level as arg
|
888
940
|
access_levels=Aspera::Node::ACCESS_LEVELS #['delete','list','mkdir','preview','read','rename','write']
|
889
941
|
perm_data={
|
@@ -896,8 +948,8 @@ module Aspera
|
|
896
948
|
'workspace_id' =>@workspace_id,
|
897
949
|
'workspace_name' =>@workspace_name,
|
898
950
|
'folder_name' =>'my folder',
|
899
|
-
'created_by_name'
|
900
|
-
'created_by_email'
|
951
|
+
'created_by_name' =>@api_aoc.user_info['name'],
|
952
|
+
'created_by_email'=>@api_aoc.user_info['email'],
|
901
953
|
'access_key' =>node_file[:node_info]['access_key'],
|
902
954
|
'node' =>node_file[:node_info]['host']
|
903
955
|
}
|
@@ -907,9 +959,9 @@ module Aspera
|
|
907
959
|
end
|
908
960
|
return result
|
909
961
|
end # files command
|
910
|
-
throw
|
962
|
+
throw 'Error: shall not reach this line'
|
911
963
|
when :automation
|
912
|
-
Log.log.warn(
|
964
|
+
Log.log.warn('BETA: work under progress')
|
913
965
|
# automation api is not in the same place
|
914
966
|
automation_rest_params=@api_aoc.params.clone
|
915
967
|
automation_rest_params[:base_url].gsub!('/api/','/automation/')
|
@@ -925,18 +977,18 @@ module Aspera
|
|
925
977
|
when *Plugin::ALL_OPS
|
926
978
|
return self.entity_command(wf_command,automation_api,'workflows',nil,:id)
|
927
979
|
when :launch
|
928
|
-
wf_id=self.
|
980
|
+
wf_id=self.instance_identifier()
|
929
981
|
data=automation_api.create("workflows/#{wf_id}/launch",{})[:data]
|
930
|
-
return {:
|
982
|
+
return {type: :single_object,data: data}
|
931
983
|
when :action
|
932
984
|
wf_command=self.options.get_next_command([:list,:create,:show])
|
933
|
-
wf_id=self.
|
985
|
+
wf_id=self.instance_identifier()
|
934
986
|
step=automation_api.create('steps',{'workflow_id'=>wf_id})[:data]
|
935
|
-
automation_api.update("workflows/#{wf_id}",{'step_order'=>[step[
|
936
|
-
action=automation_api.create('actions',{'step_id'=>step[
|
937
|
-
automation_api.update("steps/#{step[
|
987
|
+
automation_api.update("workflows/#{wf_id}",{'step_order'=>[step['id']]})
|
988
|
+
action=automation_api.create('actions',{'step_id'=>step['id'],'type'=>'manual'})[:data]
|
989
|
+
automation_api.update("steps/#{step['id']}",{'action_order'=>[action['id']]})
|
938
990
|
wf=automation_api.read("workflows/#{wf_id}")[:data]
|
939
|
-
return {:
|
991
|
+
return {type: :single_object,data: wf}
|
940
992
|
end
|
941
993
|
end
|
942
994
|
when :gateway
|
@@ -946,15 +998,15 @@ module Aspera
|
|
946
998
|
when :admin
|
947
999
|
return execute_admin_action
|
948
1000
|
when :servers
|
949
|
-
return {:
|
1001
|
+
return {type: :object_list,data: Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
|
950
1002
|
else
|
951
1003
|
raise "internal error: #{command}"
|
952
1004
|
end # action
|
953
|
-
raise RuntimeError,
|
1005
|
+
raise RuntimeError, 'internal error: command shall return'
|
954
1006
|
end
|
955
1007
|
|
956
|
-
private :
|
957
|
-
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
|
958
1010
|
|
959
1011
|
end # AoC
|
960
1012
|
end # Plugins
|