aspera-cli 4.11.0 → 4.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/BUGS.md +0 -1
- data/CHANGELOG.md +71 -52
- data/CONTRIBUTING.md +31 -6
- data/README.md +404 -259
- data/bin/asession +2 -2
- data/docs/test_env.conf +1 -0
- data/examples/aoc.rb +2 -2
- data/examples/dascli +11 -11
- data/examples/faspex4.rb +7 -7
- data/examples/node.rb +1 -1
- data/examples/proxy.pac +2 -2
- data/examples/server.rb +3 -3
- data/lib/aspera/aoc.rb +105 -40
- data/lib/aspera/cli/extended_value.rb +4 -4
- data/lib/aspera/cli/{formater.rb → formatter.rb} +7 -7
- data/lib/aspera/cli/listener/progress.rb +1 -1
- data/lib/aspera/cli/listener/progress_multi.rb +2 -2
- data/lib/aspera/cli/main.rb +18 -18
- data/lib/aspera/cli/manager.rb +5 -5
- data/lib/aspera/cli/plugin.rb +23 -20
- data/lib/aspera/cli/plugins/aoc.rb +75 -112
- data/lib/aspera/cli/plugins/ats.rb +6 -6
- data/lib/aspera/cli/plugins/config.rb +84 -83
- data/lib/aspera/cli/plugins/cos.rb +1 -1
- data/lib/aspera/cli/plugins/faspex.rb +38 -38
- data/lib/aspera/cli/plugins/faspex5.rb +187 -43
- data/lib/aspera/cli/plugins/node.rb +30 -37
- data/lib/aspera/cli/plugins/orchestrator.rb +7 -4
- data/lib/aspera/cli/plugins/preview.rb +10 -9
- data/lib/aspera/cli/plugins/server.rb +1 -1
- data/lib/aspera/cli/plugins/shares.rb +67 -43
- data/lib/aspera/cli/transfer_agent.rb +16 -16
- data/lib/aspera/cli/version.rb +2 -1
- data/lib/aspera/command_line_builder.rb +70 -66
- data/lib/aspera/cos_node.rb +9 -9
- data/lib/aspera/fasp/agent_base.rb +3 -1
- data/lib/aspera/fasp/agent_connect.rb +23 -23
- data/lib/aspera/fasp/agent_direct.rb +13 -14
- data/lib/aspera/fasp/agent_httpgw.rb +20 -19
- data/lib/aspera/fasp/agent_node.rb +13 -15
- data/lib/aspera/fasp/agent_trsdk.rb +1 -1
- data/lib/aspera/fasp/installation.rb +5 -5
- data/lib/aspera/fasp/listener.rb +1 -1
- data/lib/aspera/fasp/parameters.rb +49 -41
- data/lib/aspera/fasp/parameters.yaml +311 -212
- data/lib/aspera/fasp/resume_policy.rb +2 -2
- data/lib/aspera/fasp/transfer_spec.rb +0 -13
- data/lib/aspera/faspex_gw.rb +80 -161
- data/lib/aspera/faspex_postproc.rb +77 -0
- data/lib/aspera/log.rb +7 -7
- data/lib/aspera/nagios.rb +6 -6
- data/lib/aspera/node.rb +24 -19
- data/lib/aspera/oauth.rb +50 -47
- data/lib/aspera/proxy_auto_config.js +22 -22
- data/lib/aspera/proxy_auto_config.rb +3 -3
- data/lib/aspera/rest.rb +12 -10
- data/lib/aspera/rest_error_analyzer.rb +5 -5
- data/lib/aspera/secret_hider.rb +4 -3
- data/lib/aspera/ssh.rb +4 -4
- data/lib/aspera/sync.rb +37 -36
- data/lib/aspera/web_auth.rb +7 -59
- data/lib/aspera/web_server_simple.rb +76 -0
- data.tar.gz.sig +0 -0
- metadata +6 -4
- metadata.gz.sig +0 -0
data/bin/asession
CHANGED
@@ -15,9 +15,9 @@ TS_TMP_FILELIST_FOLDER = 'EX_file_list_folder'
|
|
15
15
|
|
16
16
|
SAMPLE_DEMO = '"remote_host":"demo.asperasoft.com","remote_user":"asperaweb","ssh_port":33001,"remote_password":"demoaspera"'
|
17
17
|
SAMPLE_DEMO2 = '"direction":"receive","destination_root":"./test.dir"'
|
18
|
-
def assert_usage(assertion,
|
18
|
+
def assert_usage(assertion, error_message)
|
19
19
|
return if assertion
|
20
|
-
$stderr.puts('ERROR: '.red.blink +
|
20
|
+
$stderr.puts('ERROR: '.red.blink + error_message) if error_message
|
21
21
|
$stderr.puts('USAGE')
|
22
22
|
$stderr.puts(' asession')
|
23
23
|
$stderr.puts(' asession -h|--help')
|
data/docs/test_env.conf
CHANGED
data/examples/aoc.rb
CHANGED
@@ -17,7 +17,7 @@ aoc_url = ARGV[0]
|
|
17
17
|
aoc_user = ARGV[1]
|
18
18
|
aoc_key_value = ARGV[2]
|
19
19
|
|
20
|
-
|
20
|
+
aoc_api = Aspera::AoC.new(
|
21
21
|
url: aoc_url,
|
22
22
|
auth: :jwt,
|
23
23
|
private_key: aoc_key_value,
|
@@ -25,6 +25,6 @@ aocapi = Aspera::AoC.new(
|
|
25
25
|
scope: 'user:all',
|
26
26
|
subpath: 'api/v1')
|
27
27
|
|
28
|
-
self_user_data =
|
28
|
+
self_user_data = aoc_api.read('self')
|
29
29
|
|
30
30
|
Aspera::Log.dump('self', self_user_data)
|
data/examples/dascli
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
#!/usr/bin/env bash
|
2
2
|
# set env var image to specify another docker image
|
3
|
-
: ${image:=martinlaurent/ascli}
|
3
|
+
: "${image:=martinlaurent/ascli}"
|
4
4
|
# set env var version to specify another image version (default: latest version)
|
5
|
-
: ${version:=latest}
|
5
|
+
: "${version:=latest}"
|
6
6
|
# set env var imgtag to specify a specific image/version
|
7
|
-
: ${imgtag=$image:$version}
|
7
|
+
: "${imgtag=$image:$version}"
|
8
8
|
# set env var `docker` to podman, to use podman
|
9
|
-
: ${docker:=docker}
|
10
|
-
# set env var docker_args to add options to docker run (transform var into array)
|
11
|
-
add_dock_args
|
9
|
+
: "${docker:=docker}"
|
10
|
+
# set env var docker_args to add options to docker run (transform var into array) # spellcheck disable=SC2086
|
11
|
+
read -a add_dock_args <<< $docker_args
|
12
12
|
# set env var ASCLI_HOME to set the config folder on host
|
13
|
-
: ${ASCLI_HOME:=$HOME/.aspera/ascli}
|
13
|
+
: "${ASCLI_HOME:=$HOME/.aspera/ascli}"
|
14
14
|
# main config folder for ascli in container (same value as in `Dockerfile`)
|
15
15
|
ascli_home_container=/home/cliuser/.aspera/ascli
|
16
|
-
if test ! -d $ASCLI_HOME;then
|
17
|
-
echo "creating
|
16
|
+
if test ! -d "$ASCLI_HOME";then
|
17
|
+
echo "creating folder: $ASCLI_HOME"
|
18
18
|
# create it if necessary to allow mounting the volume in container
|
19
19
|
mkdir -p "$ASCLI_HOME"
|
20
20
|
fi
|
@@ -23,8 +23,8 @@ exec $docker run \
|
|
23
23
|
--tty \
|
24
24
|
--interactive \
|
25
25
|
--user root \
|
26
|
-
--env ASCLI_HOME
|
26
|
+
--env ASCLI_HOME="$ascli_home_container" \
|
27
27
|
--volume "$ASCLI_HOME:$ascli_home_container" \
|
28
28
|
"${add_dock_args[@]}" \
|
29
|
-
$imgtag \
|
29
|
+
"$imgtag" \
|
30
30
|
"$@"
|
data/examples/faspex4.rb
CHANGED
@@ -82,13 +82,13 @@ end
|
|
82
82
|
api_v4 = Aspera::Rest.new({
|
83
83
|
base_url: faspex_url + '/api',
|
84
84
|
auth: {
|
85
|
-
type:
|
86
|
-
base_url:
|
87
|
-
auth:
|
88
|
-
|
89
|
-
generic:
|
90
|
-
scope:
|
85
|
+
type: :oauth2,
|
86
|
+
base_url: faspex_url + '/auth/oauth2',
|
87
|
+
auth: {type: :basic, username: faspex_user, password: faspex_pass},
|
88
|
+
grant_method: :generic,
|
89
|
+
generic: {grant_type: 'password'},
|
90
|
+
scope: 'admin'
|
91
91
|
}})
|
92
92
|
|
93
|
-
# Use it. Note that Faspex 4 API v4 is totally different from Faspex 4 v3 APIs, see ref
|
93
|
+
# Use it. Note that Faspex 4 API v4 is totally different from Faspex 4 v3 APIs, see ref in header
|
94
94
|
Aspera::Log.dump('users', api_v4.read('users')[:data])
|
data/examples/node.rb
CHANGED
@@ -23,7 +23,7 @@ node_user = ARGV.shift
|
|
23
23
|
node_pass = ENV['PASSWORD']
|
24
24
|
|
25
25
|
##############################################################
|
26
|
-
# generic
|
26
|
+
# generic initialization : configuration of FaspManager
|
27
27
|
|
28
28
|
# set trace level for sample, set to :debug to see complete list of debug information
|
29
29
|
Aspera::Log.instance.level = :debug
|
data/examples/proxy.pac
CHANGED
@@ -4,7 +4,7 @@ function FindProxyForURL(url, host) {
|
|
4
4
|
url = url.toLowerCase();
|
5
5
|
host = host.toLowerCase();
|
6
6
|
|
7
|
-
/* Don't proxy local
|
7
|
+
/* Don't proxy local host names */
|
8
8
|
if (isPlainHostName(host)) {
|
9
9
|
return 'DIRECT';
|
10
10
|
}
|
@@ -31,7 +31,7 @@ function FindProxyForURL(url, host) {
|
|
31
31
|
if (isResolvable(host)) {
|
32
32
|
var hostIP = dnsResolve(host);
|
33
33
|
|
34
|
-
/* Don't proxy
|
34
|
+
/* Don't proxy private addresses (RFC 3330) */
|
35
35
|
if (isInNet(hostIP, '0.0.0.0', '255.0.0.0')
|
36
36
|
|| isInNet(hostIP, '10.0.0.0', '255.0.0.0')
|
37
37
|
|| isInNet(hostIP, '127.0.0.0', '255.0.0.0')
|
data/examples/server.rb
CHANGED
@@ -23,7 +23,7 @@ server_user = ARGV.shift
|
|
23
23
|
server_pass = ENV['PASSWORD']
|
24
24
|
|
25
25
|
##############################################################
|
26
|
-
# generic
|
26
|
+
# generic initialization : configuration of FaspManager
|
27
27
|
|
28
28
|
# set trace level for sample, set to :debug to see complete list of debug information
|
29
29
|
Aspera::Log.instance.level = :debug
|
@@ -66,7 +66,7 @@ transfer_agent.add_listener(MyListener.new)
|
|
66
66
|
##############################################################
|
67
67
|
# first example: download by SSH credentials
|
68
68
|
|
69
|
-
# manually build
|
69
|
+
# manually build transfer spec
|
70
70
|
transfer_spec = {
|
71
71
|
'remote_host' => server_uri.host,
|
72
72
|
'ssh_port' => server_uri.port,
|
@@ -82,7 +82,7 @@ transfer_spec = {
|
|
82
82
|
transfer_agent.start_transfer(transfer_spec)
|
83
83
|
|
84
84
|
# optional: helper method: wait for completion of transfers
|
85
|
-
# here we started a single transfer session (no
|
85
|
+
# here we started a single transfer session (no multi session parameter)
|
86
86
|
# get array of status, one for each session (so, a single value array)
|
87
87
|
# each status is either :success or "error message"
|
88
88
|
transfer_result = transfer_agent.wait_for_transfers_completion
|
data/lib/aspera/aoc.rb
CHANGED
@@ -13,14 +13,14 @@ Aspera::Oauth.register_token_creator(
|
|
13
13
|
lambda{|o|
|
14
14
|
o.api.call({
|
15
15
|
operation: 'POST',
|
16
|
-
subpath: o.
|
16
|
+
subpath: o.generic_parameters[:path_token],
|
17
17
|
headers: {'Accept' => 'application/json'},
|
18
|
-
json_params: o.
|
19
|
-
url_params: o.
|
18
|
+
json_params: o.specific_parameters[:json],
|
19
|
+
url_params: o.specific_parameters[:url].merge(scope: o.generic_parameters[:scope]) # scope is here because it changes over time (node)
|
20
20
|
})
|
21
21
|
},
|
22
22
|
lambda { |oauth|
|
23
|
-
return [oauth.
|
23
|
+
return [oauth.specific_parameters.dig(:json, :url_token)]
|
24
24
|
})
|
25
25
|
|
26
26
|
module Aspera
|
@@ -122,7 +122,7 @@ module Aspera
|
|
122
122
|
raise ArgumentError, 'link option must be URL with "token" parameter' if url_param_token_pair.nil?
|
123
123
|
# ok we get it !
|
124
124
|
a_opt[:url] = 'https://' + uri.host
|
125
|
-
a_auth[:
|
125
|
+
a_auth[:grant_method] = :aoc_pub_link
|
126
126
|
a_auth[:aoc_pub_link] = {
|
127
127
|
url: {grant_type: 'url_token'}, # URL args
|
128
128
|
json: {url_token: url_param_token_pair.last} # JSON body
|
@@ -162,7 +162,7 @@ module Aspera
|
|
162
162
|
# shortcut to auth section
|
163
163
|
aoc_auth_p = aoc_rest_p[:auth]
|
164
164
|
|
165
|
-
# sets opt[:url], aoc_rest_p[:auth][:
|
165
|
+
# sets opt[:url], aoc_rest_p[:auth][:grant_method], [:auth][:aoc_pub_link] if there is a link
|
166
166
|
self.class.resolve_pub_link(aoc_auth_p, opt)
|
167
167
|
|
168
168
|
# test here because link may set url
|
@@ -181,9 +181,9 @@ module Aspera
|
|
181
181
|
aoc_auth_p[:scope] = opt[:scope]
|
182
182
|
|
183
183
|
# filled if pub link
|
184
|
-
if !aoc_auth_p.key?(:
|
184
|
+
if !aoc_auth_p.key?(:grant_method)
|
185
185
|
raise ArgumentError, 'Missing mandatory option: auth' if opt[:auth].nil?
|
186
|
-
aoc_auth_p[:
|
186
|
+
aoc_auth_p[:grant_method] = opt[:auth]
|
187
187
|
end
|
188
188
|
|
189
189
|
if aoc_auth_p[:client_id].nil?
|
@@ -191,7 +191,7 @@ module Aspera
|
|
191
191
|
end
|
192
192
|
|
193
193
|
# fill other auth parameters based on Oauth method
|
194
|
-
case aoc_auth_p[:
|
194
|
+
case aoc_auth_p[:grant_method]
|
195
195
|
when :web
|
196
196
|
raise ArgumentError, 'Missing mandatory option: redirect_uri' if opt[:redirect_uri].nil?
|
197
197
|
aoc_auth_p[:web] = {redirect_uri: opt[:redirect_uri]}
|
@@ -211,13 +211,13 @@ module Aspera
|
|
211
211
|
when :aoc_pub_link
|
212
212
|
# basic auth required for /token
|
213
213
|
aoc_auth_p[:auth] = {type: :basic, username: aoc_auth_p[:client_id], password: aoc_auth_p[:client_secret]}
|
214
|
-
else raise "ERROR: unsupported auth method: #{aoc_auth_p[:
|
214
|
+
else raise "ERROR: unsupported auth method: #{aoc_auth_p[:grant_method]}"
|
215
215
|
end
|
216
216
|
super(aoc_rest_p)
|
217
217
|
end
|
218
218
|
|
219
219
|
def url_token_data
|
220
|
-
return nil unless params[:auth][:
|
220
|
+
return nil unless params[:auth][:grant_method].eql?(:aoc_pub_link)
|
221
221
|
return @cache_url_token_info unless @cache_url_token_info.nil?
|
222
222
|
# TODO: can there be several in list ?
|
223
223
|
@cache_url_token_info = read('url_tokens')[:data].first
|
@@ -225,7 +225,7 @@ module Aspera
|
|
225
225
|
end
|
226
226
|
|
227
227
|
def additional_persistence_ids
|
228
|
-
return [
|
228
|
+
return [current_user_info['id']] if url_token_data.nil?
|
229
229
|
return [] # TODO : url_token_data['id'] ?
|
230
230
|
end
|
231
231
|
|
@@ -236,7 +236,7 @@ module Aspera
|
|
236
236
|
end
|
237
237
|
|
238
238
|
# cached user information
|
239
|
-
def
|
239
|
+
def current_user_info(exception: false)
|
240
240
|
if @cache_user_info.nil?
|
241
241
|
# get our user's default information
|
242
242
|
@cache_user_info =
|
@@ -255,7 +255,21 @@ module Aspera
|
|
255
255
|
# @returns [Aspera::Node] a node API for access key
|
256
256
|
# @param node_id [String] identifier of node in AoC
|
257
257
|
# @param scope e.g. SCOPE_NODE_USER, or nil (requires secret)
|
258
|
-
def
|
258
|
+
def node_api_from(node_id: nil, workspace_info: nil, package_info: nil, scope: nil)
|
259
|
+
if node_id.nil?
|
260
|
+
if package_info.nil?
|
261
|
+
raise 'INTERNAL ERROR: either node_id or package_info is required'
|
262
|
+
else
|
263
|
+
node_id = package_info['node_id']
|
264
|
+
end
|
265
|
+
end
|
266
|
+
if workspace_info.nil?
|
267
|
+
if package_info.nil?
|
268
|
+
raise 'INTERNAL ERROR: either workspace_info or package_info is required'
|
269
|
+
else
|
270
|
+
workspace_info = package_info['workspace_id']
|
271
|
+
end
|
272
|
+
end
|
259
273
|
node_info = read("nodes/#{node_id}")[:data]
|
260
274
|
node_rest_params = {base_url: node_info['url']}
|
261
275
|
# if secret is available
|
@@ -270,20 +284,20 @@ module Aspera
|
|
270
284
|
node_rest_params[:auth] = params[:auth].clone
|
271
285
|
node_rest_params[:auth][:scope] = self.class.node_scope(node_info['access_key'], scope)
|
272
286
|
# special header required for bearer token only
|
273
|
-
node_rest_params[:headers] = {Aspera::Node::
|
287
|
+
node_rest_params[:headers] = {Aspera::Node::HEADER_X_ASPERA_ACCESS_KEY => node_info['access_key']}
|
274
288
|
end
|
275
289
|
app_info = {
|
276
|
-
|
277
|
-
|
278
|
-
app:
|
279
|
-
api:
|
290
|
+
node_info: node_info,
|
291
|
+
workspace_info: workspace_info,
|
292
|
+
app: package_info.nil? ? FILES_APP : PACKAGES_APP,
|
293
|
+
api: self # for callback
|
280
294
|
}
|
281
295
|
app_info[:package_info] = package_info unless package_info.nil?
|
282
296
|
return Node.new(params: node_rest_params, app_info: app_info)
|
283
297
|
end
|
284
298
|
|
285
299
|
# Query entity type by name and returns the id if a single entry only
|
286
|
-
# @param entity_type path of
|
300
|
+
# @param entity_type path of entity in API
|
287
301
|
# @param entity_name name of searched entity
|
288
302
|
# @param options additional search options
|
289
303
|
def lookup_entity_by_name(entity_type, entity_name, options={})
|
@@ -295,11 +309,11 @@ module Aspera
|
|
295
309
|
else
|
296
310
|
# multiple case insensitive partial matches, try case insensitive full match
|
297
311
|
# (anyway AoC does not allow creation of 2 entities with same case insensitive name)
|
298
|
-
|
299
|
-
case
|
300
|
-
when 1 then return
|
312
|
+
name_matches = matching_items.select{|i|i['name'].casecmp?(entity_name)}
|
313
|
+
case name_matches.length
|
314
|
+
when 1 then return name_matches.first
|
301
315
|
when 0 then raise %Q(#{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.) # rubocop:disable Layout/LineLength
|
302
|
-
else raise "Two entities cannot have the same case insensitive name: #{
|
316
|
+
else raise "Two entities cannot have the same case insensitive name: #{name_matches.map{|i|i['name']}}"
|
303
317
|
end
|
304
318
|
end
|
305
319
|
end
|
@@ -311,9 +325,7 @@ module Aspera
|
|
311
325
|
pkg_data['recipients'].first.is_a?(Hash) &&
|
312
326
|
pkg_data['recipients'].first.key?('type') &&
|
313
327
|
pkg_data['recipients'].first['type'].eql?('dropbox')
|
314
|
-
|
315
|
-
shbx_kid = pkg_data['recipients'].first['id']
|
316
|
-
meta_schema = read("dropboxes/#{shbx_kid}")[:data]['metadata_schema']
|
328
|
+
meta_schema = read("dropboxes/#{pkg_data['recipients'].first['id']}")[:data]['metadata_schema']
|
317
329
|
if meta_schema.nil? || meta_schema.empty?
|
318
330
|
Log.log.debug('no metadata in shared inbox')
|
319
331
|
return
|
@@ -344,8 +356,9 @@ module Aspera
|
|
344
356
|
# @return nil package_data is modified
|
345
357
|
def resolve_package_recipients(package_data, ws_id, recipient_list_field, new_user_option)
|
346
358
|
return unless package_data.key?(recipient_list_field)
|
347
|
-
raise
|
359
|
+
raise "#{recipient_list_field} must be an Array" unless package_data[recipient_list_field].is_a?(Array)
|
348
360
|
new_user_option = {'package_contact' => true} if new_user_option.nil?
|
361
|
+
raise 'new_user_option must be a Hash' unless new_user_option.is_a?(Hash)
|
349
362
|
# list with resolved elements
|
350
363
|
resolved_list = []
|
351
364
|
package_data[recipient_list_field].each do |short_recipient_info|
|
@@ -382,6 +395,58 @@ module Aspera
|
|
382
395
|
return nil
|
383
396
|
end
|
384
397
|
|
398
|
+
# CLI allows simplified format for metadata: transform if necessary for API
|
399
|
+
def update_package_metadata_for_api(pkg_data)
|
400
|
+
case pkg_data['metadata']
|
401
|
+
when Array, NilClass # no action
|
402
|
+
when Hash
|
403
|
+
api_meta = []
|
404
|
+
pkg_data['metadata'].each do |k, v|
|
405
|
+
api_meta.push({
|
406
|
+
# 'input_type' => 'single-dropdown',
|
407
|
+
'name' => k,
|
408
|
+
'values' => v.is_a?(Array) ? v : [v]
|
409
|
+
})
|
410
|
+
end
|
411
|
+
pkg_data['metadata'] = api_meta
|
412
|
+
else raise "metadata field if not of expected type: #{pkg_meta.class}"
|
413
|
+
end
|
414
|
+
return nil
|
415
|
+
end
|
416
|
+
|
417
|
+
# create a package
|
418
|
+
# @param package_data [Hash] package creation (with extensions...)
|
419
|
+
# @param validate_meta [TrueClass,FalseClass] true to validate parameters locally
|
420
|
+
# @param new_user_option [Hash] options if an unknown user is specified
|
421
|
+
# @return transfer spec, node api and package information
|
422
|
+
def create_package_simple(package_data, validate_meta, new_user_option)
|
423
|
+
update_package_metadata_for_api(package_data)
|
424
|
+
# list of files to include in package, optional
|
425
|
+
# package_data['file_names']||=[..list of filenames to transfer...]
|
426
|
+
|
427
|
+
# lookup users
|
428
|
+
resolve_package_recipients(package_data, package_data['workspace_id'], 'recipients', new_user_option)
|
429
|
+
resolve_package_recipients(package_data, package_data['workspace_id'], 'bcc_recipients', new_user_option)
|
430
|
+
|
431
|
+
validate_metadata(package_data) if validate_meta
|
432
|
+
|
433
|
+
# create a new package container
|
434
|
+
created_package = create('packages', package_data)[:data]
|
435
|
+
|
436
|
+
package_node_api = node_api_from(package_info: created_package, scope: AoC::SCOPE_NODE_USER)
|
437
|
+
|
438
|
+
# tell AoC what to expect in package: 1 transfer (can also be done after transfer)
|
439
|
+
# TODO: if multi session was used we should probably tell
|
440
|
+
# also, currently no "multi-source" , i.e. only from client-side files, unless "node" agent is used
|
441
|
+
update("packages/#{created_package['id']}", {'sent' => true, 'transfers_expected' => 1})[:data]
|
442
|
+
|
443
|
+
return {
|
444
|
+
spec: package_node_api.transfer_spec_gen4(created_package['contents_file_id'], Fasp::TransferSpec::DIRECTION_SEND),
|
445
|
+
node: package_node_api,
|
446
|
+
info: created_package
|
447
|
+
}
|
448
|
+
end
|
449
|
+
|
385
450
|
# Add transferspec
|
386
451
|
# callback in Aspera::Node (transfer_spec_gen4)
|
387
452
|
def add_ts_tags(transfer_spec:, app_info:)
|
@@ -389,7 +454,7 @@ module Aspera
|
|
389
454
|
transfer_type = Fasp::TransferSpec.action(transfer_spec)
|
390
455
|
# Analytics tags
|
391
456
|
################
|
392
|
-
ws_info = app_info[:
|
457
|
+
ws_info = app_info[:workspace_info]
|
393
458
|
transfer_spec.deep_merge!({
|
394
459
|
'tags' => {
|
395
460
|
'aspera' => {
|
@@ -405,7 +470,7 @@ module Aspera
|
|
405
470
|
# Console cookie
|
406
471
|
################
|
407
472
|
# we are sure that fields are not nil
|
408
|
-
cookie_elements = [app_info[:app],
|
473
|
+
cookie_elements = [app_info[:app], current_user_info['name'], current_user_info['email']].map{|e|Base64.strict_encode64(e)}
|
409
474
|
cookie_elements.unshift(COOKIE_PREFIX_CONSOLE_AOC)
|
410
475
|
transfer_spec['cookie'] = cookie_elements.join(':')
|
411
476
|
# Application tags
|
@@ -433,7 +498,7 @@ module Aspera
|
|
433
498
|
# Callback from Plugins::Node
|
434
499
|
def permissions_create_params(create_param:, app_info:)
|
435
500
|
# workspace shared folder:
|
436
|
-
# access_id = "#{ID_AK_ADMIN}_WS_#{ app_info[:
|
501
|
+
# access_id = "#{ID_AK_ADMIN}_WS_#{ app_info[:workspace_info]['id']}"
|
437
502
|
default_params = {
|
438
503
|
# 'access_type' => 'user', # mandatory: user or group
|
439
504
|
# 'access_id' => access_id, # id of user or group
|
@@ -441,12 +506,12 @@ module Aspera
|
|
441
506
|
'aspera' => {
|
442
507
|
'files' => {
|
443
508
|
'workspace' => {
|
444
|
-
'id' => app_info[:
|
445
|
-
'workspace_name' => app_info[:
|
446
|
-
'user_name' =>
|
447
|
-
'shared_by_user_id' =>
|
448
|
-
'shared_by_name' =>
|
449
|
-
'shared_by_email' =>
|
509
|
+
'id' => app_info[:workspace_info]['id'],
|
510
|
+
'workspace_name' => app_info[:workspace_info]['name'],
|
511
|
+
'user_name' => current_user_info['name'],
|
512
|
+
'shared_by_user_id' => current_user_info['id'],
|
513
|
+
'shared_by_name' => current_user_info['name'],
|
514
|
+
'shared_by_email' => current_user_info['email'],
|
450
515
|
# 'shared_with_name' => access_id,
|
451
516
|
'access_key' => app_info[:node_info]['access_key'],
|
452
517
|
'node' => app_info[:node_info]['name']}}}}}
|
@@ -455,13 +520,13 @@ module Aspera
|
|
455
520
|
contact_info = lookup_entity_by_name(
|
456
521
|
'contacts',
|
457
522
|
create_param['with'],
|
458
|
-
{'current_workspace_id' => app_info[:
|
523
|
+
{'current_workspace_id' => app_info[:workspace_info]['id'], 'context' => 'share_folder'})
|
459
524
|
create_param.delete('with')
|
460
525
|
create_param['access_type'] = contact_info['source_type']
|
461
526
|
create_param['access_id'] = contact_info['source_id']
|
462
527
|
create_param['tags']['aspera']['files']['workspace']['shared_with_name'] = contact_info['email']
|
463
528
|
end
|
464
|
-
#
|
529
|
+
# optional
|
465
530
|
app_info[:opt_link_name] = create_param.delete('link_name')
|
466
531
|
end
|
467
532
|
|
@@ -470,7 +535,7 @@ module Aspera
|
|
470
535
|
event_creation = {
|
471
536
|
'types' => ['permission.created'],
|
472
537
|
'node_id' => app_info[:node_info]['id'],
|
473
|
-
'workspace_id' => app_info[:
|
538
|
+
'workspace_id' => app_info[:workspace_info]['id'],
|
474
539
|
'data' => created_data # Response from previous step
|
475
540
|
}
|
476
541
|
# (optional). The name of the folder to be displayed to the destination user. Use it if its value is different from the "share_as" field.
|
@@ -19,7 +19,7 @@ module Aspera
|
|
19
19
|
# decode comma separated table text
|
20
20
|
def decode_csvt(value)
|
21
21
|
col_titles = nil
|
22
|
-
|
22
|
+
hash_array = []
|
23
23
|
CSV.parse(value).each do |values|
|
24
24
|
next if values.empty?
|
25
25
|
if col_titles.nil?
|
@@ -27,11 +27,11 @@ module Aspera
|
|
27
27
|
else
|
28
28
|
entry = {}
|
29
29
|
col_titles.each{|title|entry[title] = values.shift}
|
30
|
-
|
30
|
+
hash_array.push(entry)
|
31
31
|
end
|
32
32
|
end
|
33
|
-
Log.log.warn('Titled CSV file without any line') if
|
34
|
-
return
|
33
|
+
Log.log.warn('Titled CSV file without any line') if hash_array.empty?
|
34
|
+
return hash_array
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -8,7 +8,7 @@ require 'pp'
|
|
8
8
|
module Aspera
|
9
9
|
module Cli
|
10
10
|
# Take care of output
|
11
|
-
class
|
11
|
+
class Formatter
|
12
12
|
FIELDS_ALL = 'ALL'
|
13
13
|
FIELDS_DEFAULT = 'DEF'
|
14
14
|
CSV_RECORD_SEPARATOR = "\n"
|
@@ -36,11 +36,11 @@ module Aspera
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
def flatten_config_overview(
|
39
|
+
def flatten_config_overview(hash_array_conf)
|
40
40
|
r = []
|
41
|
-
|
41
|
+
hash_array_conf.each do |config, preset|
|
42
42
|
preset.each do |parameter, value|
|
43
|
-
r.push(CONF_OVERVIEW_KEYS.zip([config, parameter, value]).to_h)
|
43
|
+
r.push(CONF_OVERVIEW_KEYS.zip([config, parameter, SecretHider.deep_remove_secret(value).to_s]).to_h)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
return r
|
@@ -52,7 +52,7 @@ module Aspera
|
|
52
52
|
|
53
53
|
# recursive function to modify a hash
|
54
54
|
# @param source [Hash] to be modified
|
55
|
-
# @param expand_last [
|
55
|
+
# @param expand_last [TrueClass,FalseClass] true if last level is not
|
56
56
|
# @param result [Hash] new hash flattened
|
57
57
|
# @param prefix [String] true if last level is not
|
58
58
|
def flattened_object(source, result: {}, prefix: '', expand_last: false)
|
@@ -131,7 +131,7 @@ module Aspera
|
|
131
131
|
|
132
132
|
def result_all_fields(_results, table_rows_hash_val)
|
133
133
|
raise 'internal error: must be array' unless table_rows_hash_val.is_a?(Array)
|
134
|
-
# get the list of all column names used in all lines, not just
|
134
|
+
# get the list of all column names used in all lines, not just first one, as all lines may have different columns
|
135
135
|
return table_rows_hash_val.each_with_object({}){|v, m|v.each_key{|c|m[c] = true}; }.keys
|
136
136
|
end
|
137
137
|
|
@@ -141,7 +141,7 @@ module Aspera
|
|
141
141
|
raise 'INTERNAL ERROR, result must have type' unless results.key?(:type)
|
142
142
|
raise 'INTERNAL ERROR, result must have data' unless results.key?(:data) || %i[empty nothing].include?(results[:type])
|
143
143
|
res_data = results[:data]
|
144
|
-
# for config
|
144
|
+
# for config overview, it is name and value
|
145
145
|
is_config_overview = res_data.is_a?(Array) && !res_data.empty? && res_data.first.is_a?(Hash) && res_data.first.keys.sort.eql?(CONF_OVERVIEW_KEYS)
|
146
146
|
SecretHider.deep_remove_secret(res_data, is_name_value: is_config_overview) unless @option_show_secrets || @option_display.eql?(:data)
|
147
147
|
# comma separated list in string format
|
@@ -45,8 +45,8 @@ module Aspera
|
|
45
45
|
Log.log.error{"Internal error: no #{Fasp::AgentBase::LISTENER_SESSION_ID_S} in event: #{data}"}
|
46
46
|
return
|
47
47
|
end
|
48
|
-
|
49
|
-
@progress_bar.title =
|
48
|
+
new_title = @sessions.length < 2 ? '' : "multi=#{@sessions.length}"
|
49
|
+
@progress_bar.title = new_title unless @progress_bar.title.eql?(new_title)
|
50
50
|
session = @sessions[data[Fasp::AgentBase::LISTENER_SESSION_ID_S]] ||= {
|
51
51
|
cumulative: 0,
|
52
52
|
job_size: 0,
|