aspera-cli 4.6.0 → 4.7.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 +427 -300
- data/bin/ascli +2 -1
- data/bin/asession +1 -0
- data/docs/test_env.conf +2 -0
- data/examples/aoc.rb +4 -3
- data/examples/faspex4.rb +21 -19
- data/examples/proxy.pac +1 -1
- data/examples/transfer.rb +15 -15
- data/lib/aspera/aoc.rb +135 -124
- data/lib/aspera/ascmd.rb +85 -75
- data/lib/aspera/ats_api.rb +11 -10
- data/lib/aspera/cli/basic_auth_plugin.rb +13 -14
- data/lib/aspera/cli/extended_value.rb +42 -33
- data/lib/aspera/cli/formater.rb +138 -111
- data/lib/aspera/cli/info.rb +17 -0
- data/lib/aspera/cli/listener/line_dump.rb +3 -2
- data/lib/aspera/cli/listener/logger.rb +2 -1
- data/lib/aspera/cli/listener/progress.rb +16 -18
- data/lib/aspera/cli/listener/progress_multi.rb +13 -16
- data/lib/aspera/cli/main.rb +122 -130
- data/lib/aspera/cli/manager.rb +146 -154
- data/lib/aspera/cli/plugin.rb +38 -34
- data/lib/aspera/cli/plugins/alee.rb +6 -6
- data/lib/aspera/cli/plugins/aoc.rb +273 -276
- data/lib/aspera/cli/plugins/ats.rb +82 -76
- data/lib/aspera/cli/plugins/bss.rb +14 -16
- data/lib/aspera/cli/plugins/config.rb +350 -306
- data/lib/aspera/cli/plugins/console.rb +23 -19
- data/lib/aspera/cli/plugins/cos.rb +18 -18
- data/lib/aspera/cli/plugins/faspex.rb +180 -159
- data/lib/aspera/cli/plugins/faspex5.rb +64 -54
- data/lib/aspera/cli/plugins/node.rb +147 -140
- data/lib/aspera/cli/plugins/orchestrator.rb +68 -66
- data/lib/aspera/cli/plugins/preview.rb +92 -96
- data/lib/aspera/cli/plugins/server.rb +79 -75
- data/lib/aspera/cli/plugins/shares.rb +23 -24
- data/lib/aspera/cli/plugins/sync.rb +20 -22
- data/lib/aspera/cli/transfer_agent.rb +40 -39
- data/lib/aspera/cli/version.rb +2 -1
- data/lib/aspera/colors.rb +35 -27
- data/lib/aspera/command_line_builder.rb +48 -34
- data/lib/aspera/cos_node.rb +29 -21
- data/lib/aspera/data_repository.rb +3 -2
- data/lib/aspera/environment.rb +50 -45
- data/lib/aspera/fasp/agent_base.rb +22 -20
- data/lib/aspera/fasp/agent_connect.rb +13 -11
- data/lib/aspera/fasp/agent_direct.rb +48 -59
- data/lib/aspera/fasp/agent_httpgw.rb +33 -39
- data/lib/aspera/fasp/agent_node.rb +15 -13
- data/lib/aspera/fasp/agent_trsdk.rb +12 -14
- data/lib/aspera/fasp/error.rb +2 -1
- data/lib/aspera/fasp/error_info.rb +68 -52
- data/lib/aspera/fasp/installation.rb +106 -94
- data/lib/aspera/fasp/listener.rb +1 -0
- data/lib/aspera/fasp/parameters.rb +83 -92
- data/lib/aspera/fasp/parameters.yaml +305 -249
- data/lib/aspera/fasp/resume_policy.rb +11 -14
- data/lib/aspera/fasp/transfer_spec.rb +26 -0
- data/lib/aspera/fasp/uri.rb +22 -21
- data/lib/aspera/faspex_gw.rb +55 -90
- data/lib/aspera/hash_ext.rb +4 -3
- data/lib/aspera/id_generator.rb +8 -7
- data/lib/aspera/keychain/encrypted_hash.rb +17 -16
- data/lib/aspera/keychain/macos_security.rb +6 -10
- data/lib/aspera/log.rb +25 -20
- data/lib/aspera/nagios.rb +13 -12
- data/lib/aspera/node.rb +30 -22
- data/lib/aspera/oauth.rb +175 -226
- data/lib/aspera/open_application.rb +4 -3
- data/lib/aspera/persistency_action_once.rb +6 -6
- data/lib/aspera/persistency_folder.rb +5 -9
- data/lib/aspera/preview/file_types.rb +6 -5
- data/lib/aspera/preview/generator.rb +25 -24
- data/lib/aspera/preview/options.rb +16 -14
- data/lib/aspera/preview/utils.rb +98 -98
- data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
- data/lib/aspera/proxy_auto_config.rb +111 -20
- data/lib/aspera/rest.rb +115 -113
- data/lib/aspera/rest_call_error.rb +2 -2
- data/lib/aspera/rest_error_analyzer.rb +23 -25
- data/lib/aspera/rest_errors_aspera.rb +15 -14
- data/lib/aspera/ssh.rb +12 -10
- data/lib/aspera/sync.rb +42 -41
- data/lib/aspera/temp_file_manager.rb +18 -14
- data/lib/aspera/timer_limiter.rb +2 -1
- data/lib/aspera/uri_reader.rb +7 -5
- data/lib/aspera/web_auth.rb +79 -76
- metadata +64 -21
- data/docs/Makefile +0 -65
- data/docs/README.erb.md +0 -4424
- data/docs/README.md +0 -13
- data/docs/diagrams.txt +0 -49
- data/docs/doc_tools.rb +0 -58
- data/lib/aspera/cli/plugins/shares2.rb +0 -114
- data/lib/aspera/fasp/default.rb +0 -17
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'aspera/cli/plugins/node'
|
2
3
|
require 'aspera/cli/plugins/ats'
|
3
4
|
require 'aspera/cli/basic_auth_plugin'
|
4
5
|
require 'aspera/cli/transfer_agent'
|
5
6
|
require 'aspera/fasp/agent_node'
|
7
|
+
require 'aspera/fasp/transfer_spec'
|
6
8
|
require 'aspera/aoc'
|
7
9
|
require 'aspera/node'
|
8
10
|
require 'aspera/persistency_action_once'
|
@@ -17,9 +19,10 @@ module Aspera
|
|
17
19
|
class << self
|
18
20
|
def detect(base_url)
|
19
21
|
api=Rest.new({base_url: base_url})
|
20
|
-
|
21
|
-
if
|
22
|
-
|
22
|
+
# either in standard domain, or product name in page
|
23
|
+
if URI.parse(base_url).host.end_with?(Aspera::AoC::PROD_DOMAIN) ||
|
24
|
+
api.call({operation: 'GET', redirect_max: 1, headers: {'Accept'=>'text/html'}})[:http].body.include?(Aspera::AoC::PRODUCT_NAME)
|
25
|
+
return {product: :aoc,version: 'SaaS' }
|
23
26
|
end
|
24
27
|
return nil
|
25
28
|
end
|
@@ -38,34 +41,34 @@ module Aspera
|
|
38
41
|
@api_aoc=nil
|
39
42
|
@url_token_data=nil
|
40
43
|
@api_aoc=nil
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
AoC.
|
44
|
+
options.add_opt_list(:auth,Oauth::STD_AUTH_TYPES,'OAuth type of authentication')
|
45
|
+
options.add_opt_list(:operation,[:push,:pull],'client operation for transfers')
|
46
|
+
options.add_opt_simple(:client_id,'OAuth API client identifier in application')
|
47
|
+
options.add_opt_simple(:client_secret,'OAuth API client passcode')
|
48
|
+
options.add_opt_simple(:redirect_uri,'OAuth API client redirect URI')
|
49
|
+
options.add_opt_simple(:private_key,'OAuth JWT RSA private key PEM value (prefix file path with @val:@file:)')
|
50
|
+
options.add_opt_simple(:workspace,'name of workspace')
|
51
|
+
options.add_opt_simple(:name,'resource name')
|
52
|
+
options.add_opt_simple(:path,'file or folder path')
|
53
|
+
options.add_opt_simple(:link,'public link to shared resource')
|
54
|
+
options.add_opt_simple(:new_user_option,'new user creation option')
|
55
|
+
options.add_opt_simple(:from_folder,'share to share source folder')
|
56
|
+
options.add_opt_simple(:scope,'OAuth scope for AoC API calls')
|
57
|
+
options.add_opt_boolean(:bulk,'bulk operation')
|
58
|
+
options.add_opt_boolean(:default_ports,'use standard FASP ports or get from node api')
|
59
|
+
options.set_option(:bulk,:no)
|
60
|
+
options.set_option(:default_ports,:yes)
|
61
|
+
options.set_option(:new_user_option,{'package_contact'=>true})
|
62
|
+
options.set_option(:operation,:push)
|
63
|
+
options.set_option(:auth,:jwt)
|
64
|
+
options.set_option(:scope,AoC::SCOPE_FILES_USER)
|
65
|
+
options.set_option(:private_key,'@file:'+env[:private_key_path]) if env[:private_key_path].is_a?(String)
|
66
|
+
options.parse_options!
|
67
|
+
AoC.use_standard_ports=options.get_option(:default_ports)
|
65
68
|
return if env[:man_only]
|
66
69
|
end
|
67
70
|
|
68
|
-
def
|
71
|
+
def aoc_api
|
69
72
|
if @api_aoc.nil?
|
70
73
|
@api_aoc=AoC.new(aoc_params(AoC::API_V1))
|
71
74
|
# add keychain for access key secrets
|
@@ -77,23 +80,23 @@ module Aspera
|
|
77
80
|
# starts transfer using transfer agent
|
78
81
|
def transfer_start(app,direction,node_file,ts_add)
|
79
82
|
ts_add.deep_merge!(AoC.analytics_ts(app,direction,@workspace_id,@workspace_name))
|
80
|
-
ts_add.deep_merge!(
|
81
|
-
return
|
83
|
+
ts_add.deep_merge!(aoc_api.console_ts(app))
|
84
|
+
return transfer.start(*aoc_api.tr_spec(app,direction,node_file,ts_add))
|
82
85
|
end
|
83
86
|
|
84
|
-
NODE4_COMMANDS=[
|
87
|
+
NODE4_COMMANDS=[:browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node, :node_info].freeze
|
85
88
|
|
86
89
|
def execute_node_gen4_command(command_repo,top_node_file)
|
87
90
|
case command_repo
|
88
91
|
when :bearer_token_node
|
89
|
-
thepath=
|
90
|
-
node_file =
|
91
|
-
node_api
|
92
|
+
thepath=options.get_next_argument('path')
|
93
|
+
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
94
|
+
node_api=aoc_api.get_node_api(node_file[:node_info], use_secret: false)
|
92
95
|
return Main.result_status(node_api.oauth_token)
|
93
96
|
when :node_info
|
94
|
-
thepath=
|
95
|
-
node_file =
|
96
|
-
node_api
|
97
|
+
thepath=options.get_next_argument('path')
|
98
|
+
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
99
|
+
node_api=aoc_api.get_node_api(node_file[:node_info], use_secret: false)
|
97
100
|
return {type: :single_object,data: {
|
98
101
|
url: node_file[:node_info]['url'],
|
99
102
|
username: node_file[:node_info]['access_key'],
|
@@ -101,12 +104,12 @@ module Aspera
|
|
101
104
|
root_id: node_file[:file_id]
|
102
105
|
}}
|
103
106
|
when :browse
|
104
|
-
thepath=
|
105
|
-
node_file =
|
106
|
-
node_api
|
107
|
+
thepath=options.get_next_argument('path')
|
108
|
+
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
109
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
107
110
|
file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
|
108
111
|
if file_info['type'].eql?('folder')
|
109
|
-
result=node_api.read("files/#{node_file[:file_id]}/files",
|
112
|
+
result=node_api.read("files/#{node_file[:file_id]}/files",options.get_option(:value,:optional))
|
110
113
|
items=result[:data]
|
111
114
|
self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
|
112
115
|
else
|
@@ -114,31 +117,31 @@ module Aspera
|
|
114
117
|
end
|
115
118
|
return {type: :object_list,data: items,fields: ['name','type','recursive_size','size','modified_time','access_level']}
|
116
119
|
when :find
|
117
|
-
thepath=
|
118
|
-
node_file
|
119
|
-
test_block=Aspera::Node.file_matcher(
|
120
|
-
return {type: :object_list,data:
|
120
|
+
thepath=options.get_next_argument('path')
|
121
|
+
node_file=aoc_api.resolve_node_file(top_node_file,thepath)
|
122
|
+
test_block=Aspera::Node.file_matcher(options.get_option(:value,:optional))
|
123
|
+
return {type: :object_list,data: aoc_api.find_files(node_file,test_block),fields: ['path']}
|
121
124
|
when :mkdir
|
122
|
-
thepath=
|
125
|
+
thepath=options.get_next_argument('path')
|
123
126
|
containing_folder_path = thepath.split(AoC::PATH_SEPARATOR)
|
124
127
|
new_folder=containing_folder_path.pop
|
125
|
-
node_file =
|
126
|
-
node_api
|
128
|
+
node_file = aoc_api.resolve_node_file(top_node_file,containing_folder_path.join(AoC::PATH_SEPARATOR))
|
129
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
127
130
|
result=node_api.create("files/#{node_file[:file_id]}/files",{name: new_folder,type: :folder})[:data]
|
128
131
|
return Main.result_status("created: #{result['name']} (id=#{result['id']})")
|
129
132
|
when :rename
|
130
|
-
thepath=
|
131
|
-
newname=
|
132
|
-
node_file =
|
133
|
-
node_api
|
133
|
+
thepath=options.get_next_argument('source path')
|
134
|
+
newname=options.get_next_argument('new name')
|
135
|
+
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
136
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
134
137
|
result=node_api.update("files/#{node_file[:file_id]}",{name: newname})[:data]
|
135
138
|
return Main.result_status("renamed #{thepath} to #{newname}")
|
136
139
|
when :delete
|
137
|
-
thepath=
|
140
|
+
thepath=options.get_next_argument('path')
|
138
141
|
return do_bulk_operation(thepath,'deleted','path') do |l_path|
|
139
142
|
raise "expecting String (path), got #{l_path.class.name} (#{l_path})" unless l_path.is_a?(String)
|
140
|
-
node_file =
|
141
|
-
node_api
|
143
|
+
node_file = aoc_api.resolve_node_file(top_node_file,l_path)
|
144
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
142
145
|
result=node_api.delete("files/#{node_file[:file_id]}")[:data]
|
143
146
|
{'path'=>l_path}
|
144
147
|
end
|
@@ -148,26 +151,26 @@ module Aspera
|
|
148
151
|
# in same workspace
|
149
152
|
server_home_node_file=client_home_node_file=top_node_file
|
150
153
|
# default is push
|
151
|
-
case
|
154
|
+
case options.get_option(:operation,:mandatory)
|
152
155
|
when :push
|
153
|
-
client_tr_oper=
|
154
|
-
client_folder=
|
155
|
-
server_folder=
|
156
|
+
client_tr_oper=Fasp::TransferSpec::DIRECTION_SEND
|
157
|
+
client_folder=options.get_option(:from_folder,:mandatory)
|
158
|
+
server_folder=transfer.destination_folder(client_tr_oper)
|
156
159
|
when :pull
|
157
|
-
client_tr_oper=
|
158
|
-
client_folder=
|
159
|
-
server_folder=
|
160
|
+
client_tr_oper=Fasp::TransferSpec::DIRECTION_RECEIVE
|
161
|
+
client_folder=transfer.destination_folder(client_tr_oper)
|
162
|
+
server_folder=options.get_option(:from_folder,:mandatory)
|
160
163
|
end
|
161
|
-
client_node_file =
|
162
|
-
server_node_file =
|
164
|
+
client_node_file = aoc_api.resolve_node_file(client_home_node_file,client_folder)
|
165
|
+
server_node_file = aoc_api.resolve_node_file(server_home_node_file,server_folder)
|
163
166
|
# force node as transfer agent
|
164
|
-
client_node_api
|
165
|
-
@agents[:transfer].
|
167
|
+
client_node_api=aoc_api.get_node_api(client_node_file[:node_info], use_secret: false)
|
168
|
+
@agents[:transfer].agent_instance=Fasp::AgentNode.new({
|
166
169
|
url: client_node_api.params[:base_url],
|
167
170
|
username: client_node_file[:node_info]['access_key'],
|
168
171
|
password: client_node_api.oauth_token,
|
169
172
|
root_id: client_node_file[:file_id]
|
170
|
-
})
|
173
|
+
})
|
171
174
|
# additional node to node TS info
|
172
175
|
add_ts={
|
173
176
|
'remote_access_key' => server_node_file[:node_info]['access_key'],
|
@@ -176,11 +179,11 @@ module Aspera
|
|
176
179
|
}
|
177
180
|
return Main.result_transfer(transfer_start(AoC::FILES_APP,client_tr_oper,server_node_file,add_ts))
|
178
181
|
when :upload
|
179
|
-
node_file =
|
182
|
+
node_file = aoc_api.resolve_node_file(top_node_file,transfer.destination_folder(Fasp::TransferSpec::DIRECTION_SEND))
|
180
183
|
add_ts={'tags'=>{'aspera'=>{'files'=>{'parentCwd'=>"#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
|
181
|
-
return Main.result_transfer(transfer_start(AoC::FILES_APP,
|
184
|
+
return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_SEND,node_file,add_ts))
|
182
185
|
when :download
|
183
|
-
source_paths=
|
186
|
+
source_paths=transfer.ts_source_paths
|
184
187
|
# special case for AoC : all files must be in same folder
|
185
188
|
source_folder=source_paths.shift['source']
|
186
189
|
# if a single file: split into folder and path
|
@@ -189,13 +192,13 @@ module Aspera
|
|
189
192
|
source_paths=[{'source'=>source_folder.pop}]
|
190
193
|
source_folder=source_folder.join(AoC::PATH_SEPARATOR)
|
191
194
|
end
|
192
|
-
node_file =
|
195
|
+
node_file = aoc_api.resolve_node_file(top_node_file,source_folder)
|
193
196
|
# override paths with just filename
|
194
197
|
add_ts={'tags'=>{'aspera'=>{'files'=>{'parentCwd'=>"#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
|
195
198
|
add_ts.merge!({'paths'=>source_paths})
|
196
|
-
return Main.result_transfer(transfer_start(AoC::FILES_APP,
|
199
|
+
return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_RECEIVE,node_file,add_ts))
|
197
200
|
when :http_node_download
|
198
|
-
source_paths=
|
201
|
+
source_paths=transfer.ts_source_paths
|
199
202
|
source_folder=source_paths.shift['source']
|
200
203
|
if source_paths.empty?
|
201
204
|
source_folder=source_folder.split(AoC::PATH_SEPARATOR)
|
@@ -204,35 +207,37 @@ module Aspera
|
|
204
207
|
end
|
205
208
|
raise CliBadArgument,'one file at a time only in HTTP mode' if source_paths.length > 1
|
206
209
|
file_name = source_paths.first['source']
|
207
|
-
node_file =
|
208
|
-
node_api
|
209
|
-
node_api.call({operation: 'GET',subpath: "files/#{node_file[:file_id]}/content",
|
210
|
+
node_file = aoc_api.resolve_node_file(top_node_file,File.join(source_folder,file_name))
|
211
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
212
|
+
node_api.call({operation: 'GET',subpath: "files/#{node_file[:file_id]}/content",
|
213
|
+
save_to_file: File.join(transfer.destination_folder(Fasp::TransferSpec::DIRECTION_RECEIVE),file_name)})
|
210
214
|
return Main.result_status("downloaded: #{file_name}")
|
211
215
|
when :v3
|
212
216
|
# Note: other common actions are unauthorized with user scope
|
213
|
-
command_legacy=
|
217
|
+
command_legacy=options.get_next_command(Node::SIMPLE_ACTIONS)
|
214
218
|
# TODO: shall we support all methods here ? what if there is a link ?
|
215
|
-
node_api
|
219
|
+
node_api=aoc_api.get_node_api(top_node_file[:node_info])
|
216
220
|
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: node_api)).execute_action(command_legacy)
|
217
221
|
when :file
|
218
|
-
command_node_file=
|
219
|
-
file_path=
|
220
|
-
node_file =
|
221
|
-
|
222
|
+
command_node_file=options.get_next_command([:show,:permission,:modify])
|
223
|
+
file_path=options.get_option(:path,:optional)
|
224
|
+
node_file =
|
225
|
+
if !file_path.nil?
|
226
|
+
aoc_api.resolve_node_file(top_node_file,file_path) # TODO: allow follow link ?
|
222
227
|
else
|
223
|
-
{node_info: top_node_file[:node_info],file_id:
|
228
|
+
{node_info: top_node_file[:node_info],file_id: instance_identifier()}
|
224
229
|
end
|
225
|
-
node_api
|
230
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
226
231
|
case command_node_file
|
227
232
|
when :show
|
228
233
|
items=node_api.read("files/#{node_file[:file_id]}")[:data]
|
229
234
|
return {type: :single_object,data: items}
|
230
235
|
when :modify
|
231
|
-
update_param=
|
236
|
+
update_param=options.get_next_argument('update data (Hash)')
|
232
237
|
res=node_api.update("files/#{node_file[:file_id]}",update_param)[:data]
|
233
238
|
return {type: :single_object,data: res}
|
234
239
|
when :permission
|
235
|
-
command_perm=
|
240
|
+
command_perm=options.get_next_command([:list,:create])
|
236
241
|
case command_perm
|
237
242
|
when :list
|
238
243
|
# generic options : TODO: as arg ? option_url_query
|
@@ -258,10 +263,10 @@ module Aspera
|
|
258
263
|
'tags' =>{'aspera'=>{'files'=>{'workspace'=>{
|
259
264
|
'id' =>@workspace_id,
|
260
265
|
'workspace_name' =>@workspace_name,
|
261
|
-
'user_name'
|
262
|
-
'shared_by_user_id'
|
263
|
-
'shared_by_name'
|
264
|
-
'shared_by_email'
|
266
|
+
'user_name' =>aoc_api.user_info['name'],
|
267
|
+
'shared_by_user_id'=>aoc_api.user_info['id'],
|
268
|
+
'shared_by_name' =>aoc_api.user_info['name'],
|
269
|
+
'shared_by_email' =>aoc_api.user_info['email'],
|
265
270
|
'shared_with_name' =>access_id,
|
266
271
|
'access_key' =>node_file[:node_info]['access_key'],
|
267
272
|
'node' =>node_file[:node_info]['name']}}}}}
|
@@ -269,10 +274,8 @@ module Aspera
|
|
269
274
|
return {type: :single_object,data: item}
|
270
275
|
else raise "internal error:shall not reach here (#{command_perm})"
|
271
276
|
end
|
272
|
-
raise 'internal error:shall not reach here'
|
273
277
|
else raise "internal error:shall not reach here (#{command_node_file})"
|
274
278
|
end
|
275
|
-
raise 'internal error:shall not reach here'
|
276
279
|
end # command_repo
|
277
280
|
raise 'ERR'
|
278
281
|
end # execute_node_gen4_command
|
@@ -280,7 +283,7 @@ module Aspera
|
|
280
283
|
# build constructor option list for AoC based on options of CLI
|
281
284
|
def aoc_params(subpath)
|
282
285
|
# copy command line options to args
|
283
|
-
opt=[:link,:url,:auth,:client_id,:client_secret,:scope,:redirect_uri,:private_key,:username,:password].
|
286
|
+
opt=[:link,:url,:auth,:client_id,:client_secret,:scope,:redirect_uri,:private_key,:username,:password].each_with_object({}){|i,m|m[i]=options.get_option(i,:optional);}
|
284
287
|
opt[:subpath]=subpath
|
285
288
|
return opt
|
286
289
|
end
|
@@ -293,17 +296,16 @@ module Aspera
|
|
293
296
|
# @persist_ids
|
294
297
|
# returns nil
|
295
298
|
def set_workspace_info
|
296
|
-
|
297
|
-
|
298
|
-
@
|
299
|
+
@url_token_data=aoc_api.url_token_data
|
300
|
+
if @url_token_data.nil?
|
301
|
+
@default_workspace_id=aoc_api.user_info['default_workspace_id']
|
302
|
+
@persist_ids=[aoc_api.user_info['id']]
|
303
|
+
else
|
299
304
|
@default_workspace_id=@url_token_data['data']['workspace_id']
|
300
305
|
@persist_ids=[] # TODO : @url_token_data['id'] ?
|
301
|
-
else
|
302
|
-
@default_workspace_id=@api_aoc.user_info['default_workspace_id']
|
303
|
-
@persist_ids=[@api_aoc.user_info['id']]
|
304
306
|
end
|
305
307
|
|
306
|
-
ws_name=
|
308
|
+
ws_name=options.get_option(:workspace,:optional)
|
307
309
|
if ws_name.nil?
|
308
310
|
Log.log.debug('using default workspace'.green)
|
309
311
|
if @default_workspace_id.eql?(nil)
|
@@ -313,7 +315,7 @@ module Aspera
|
|
313
315
|
@workspace_id=@default_workspace_id
|
314
316
|
else
|
315
317
|
# lookup another workspace
|
316
|
-
wss
|
318
|
+
wss=aoc_api.read('workspaces',{'q'=>ws_name})[:data]
|
317
319
|
wss=wss.select { |i| i['name'].eql?(ws_name) }
|
318
320
|
case wss.length
|
319
321
|
when 0
|
@@ -324,7 +326,7 @@ module Aspera
|
|
324
326
|
raise 'unexpected case'
|
325
327
|
end
|
326
328
|
end
|
327
|
-
@workspace_data
|
329
|
+
@workspace_data=aoc_api.read("workspaces/#{@workspace_id}")[:data]
|
328
330
|
Log.log.debug("workspace_id=#{@workspace_id},@workspace_data=#{@workspace_data}".red)
|
329
331
|
|
330
332
|
@workspace_name||=@workspace_data['name']
|
@@ -346,16 +348,16 @@ module Aspera
|
|
346
348
|
home_file_id||=@workspace_data['home_file_id']
|
347
349
|
raise 'node_id must be defined' if home_node_id.to_s.empty?
|
348
350
|
@home_node_file={
|
349
|
-
node_info:
|
351
|
+
node_info: aoc_api.read("nodes/#{home_node_id}")[:data],
|
350
352
|
file_id: home_file_id
|
351
353
|
}
|
352
|
-
|
354
|
+
aoc_api.check_get_node_file(@home_node_file)
|
353
355
|
|
354
356
|
return nil
|
355
357
|
end
|
356
358
|
|
357
359
|
def do_bulk_operation(ids_or_one,success_msg,id_result='id',&do_action)
|
358
|
-
ids_or_one=[ids_or_one] unless
|
360
|
+
ids_or_one=[ids_or_one] unless options.get_option(:bulk)
|
359
361
|
raise 'expecting Array' unless ids_or_one.is_a?(Array)
|
360
362
|
result_list=[]
|
361
363
|
ids_or_one.each do |id|
|
@@ -364,7 +366,7 @@ module Aspera
|
|
364
366
|
res=do_action.call(id)
|
365
367
|
one=res if id.is_a?(Hash) # if block returns a has, let's use this
|
366
368
|
one['status']=success_msg
|
367
|
-
rescue => e
|
369
|
+
rescue StandardError => e
|
368
370
|
one['status']=e.to_s
|
369
371
|
end
|
370
372
|
result_list.push(one)
|
@@ -375,15 +377,15 @@ module Aspera
|
|
375
377
|
# get identifier or name from command line
|
376
378
|
# @return identifier
|
377
379
|
def get_resource_id_from_args(resource_class_path)
|
378
|
-
l_res_id=
|
379
|
-
l_res_name=
|
380
|
-
raise
|
380
|
+
l_res_id=options.get_option(:id)
|
381
|
+
l_res_name=options.get_option(:name)
|
382
|
+
raise 'Provide either option id or name, not both' unless l_res_id.nil? || l_res_name.nil?
|
381
383
|
# try to find item by name (single partial match or exact match)
|
382
|
-
l_res_id
|
384
|
+
l_res_id=aoc_api.lookup_entity_by_name(resource_class_path,l_res_name)['id'] unless l_res_name.nil?
|
383
385
|
# if no name or id option, taken on command line (after command)
|
384
386
|
if l_res_id.nil?
|
385
|
-
l_res_id=
|
386
|
-
l_res_id
|
387
|
+
l_res_id=options.get_next_argument('identifier')
|
388
|
+
l_res_id=aoc_api.lookup_entity_by_name(resource_class_path,options.get_next_argument('identifier'))['id'] if l_res_id.eql?('name')
|
387
389
|
end
|
388
390
|
return l_res_id
|
389
391
|
end
|
@@ -396,7 +398,7 @@ module Aspera
|
|
396
398
|
def resolve_package_recipients(package_data,recipient_list_field)
|
397
399
|
return unless package_data.has_key?(recipient_list_field)
|
398
400
|
raise CliBadArgument,"#{recipient_list_field} must be an Array" unless package_data[recipient_list_field].is_a?(Array)
|
399
|
-
new_user_option=
|
401
|
+
new_user_option=options.get_option(:new_user_option,:mandatory)
|
400
402
|
# list with resolved elements
|
401
403
|
resolved_list=[]
|
402
404
|
package_data[recipient_list_field].each do |short_recipient_info|
|
@@ -407,20 +409,13 @@ module Aspera
|
|
407
409
|
# email: user, else dropbox
|
408
410
|
entity_type=short_recipient_info.include?('@') ? 'contacts' : 'dropboxes'
|
409
411
|
begin
|
410
|
-
full_recipient_info
|
412
|
+
full_recipient_info=aoc_api.lookup_entity_by_name(entity_type,short_recipient_info,{'current_workspace_id'=>@workspace_id})
|
411
413
|
rescue RuntimeError => e
|
412
414
|
raise e unless e.message.eql?('not found')
|
413
|
-
|
414
|
-
|
415
|
-
else
|
416
|
-
raise "no such shared inbox in workspace #{@workspace_name}"
|
417
|
-
end
|
418
|
-
end
|
419
|
-
if entity_type.eql?('dropboxes')
|
420
|
-
short_recipient_info={'id'=>full_recipient_info['id'],'type'=>'dropbox'}
|
421
|
-
else
|
422
|
-
short_recipient_info={'id'=>full_recipient_info['source_id'],'type'=>full_recipient_info['source_type']}
|
415
|
+
raise "no such shared inbox in workspace #{@workspace_name}" unless entity_type.eql?('contacts')
|
416
|
+
full_recipient_info=aoc_api.create('contacts',{'current_workspace_id'=>@workspace_id,'email'=>short_recipient_info}.merge(new_user_option))[:data]
|
423
417
|
end
|
418
|
+
short_recipient_info=entity_type.eql?('dropboxes') ? {'id'=>full_recipient_info['id'],'type'=>'dropbox'} : {'id'=>full_recipient_info['source_id'],'type'=>full_recipient_info['source_type']}
|
424
419
|
else # unexpected extended value, must be String or Hash
|
425
420
|
raise "#{recipient_list_field} item must be a String (email, shared inbox) or Hash (id,type)"
|
426
421
|
end # type of recipient info
|
@@ -433,8 +428,8 @@ module Aspera
|
|
433
428
|
|
434
429
|
def normalize_metadata(pkg_data)
|
435
430
|
case pkg_data['metadata']
|
436
|
-
when NilClass
|
437
|
-
when Array
|
431
|
+
when NilClass then return
|
432
|
+
when Array then return
|
438
433
|
when Hash
|
439
434
|
api_meta=[]
|
440
435
|
pkg_data['metadata'].each do |k,v|
|
@@ -445,7 +440,6 @@ module Aspera
|
|
445
440
|
})
|
446
441
|
end
|
447
442
|
pkg_data['metadata']=api_meta
|
448
|
-
|
449
443
|
else raise "metadata field if not of expected type: #{pkg_meta.class}"
|
450
444
|
end
|
451
445
|
nil
|
@@ -453,27 +447,26 @@ module Aspera
|
|
453
447
|
|
454
448
|
# private
|
455
449
|
def option_url_query(default)
|
456
|
-
query=
|
450
|
+
query=options.get_option(:query,:optional)
|
457
451
|
query=default if query.nil?
|
458
452
|
Log.log.debug("Query=#{query}".bg_red)
|
459
453
|
begin
|
460
454
|
# check it is suitable
|
461
455
|
URI.encode_www_form(query) unless query.nil?
|
462
|
-
rescue => e
|
456
|
+
rescue StandardError => e
|
463
457
|
raise CliBadArgument,"query must be an extended value which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
|
464
458
|
end
|
465
459
|
return query
|
466
460
|
end
|
467
461
|
|
468
462
|
def assert_public_link_types(expected)
|
469
|
-
|
470
|
-
raise CliBadArgument,"public link type is #{@url_token_data['purpose']} but action requires one of #{expected.join(',')}"
|
471
|
-
end
|
463
|
+
raise CliBadArgument,"public link type is #{@url_token_data['purpose']} but action requires one of #{expected.join(',')}" unless expected.include?(@url_token_data['purpose'])
|
472
464
|
end
|
473
465
|
|
474
|
-
# Call
|
466
|
+
# Call aoc_api.read with same parameters.
|
467
|
+
# Use paging if necessary to get all results
|
475
468
|
def read_with_paging(resource_class_path,base_query)
|
476
|
-
raise
|
469
|
+
raise 'Query must be Hash' unless base_query.is_a?(Hash)
|
477
470
|
# set default large page if user does not specify own parameters. AoC Caps to 1000 anyway
|
478
471
|
base_query['per_page']=1000 unless base_query.has_key?('per_page')
|
479
472
|
max_items=base_query[MAX_ITEMS]
|
@@ -488,7 +481,7 @@ module Aspera
|
|
488
481
|
loop do
|
489
482
|
query=base_query.clone
|
490
483
|
query['page']=current_page
|
491
|
-
result
|
484
|
+
result=aoc_api.read(resource_class_path,query)
|
492
485
|
total_count=result[:http]['X-Total-Count']
|
493
486
|
page_count+=1
|
494
487
|
current_page+=1
|
@@ -496,26 +489,28 @@ module Aspera
|
|
496
489
|
break if add_items.empty?
|
497
490
|
# append new items to full list
|
498
491
|
item_list += add_items
|
499
|
-
break if !max_pages.nil?
|
500
|
-
break if !max_items.nil?
|
492
|
+
break if !max_pages.nil? && page_count > max_pages
|
493
|
+
break if !max_items.nil? && item_list.count > max_items
|
501
494
|
end
|
502
495
|
return item_list,total_count
|
503
496
|
end
|
504
497
|
|
505
498
|
def execute_admin_action
|
506
|
-
|
507
|
-
|
499
|
+
# upgrade scope to admin
|
500
|
+
aoc_api.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
|
501
|
+
command_admin=options.get_next_command([:ats, :resource, :usage_reports, :analytics, :subscription, :auth_providers])
|
508
502
|
case command_admin
|
509
503
|
when :auth_providers
|
510
|
-
command_auth_prov=
|
504
|
+
command_auth_prov=options.get_next_command([:list, :update])
|
511
505
|
case command_auth_prov
|
512
506
|
when :list
|
513
|
-
providers
|
507
|
+
providers=aoc_api.read('admin/auth_providers')[:data]
|
514
508
|
return {type: :object_list,data: providers}
|
515
509
|
when :update
|
510
|
+
raise 'not implemented'
|
516
511
|
end
|
517
512
|
when :subscription
|
518
|
-
org
|
513
|
+
org=aoc_api.read('organization')[:data]
|
519
514
|
bss_api=AoC.new(aoc_params('bss/platform'))
|
520
515
|
graphql_query="
|
521
516
|
query ($organization_id: ID!) {
|
@@ -568,41 +563,41 @@ module Aspera
|
|
568
563
|
result=bss_api.create('graphql',{'variables'=>{'organization_id'=>org['id']},'query'=>graphql_query})[:data]['data']
|
569
564
|
return {type: :single_object,data: result['aoc']['bssSubscription']}
|
570
565
|
when :ats
|
571
|
-
ats_api = Rest.new(
|
572
|
-
base_url:
|
566
|
+
ats_api = Rest.new(aoc_api.params.deep_merge({
|
567
|
+
base_url: aoc_api.params[:base_url]+'/admin/ats/pub/v1',
|
573
568
|
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
574
569
|
}))
|
575
570
|
return Ats.new(@agents).execute_action_gen(ats_api)
|
576
571
|
when :analytics
|
577
|
-
analytics_api = Rest.new(
|
578
|
-
base_url:
|
572
|
+
analytics_api = Rest.new(aoc_api.params.deep_merge({
|
573
|
+
base_url: aoc_api.params[:base_url].gsub('/api/v1','')+'/analytics/v2',
|
579
574
|
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
580
575
|
}))
|
581
|
-
command_analytics=
|
576
|
+
command_analytics=options.get_next_command([:application_events, :transfers])
|
582
577
|
case command_analytics
|
583
578
|
when :application_events
|
584
579
|
event_type=command_analytics.to_s
|
585
|
-
events=analytics_api.read("organizations/#{
|
580
|
+
events=analytics_api.read("organizations/#{aoc_api.user_info['organization_id']}/#{event_type}")[:data][event_type]
|
586
581
|
return {type: :object_list,data: events}
|
587
582
|
when :transfers
|
588
583
|
event_type=command_analytics.to_s
|
589
|
-
filter_resource=
|
590
|
-
filter_id=
|
591
|
-
|
592
|
-
when '
|
593
|
-
when '
|
584
|
+
filter_resource=options.get_option(:name,:optional) || 'organizations'
|
585
|
+
filter_id=options.get_option(:id,:optional) ||
|
586
|
+
case filter_resource
|
587
|
+
when 'organizations' then aoc_api.user_info['organization_id']
|
588
|
+
when 'users' then aoc_api.user_info['id']
|
589
|
+
when 'nodes' then aoc_api.user_info['id']
|
594
590
|
else raise 'organizations or users for option --name'
|
595
591
|
end
|
596
|
-
|
597
|
-
filter=self.options.get_option(:query,:optional) || {}
|
592
|
+
filter=options.get_option(:query,:optional) || {}
|
598
593
|
raise 'query must be Hash' unless filter.is_a?(Hash)
|
599
594
|
filter['limit']||=100
|
600
|
-
if
|
595
|
+
if options.get_option(:once_only,:mandatory)
|
601
596
|
saved_date=[]
|
602
597
|
startdate_persistency=PersistencyActionOnce.new(
|
603
598
|
manager: @agents[:persistency],
|
604
599
|
data: saved_date,
|
605
|
-
ids: IdGenerator.from_list(['aoc_ana_date',
|
600
|
+
ids: IdGenerator.from_list(['aoc_ana_date',options.get_option(:url,:mandatory),@workspace_name].push(filter_resource,filter_id)))
|
606
601
|
start_datetime=saved_date.first
|
607
602
|
stop_datetime=Time.now.utc.strftime('%FT%T.%LZ')
|
608
603
|
#Log.log().error("start: #{start_datetime}")
|
@@ -613,23 +608,26 @@ module Aspera
|
|
613
608
|
end
|
614
609
|
events=analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",option_url_query(filter))[:data][event_type]
|
615
610
|
startdate_persistency.save unless startdate_persistency.nil?
|
616
|
-
if !
|
611
|
+
if !options.get_option(:notif_to,:optional).nil?
|
617
612
|
events.each do |tr_event|
|
618
|
-
|
613
|
+
config.send_email_template({ev: tr_event})
|
619
614
|
end
|
620
615
|
end
|
621
616
|
return {type: :object_list,data: events}
|
622
617
|
end
|
623
618
|
when :resource
|
624
|
-
resource_type=
|
619
|
+
resource_type=options.get_next_argument('resource',
|
620
|
+
[:self,:organization,:user,:group,:client,:contact,:dropbox,:node,:operation,:package,:saml_configuration, :workspace, :dropbox_membership,:short_link,:workspace_membership,
|
621
|
+
:application,:client_registration_token,:client_access_key,:kms_profile])
|
625
622
|
# get path on API, resource type is singular, but api is plural
|
626
|
-
resource_class_path=
|
623
|
+
resource_class_path=
|
624
|
+
case resource_type
|
627
625
|
# special cases: singleton, in admin, with x
|
628
|
-
when :self,:organization
|
629
|
-
when :client_registration_token,:client_access_key
|
630
|
-
when :application
|
631
|
-
when :dropbox
|
632
|
-
when :kms_profile
|
626
|
+
when :self,:organization then resource_type
|
627
|
+
when :client_registration_token,:client_access_key then "admin/#{resource_type}s"
|
628
|
+
when :application then 'admin/apps_new'
|
629
|
+
when :dropbox then resource_type.to_s+'es'
|
630
|
+
when :kms_profile then "integrations/#{resource_type}s"
|
633
631
|
else resource_type.to_s+'s'
|
634
632
|
end
|
635
633
|
# build list of supported operations
|
@@ -640,9 +638,9 @@ module Aspera
|
|
640
638
|
supported_operations.push(:v4,:v3) if resource_type.eql?(:node)
|
641
639
|
supported_operations.push(:set_pub_key) if resource_type.eql?(:client)
|
642
640
|
supported_operations.push(:shared_folders,:shared_create) if [:node,:workspace].include?(resource_type)
|
643
|
-
command=
|
641
|
+
command=options.get_next_command(supported_operations)
|
644
642
|
# require identifier for non global commands
|
645
|
-
if !singleton_object
|
643
|
+
if !singleton_object && !global_operations.include?(command)
|
646
644
|
res_id=get_resource_id_from_args(resource_class_path)
|
647
645
|
resource_instance_path="#{resource_class_path}/#{res_id}"
|
648
646
|
end
|
@@ -653,23 +651,24 @@ module Aspera
|
|
653
651
|
id_result='token' if resource_class_path.eql?('admin/client_registration_tokens')
|
654
652
|
# TODO: report inconsistency: creation url is !=, and does not return id.
|
655
653
|
resource_class_path='admin/client_registration/token' if resource_class_path.eql?('admin/client_registration_tokens')
|
656
|
-
list_or_one=
|
657
|
-
return do_bulk_operation(list_or_one,'created',id_result)do|params|
|
654
|
+
list_or_one=options.get_next_argument('creation data (Hash)')
|
655
|
+
return do_bulk_operation(list_or_one,'created',id_result) do |params|
|
658
656
|
raise 'expecting Hash' unless params.is_a?(Hash)
|
659
|
-
|
657
|
+
aoc_api.create(resource_class_path,params)[:data]
|
660
658
|
end
|
661
659
|
when :list
|
662
660
|
default_fields=['id']
|
663
661
|
default_query={}
|
664
662
|
case resource_type
|
665
|
-
when :application
|
666
|
-
|
667
|
-
when :
|
668
|
-
when :
|
669
|
-
when :
|
670
|
-
when :
|
671
|
-
when :
|
672
|
-
when :
|
663
|
+
when :application then default_query={organization_apps: true};
|
664
|
+
default_fields.push('app_type','app_name','available','direct_authorizations_allowed','workspace_authorizations_allowed')
|
665
|
+
when :client,:client_access_key,:dropbox,:group,:package,:saml_configuration,:workspace then default_fields.push('name')
|
666
|
+
when :client_registration_token then default_fields.push('value','data.client_subject_scopes','created_at')
|
667
|
+
when :contact then default_fields=['email','name','source_id','source_type']
|
668
|
+
when :node then default_fields.push('name','host','access_key')
|
669
|
+
when :operation then default_fields=nil
|
670
|
+
when :short_link then default_fields.push('short_url','data.url_token_data.purpose')
|
671
|
+
when :user then default_fields.push('name','email')
|
673
672
|
end
|
674
673
|
item_list,total_count=read_with_paging(resource_class_path,option_url_query(default_query))
|
675
674
|
count_msg="Items: #{item_list.length}/#{total_count}"
|
@@ -677,52 +676,54 @@ module Aspera
|
|
677
676
|
self.format.display_status(count_msg)
|
678
677
|
return {type: :object_list,data: item_list,fields: default_fields}
|
679
678
|
when :show
|
680
|
-
object
|
681
|
-
fields=object.keys.
|
679
|
+
object=aoc_api.read(resource_instance_path)[:data]
|
680
|
+
fields=object.keys.reject{|k|k.eql?('certificate')}
|
682
681
|
return { type: :single_object, data: object, fields: fields }
|
683
682
|
when :modify
|
684
|
-
changes=
|
685
|
-
|
683
|
+
changes=options.get_next_argument('modified parameters (hash)')
|
684
|
+
aoc_api.update(resource_instance_path,changes)
|
686
685
|
return Main.result_status('modified')
|
687
686
|
when :delete
|
688
|
-
return do_bulk_operation(res_id,'deleted')do|one_id|
|
689
|
-
|
687
|
+
return do_bulk_operation(res_id,'deleted') do |one_id|
|
688
|
+
aoc_api.delete("#{resource_class_path}/#{one_id}")
|
690
689
|
{'id'=>one_id}
|
691
690
|
end
|
692
691
|
when :set_pub_key
|
693
692
|
# special : reads private and generate public
|
694
|
-
the_private_key=
|
693
|
+
the_private_key=options.get_next_argument('private_key')
|
695
694
|
the_public_key=OpenSSL::PKey::RSA.new(the_private_key).public_key.to_s
|
696
|
-
|
695
|
+
aoc_api.update(resource_instance_path,{jwt_grant_enabled: true, public_key: the_public_key})
|
697
696
|
return Main.result_success
|
698
697
|
when :v3,:v4
|
699
|
-
res_data
|
700
|
-
api_node
|
698
|
+
res_data=aoc_api.read(resource_instance_path)[:data]
|
699
|
+
api_node=aoc_api.get_node_api(res_data)
|
701
700
|
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action if command.eql?(:v3)
|
702
701
|
ak_data=api_node.call({operation: 'GET',subpath: "access_keys/#{res_data['access_key']}",headers: {'Accept'=>'application/json'}})[:data]
|
703
|
-
command_repo=
|
702
|
+
command_repo=options.get_next_command(NODE4_COMMANDS)
|
704
703
|
return execute_node_gen4_command(command_repo,{node_info: res_data, file_id: ak_data['root_file_id']})
|
705
704
|
when :shared_folders
|
706
|
-
read_params
|
707
|
-
|
708
|
-
when :
|
705
|
+
read_params=
|
706
|
+
case resource_type
|
707
|
+
when :workspace then{'access_id'=>"#{ID_AK_ADMIN}_WS_#{res_id}",'access_type'=>'user'}
|
708
|
+
when :node then{'include'=>['[]','access_level','permission_count'],'created_by_id'=>ID_AK_ADMIN}
|
709
709
|
else raise 'error'
|
710
710
|
end
|
711
|
-
res_data
|
712
|
-
fields=
|
713
|
-
|
714
|
-
when :
|
711
|
+
res_data=aoc_api.read("#{resource_instance_path}/permissions",read_params)[:data]
|
712
|
+
fields=
|
713
|
+
case resource_type
|
714
|
+
when :node then['id','file_id','file.path','access_type']
|
715
|
+
when :workspace then['id','node_id','file_id','node_name','file.path','tags.aspera.files.workspace.share_as']
|
715
716
|
else raise "unexpected resource type #{resource_type}"
|
716
717
|
end
|
717
|
-
return { type: :object_list, data: res_data
|
718
|
+
return { type: :object_list, data: res_data, fields: fields}
|
718
719
|
when :shared_create
|
719
720
|
# TODO: finish implementation
|
720
|
-
folder_path=
|
721
|
-
user_create_data=
|
722
|
-
res_data
|
723
|
-
node_file =
|
721
|
+
folder_path=options.get_next_argument('folder path in node')
|
722
|
+
user_create_data=options.get_next_argument('creation data (Hash)')
|
723
|
+
res_data=aoc_api.read(resource_instance_path)[:data]
|
724
|
+
node_file = aoc_api.resolve_node_file({node_info: res_data, file_id: ak_data['root_file_id']},folder_path)
|
724
725
|
|
725
|
-
#node_api
|
726
|
+
#node_api=aoc_api.get_node_api(node_file[:node_info])
|
726
727
|
#file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
|
727
728
|
|
728
729
|
access_id="#{ID_AK_ADMIN}_WS_#{@workspace_id}"
|
@@ -735,10 +736,10 @@ module Aspera
|
|
735
736
|
'id' =>@workspace_id,
|
736
737
|
'workspace_name' =>@workspace_name,
|
737
738
|
'share_as' =>File.basename(folder_path),
|
738
|
-
'user_name'
|
739
|
-
'shared_by_user_id'
|
740
|
-
'shared_by_name'
|
741
|
-
'shared_by_email'
|
739
|
+
'user_name' =>aoc_api.user_info['name'],
|
740
|
+
'shared_by_user_id'=>aoc_api.user_info['id'],
|
741
|
+
'shared_by_name' =>aoc_api.user_info['name'],
|
742
|
+
'shared_by_email' =>aoc_api.user_info['email'],
|
742
743
|
'shared_with_name' =>access_id,
|
743
744
|
'access_key' =>node_file[:node_info]['access_key'],
|
744
745
|
'node' =>node_file[:node_info]['name']}
|
@@ -749,17 +750,15 @@ module Aspera
|
|
749
750
|
else raise 'unknown command'
|
750
751
|
end
|
751
752
|
when :usage_reports
|
752
|
-
return {type: :object_list,data:
|
753
|
+
return {type: :object_list,data: aoc_api.read('usage_reports',{workspace_id: @workspace_id})[:data]}
|
753
754
|
end
|
754
755
|
end
|
755
756
|
|
756
757
|
# must be public
|
757
|
-
ACTIONS=[
|
758
|
+
ACTIONS=[:reminder, :servers, :bearer_token, :organization, :tier_restrictions, :user, :packages, :files, :admin, :automation, :gateway].freeze
|
758
759
|
|
759
760
|
def execute_action
|
760
|
-
command=
|
761
|
-
# all commands require to login, but those 2
|
762
|
-
get_api unless [:reminder,:servers].include?(command)
|
761
|
+
command=options.get_next_command(ACTIONS)
|
763
762
|
case command
|
764
763
|
when :reminder
|
765
764
|
# send an email reminder with list of orgs
|
@@ -769,48 +768,48 @@ module Aspera
|
|
769
768
|
when :servers
|
770
769
|
return {type: :object_list,data: Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
|
771
770
|
when :bearer_token
|
772
|
-
return {type: :text,data:
|
771
|
+
return {type: :text,data: aoc_api.oauth_token}
|
773
772
|
when :organization
|
774
|
-
return { type: :single_object, data:
|
773
|
+
return { type: :single_object, data: aoc_api.read('organization')[:data] }
|
775
774
|
when :tier_restrictions
|
776
|
-
return { type: :single_object, data:
|
775
|
+
return { type: :single_object, data: aoc_api.read('tier_restrictions')[:data] }
|
777
776
|
when :user
|
778
|
-
case
|
777
|
+
case options.get_next_command([:workspaces,:profile])
|
779
778
|
# when :settings
|
780
|
-
# return {type: :object_list,data:
|
779
|
+
# return {type: :object_list,data: aoc_api.read('client_settings/')[:data]}
|
781
780
|
when :workspaces
|
782
|
-
case
|
781
|
+
case options.get_next_command([:list,:current])
|
783
782
|
when :list
|
784
|
-
return {type: :object_list,data:
|
783
|
+
return {type: :object_list,data: aoc_api.read('workspaces')[:data],fields: ['id','name']}
|
785
784
|
when :current
|
786
785
|
set_workspace_info
|
787
786
|
return { type: :single_object, data: @workspace_data }
|
788
787
|
end
|
789
788
|
when :profile
|
790
|
-
case
|
789
|
+
case options.get_next_command([:show,:modify])
|
791
790
|
when :show
|
792
|
-
return { type: :single_object, data:
|
791
|
+
return { type: :single_object, data: aoc_api.user_info }
|
793
792
|
when :modify
|
794
|
-
|
793
|
+
aoc_api.update("users/#{aoc_api.user_info['id']}",options.get_next_argument('modified parameters (hash)'))
|
795
794
|
return Main.result_status('modified')
|
796
795
|
end
|
797
796
|
end
|
798
797
|
when :packages
|
799
798
|
set_workspace_info if @url_token_data.nil?
|
800
|
-
case
|
799
|
+
case options.get_next_command([:shared_inboxes, :send, :recv, :list, :show, :delete])
|
801
800
|
when :shared_inboxes
|
802
|
-
case
|
801
|
+
case options.get_next_command([:list, :show])
|
803
802
|
when :list
|
804
803
|
query=option_url_query(nil)
|
805
804
|
if query.nil?
|
806
805
|
query={'embed[]'=>'dropbox','workspace_id'=>@workspace_id,'aggregate_permissions_by_dropbox'=>true,'sort'=>'dropbox_name'}
|
807
806
|
end
|
808
|
-
return {type: :object_list,data:
|
807
|
+
return {type: :object_list,data: aoc_api.read('dropbox_memberships',query)[:data],fields: ['dropbox_id','dropbox.name']}
|
809
808
|
when :show
|
810
|
-
return {type: :single_object,data:
|
809
|
+
return {type: :single_object,data: aoc_api.read(get_resource_path_from_args('dropboxes'),query)[:data]}
|
811
810
|
end
|
812
811
|
when :send
|
813
|
-
package_data=
|
812
|
+
package_data=options.get_option(:value,:mandatory)
|
814
813
|
raise CliBadArgument,'value must be hash, refer to doc' unless package_data.is_a?(Hash)
|
815
814
|
|
816
815
|
if !@url_token_data.nil?
|
@@ -831,56 +830,56 @@ module Aspera
|
|
831
830
|
normalize_metadata(package_data)
|
832
831
|
|
833
832
|
# create a new package container
|
834
|
-
package_info
|
833
|
+
package_info=aoc_api.create('packages',package_data)[:data]
|
835
834
|
|
836
835
|
# get node information for the node on which package must be created
|
837
|
-
node_info
|
836
|
+
node_info=aoc_api.read("nodes/#{package_info['node_id']}")[:data]
|
838
837
|
|
839
838
|
# tell AoC what to expect in package: 1 transfer (can also be done after transfer)
|
840
839
|
# TODO: if multisession was used we should probably tell
|
841
840
|
# also, currently no "multi-source" , i.e. only from client-side files, unless "node" agent is used
|
842
|
-
|
841
|
+
aoc_api.update("packages/#{package_info['id']}",{'sent'=>true,'transfers_expected'=>1})[:data]
|
843
842
|
|
844
843
|
# get destination: package folder
|
845
844
|
node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
|
846
845
|
# execute transfer, raise exception if at least one error
|
847
|
-
Main.result_transfer(transfer_start(AoC::PACKAGES_APP,
|
846
|
+
Main.result_transfer(transfer_start(AoC::PACKAGES_APP,Fasp::TransferSpec::DIRECTION_SEND,node_file,AoC.package_tags(package_info,'upload')))
|
848
847
|
# return all info on package
|
849
848
|
return { type: :single_object, data: package_info}
|
850
849
|
when :recv
|
851
850
|
if !@url_token_data.nil?
|
852
851
|
assert_public_link_types(['view_received_package'])
|
853
|
-
|
852
|
+
options.set_option(:id,@url_token_data['data']['package_id'])
|
854
853
|
end
|
855
854
|
# scalar here
|
856
|
-
ids_to_download=
|
855
|
+
ids_to_download=instance_identifier()
|
857
856
|
skip_ids_data=[]
|
858
857
|
skip_ids_persistency=nil
|
859
|
-
if
|
858
|
+
if options.get_option(:once_only,:mandatory)
|
860
859
|
skip_ids_persistency=PersistencyActionOnce.new(
|
861
860
|
manager: @agents[:persistency],
|
862
861
|
data: skip_ids_data,
|
863
|
-
id: IdGenerator.from_list(['aoc_recv',
|
862
|
+
id: IdGenerator.from_list(['aoc_recv',options.get_option(:url,:mandatory),@workspace_id].push(*@persist_ids)))
|
864
863
|
end
|
865
864
|
if ids_to_download.eql?(VAL_ALL)
|
866
865
|
# get list of packages in inbox
|
867
|
-
package_info
|
866
|
+
package_info=aoc_api.read('packages',{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
|
868
867
|
# remove from list the ones already downloaded
|
869
868
|
ids_to_download=package_info.map{|e|e['id']}
|
870
869
|
# array here
|
871
|
-
ids_to_download.
|
870
|
+
ids_to_download.reject!{|id|skip_ids_data.include?(id)}
|
872
871
|
end # ALL
|
873
872
|
# list here
|
874
873
|
ids_to_download = [ids_to_download] unless ids_to_download.is_a?(Array)
|
875
874
|
result_transfer=[]
|
876
875
|
self.format.display_status("found #{ids_to_download.length} package(s).")
|
877
876
|
ids_to_download.each do |package_id|
|
878
|
-
package_info
|
879
|
-
node_info
|
877
|
+
package_info=aoc_api.read("packages/#{package_id}")[:data]
|
878
|
+
node_info=aoc_api.read("nodes/#{package_info['node_id']}")[:data]
|
880
879
|
self.format.display_status("downloading package: #{package_info['name']}")
|
881
880
|
add_ts={'paths'=>[{'source'=>'.'}]}
|
882
881
|
node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
|
883
|
-
statuses=transfer_start(AoC::PACKAGES_APP,
|
882
|
+
statuses=transfer_start(AoC::PACKAGES_APP,Fasp::TransferSpec::DIRECTION_RECEIVE,node_file,AoC.package_tags(package_info,'download').merge(add_ts))
|
884
883
|
result_transfer.push({'package'=>package_id,Main::STATUS_FIELD=>statuses})
|
885
884
|
# update skip list only if all transfer sessions completed
|
886
885
|
if TransferAgent.session_status(statuses).eql?(:success)
|
@@ -890,57 +889,55 @@ module Aspera
|
|
890
889
|
end
|
891
890
|
return Main.result_transfer_multiple(result_transfer)
|
892
891
|
when :show
|
893
|
-
package_id=
|
894
|
-
package_info
|
892
|
+
package_id=options.get_next_argument('package ID')
|
893
|
+
package_info=aoc_api.read("packages/#{package_id}")[:data]
|
895
894
|
return { type: :single_object, data: package_info }
|
896
895
|
when :list
|
897
896
|
query=option_url_query({'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true})
|
898
897
|
if query.has_key?('dropbox_name')
|
899
898
|
# convenience: specify name instead of id
|
900
899
|
raise 'not both dropbox_name and dropbox_id' if query.has_key?('dropbox_id')
|
901
|
-
query['dropbox_id']
|
900
|
+
query['dropbox_id']=aoc_api.lookup_entity_by_name('dropboxes',query['dropbox_name'])['id']
|
902
901
|
query.delete('dropbox_name')
|
903
902
|
end
|
904
903
|
raise 'option must be Hash' unless query.is_a?(Hash)
|
905
904
|
query['workspace_id']||=@workspace_id
|
906
|
-
packages
|
905
|
+
packages=aoc_api.read('packages',query)[:data]
|
907
906
|
return {type: :object_list,data: packages,fields: ['id','name','bytes_transferred']}
|
908
907
|
when :delete
|
909
|
-
list_or_one=
|
910
|
-
return do_bulk_operation(list_or_one,'deleted')do|id|
|
911
|
-
raise 'expecting String identifier' unless id.is_a?(String)
|
912
|
-
|
908
|
+
list_or_one=instance_identifier()
|
909
|
+
return do_bulk_operation(list_or_one,'deleted') do |id|
|
910
|
+
raise 'expecting String identifier' unless id.is_a?(String) || id.is_a?(Integer)
|
911
|
+
aoc_api.delete("packages/#{id}")[:data]
|
913
912
|
end
|
914
913
|
end
|
915
914
|
when :files
|
916
915
|
# get workspace related information
|
917
916
|
set_workspace_info
|
918
917
|
set_home_node_file
|
919
|
-
command_repo=
|
918
|
+
command_repo=options.get_next_command([NODE4_COMMANDS,:short_link].flatten)
|
920
919
|
case command_repo
|
921
|
-
when *NODE4_COMMANDS
|
920
|
+
when *NODE4_COMMANDS then return execute_node_gen4_command(command_repo,@home_node_file)
|
922
921
|
when :short_link
|
923
|
-
folder_dest=
|
924
|
-
value_option=
|
922
|
+
folder_dest=options.get_option(:to_folder,:optional)
|
923
|
+
value_option=options.get_option(:value,:optional)
|
925
924
|
case value_option
|
926
|
-
when 'public'
|
927
|
-
|
928
|
-
when
|
929
|
-
value_option={'purpose'=>'shared_folder_auth_link'}
|
930
|
-
when NilClass,Hash
|
925
|
+
when 'public' then value_option={'purpose'=>'token_auth_redirection'}
|
926
|
+
when 'private' then value_option={'purpose'=>'shared_folder_auth_link'}
|
927
|
+
when NilClass,Hash then nil # keep value
|
931
928
|
else raise 'value must be either: public, private, Hash or nil'
|
932
929
|
end
|
933
930
|
create_params=nil
|
934
931
|
node_file=nil
|
935
932
|
if !folder_dest.nil?
|
936
|
-
node_file =
|
933
|
+
node_file = aoc_api.resolve_node_file(@home_node_file,folder_dest)
|
937
934
|
create_params={
|
938
935
|
file_id: node_file[:file_id],
|
939
936
|
node_id: node_file[:node_info]['id'],
|
940
937
|
workspace_id: @workspace_id
|
941
938
|
}
|
942
939
|
end
|
943
|
-
if !value_option.nil?
|
940
|
+
if !value_option.nil? && !create_params.nil?
|
944
941
|
case value_option['purpose']
|
945
942
|
when 'shared_folder_auth_link'
|
946
943
|
value_option['data']=create_params
|
@@ -958,11 +955,11 @@ module Aspera
|
|
958
955
|
else
|
959
956
|
raise 'purpose must be one of: token_auth_redirection or shared_folder_auth_link'
|
960
957
|
end
|
961
|
-
|
958
|
+
options.set_option(:value,value_option)
|
962
959
|
end
|
963
|
-
result=
|
964
|
-
if result[:data].is_a?(Hash)
|
965
|
-
node_api
|
960
|
+
result=entity_action(@api_aoc,'short_links',id_default: 'self')
|
961
|
+
if result[:data].is_a?(Hash) && result[:data].has_key?('created_at') && result[:data]['resource_type'].eql?('UrlToken')
|
962
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
966
963
|
# TODO: access level as arg
|
967
964
|
access_levels=Aspera::Node::ACCESS_LEVELS #['delete','list','mkdir','preview','read','rename','write']
|
968
965
|
perm_data={
|
@@ -975,8 +972,8 @@ module Aspera
|
|
975
972
|
'workspace_id' =>@workspace_id,
|
976
973
|
'workspace_name' =>@workspace_name,
|
977
974
|
'folder_name' =>'my folder',
|
978
|
-
'created_by_name'
|
979
|
-
'created_by_email'
|
975
|
+
'created_by_name' =>aoc_api.user_info['name'],
|
976
|
+
'created_by_email'=>aoc_api.user_info['email'],
|
980
977
|
'access_key' =>node_file[:node_info]['access_key'],
|
981
978
|
'node' =>node_file[:node_info]['host']
|
982
979
|
}
|
@@ -990,26 +987,27 @@ module Aspera
|
|
990
987
|
when :automation
|
991
988
|
Log.log.warn('BETA: work under progress')
|
992
989
|
# automation api is not in the same place
|
993
|
-
automation_rest_params
|
990
|
+
automation_rest_params=aoc_api.params.clone
|
994
991
|
automation_rest_params[:base_url].gsub!('/api/','/automation/')
|
995
992
|
automation_api=Rest.new(automation_rest_params)
|
996
|
-
command_automation=
|
993
|
+
command_automation=options.get_next_command([:workflows, :instances])
|
997
994
|
case command_automation
|
998
995
|
when :instances
|
999
|
-
return
|
996
|
+
return entity_action(@api_aoc,'workflow_instances')
|
1000
997
|
when :workflows
|
1001
|
-
|
1002
|
-
wf_command=self.options.get_next_command(wF_COMMANDS)
|
998
|
+
wf_command=options.get_next_command([Plugin::ALL_OPS,:action,:launch].flatten)
|
1003
999
|
case wf_command
|
1004
1000
|
when *Plugin::ALL_OPS
|
1005
|
-
return
|
1001
|
+
return entity_command(wf_command,automation_api,'workflows',id_default: :id)
|
1006
1002
|
when :launch
|
1007
|
-
wf_id=
|
1003
|
+
wf_id=instance_identifier()
|
1008
1004
|
data=automation_api.create("workflows/#{wf_id}/launch",{})[:data]
|
1009
1005
|
return {type: :single_object,data: data}
|
1010
1006
|
when :action
|
1011
|
-
|
1012
|
-
wf_id=
|
1007
|
+
#TODO: not complete
|
1008
|
+
wf_id=instance_identifier()
|
1009
|
+
wf_action_cmd=options.get_next_command([:list,:create,:show])
|
1010
|
+
Log.log.warn("Not implemented: #{wf_action_cmd}")
|
1013
1011
|
step=automation_api.create('steps',{'workflow_id'=>wf_id})[:data]
|
1014
1012
|
automation_api.update("workflows/#{wf_id}",{'step_order'=>[step['id']]})
|
1015
1013
|
action=automation_api.create('actions',{'step_id'=>step['id'],'type'=>'manual'})[:data]
|
@@ -1027,12 +1025,11 @@ module Aspera
|
|
1027
1025
|
else
|
1028
1026
|
raise "internal error: #{command}"
|
1029
1027
|
end # action
|
1030
|
-
raise
|
1028
|
+
raise 'internal error: command shall return'
|
1031
1029
|
end
|
1032
1030
|
|
1033
1031
|
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
|
1034
1032
|
private_constant :VAL_ALL,:NODE4_COMMANDS, :ID_AK_ADMIN
|
1035
|
-
|
1036
1033
|
end # AoC
|
1037
1034
|
end # Plugins
|
1038
1035
|
end # Cli
|