aspera-cli 4.19.0 → 4.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +46 -0
- data/CONTRIBUTING.md +18 -4
- data/README.md +886 -510
- data/bin/asession +27 -20
- data/examples/build_exec +65 -76
- data/examples/build_exec_rubyc +40 -0
- data/examples/get_proto_file.rb +7 -0
- data/lib/aspera/agent/alpha.rb +18 -24
- data/lib/aspera/agent/base.rb +2 -18
- data/lib/aspera/agent/connect.rb +34 -15
- data/lib/aspera/agent/direct.rb +44 -54
- data/lib/aspera/agent/httpgw.rb +2 -3
- data/lib/aspera/agent/node.rb +11 -21
- data/lib/aspera/agent/{trsdk.rb → transferd.rb} +27 -51
- data/lib/aspera/api/alee.rb +15 -0
- data/lib/aspera/api/aoc.rb +139 -105
- data/lib/aspera/api/ats.rb +1 -1
- data/lib/aspera/api/cos_node.rb +1 -1
- data/lib/aspera/api/httpgw.rb +15 -10
- data/lib/aspera/api/node.rb +70 -32
- data/lib/aspera/ascmd.rb +56 -48
- data/lib/aspera/ascp/installation.rb +166 -70
- data/lib/aspera/ascp/management.rb +30 -8
- data/lib/aspera/assert.rb +10 -5
- data/lib/aspera/cli/formatter.rb +166 -162
- data/lib/aspera/cli/hints.rb +2 -1
- data/lib/aspera/cli/info.rb +12 -10
- data/lib/aspera/cli/main.rb +28 -13
- data/lib/aspera/cli/manager.rb +7 -2
- data/lib/aspera/cli/plugin.rb +17 -31
- data/lib/aspera/cli/plugins/alee.rb +3 -3
- data/lib/aspera/cli/plugins/aoc.rb +246 -208
- data/lib/aspera/cli/plugins/ats.rb +16 -14
- data/lib/aspera/cli/plugins/config.rb +154 -94
- data/lib/aspera/cli/plugins/console.rb +3 -3
- data/lib/aspera/cli/plugins/cos.rb +1 -0
- data/lib/aspera/cli/plugins/faspex.rb +15 -23
- data/lib/aspera/cli/plugins/faspex5.rb +64 -50
- data/lib/aspera/cli/plugins/faspio.rb +2 -2
- data/lib/aspera/cli/plugins/httpgw.rb +1 -1
- data/lib/aspera/cli/plugins/node.rb +174 -109
- data/lib/aspera/cli/plugins/orchestrator.rb +14 -13
- data/lib/aspera/cli/plugins/preview.rb +8 -9
- data/lib/aspera/cli/plugins/server.rb +5 -9
- data/lib/aspera/cli/plugins/shares.rb +2 -2
- data/lib/aspera/cli/sync_actions.rb +2 -2
- data/lib/aspera/cli/transfer_agent.rb +12 -14
- data/lib/aspera/cli/transfer_progress.rb +37 -17
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +4 -5
- data/lib/aspera/coverage.rb +13 -1
- data/lib/aspera/environment.rb +75 -25
- data/lib/aspera/faspex_gw.rb +2 -2
- data/lib/aspera/json_rpc.rb +1 -1
- data/lib/aspera/keychain/macos_security.rb +7 -12
- data/lib/aspera/log.rb +3 -4
- data/lib/aspera/node_simulator.rb +230 -112
- data/lib/aspera/oauth/base.rb +64 -83
- data/lib/aspera/oauth/factory.rb +52 -6
- data/lib/aspera/oauth/generic.rb +4 -8
- data/lib/aspera/oauth/jwt.rb +6 -3
- data/lib/aspera/oauth/url_json.rb +1 -2
- data/lib/aspera/oauth/web.rb +5 -2
- data/lib/aspera/persistency_action_once.rb +16 -8
- data/lib/aspera/persistency_folder.rb +20 -2
- data/lib/aspera/preview/generator.rb +1 -1
- data/lib/aspera/preview/utils.rb +11 -17
- data/lib/aspera/products/alpha.rb +30 -0
- data/lib/aspera/products/connect.rb +48 -0
- data/lib/aspera/products/other.rb +82 -0
- data/lib/aspera/products/transferd.rb +54 -0
- data/lib/aspera/rest.rb +116 -87
- data/lib/aspera/secret_hider.rb +2 -2
- data/lib/aspera/ssh.rb +31 -24
- data/lib/aspera/transfer/faux_file.rb +4 -4
- data/lib/aspera/transfer/parameters.rb +16 -17
- data/lib/aspera/transfer/spec.rb +12 -12
- data/lib/aspera/transfer/spec.yaml +22 -20
- data/lib/aspera/transfer/sync.rb +2 -10
- data/lib/aspera/transfer/uri.rb +3 -3
- data/lib/aspera/uri_reader.rb +1 -1
- data/lib/aspera/web_auth.rb +166 -17
- data/lib/aspera/web_server_simple.rb +4 -3
- data/lib/transferd_pb.rb +86 -0
- data/lib/transferd_services_pb.rb +84 -0
- data.tar.gz.sig +0 -0
- metadata +58 -22
- metadata.gz.sig +0 -0
- data/lib/aspera/ascp/products.rb +0 -156
data/lib/aspera/api/aoc.rb
CHANGED
@@ -12,18 +12,9 @@ require 'cgi'
|
|
12
12
|
|
13
13
|
module Aspera
|
14
14
|
module Api
|
15
|
-
SAAS_DOMAIN_PROD = 'ibmaspera.com'
|
16
|
-
class Alee < Aspera::Rest
|
17
|
-
def initialize(entitlement_id, customer_id, api_domain: SAAS_DOMAIN_PROD, version: 'v1')
|
18
|
-
super(
|
19
|
-
base_url: "https://api.#{api_domain}/metering/#{version}",
|
20
|
-
headers: {'X-Aspera-Entitlement-Authorization' => Rest.basic_token(entitlement_id, customer_id)}
|
21
|
-
)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
15
|
class AoC < Aspera::Rest
|
26
16
|
PRODUCT_NAME = 'Aspera on Cloud'
|
17
|
+
# use default workspace if it is set, else none
|
27
18
|
DEFAULT_WORKSPACE = ''
|
28
19
|
# Production domain of AoC
|
29
20
|
SAAS_DOMAIN_PROD = 'ibmaspera.com' # cspell:disable-line
|
@@ -72,48 +63,61 @@ module Aspera
|
|
72
63
|
return client_key, DataRepository.instance.item(client_key)
|
73
64
|
end
|
74
65
|
|
75
|
-
# base API url depends on domain, which could be "qa.xxx"
|
76
|
-
def api_base_url(
|
77
|
-
return "https
|
66
|
+
# base API url depends on domain, which could be "qa.xxx" or self-managed domain
|
67
|
+
def api_base_url(api_domain: SAAS_DOMAIN_PROD)
|
68
|
+
return "https://api.#{api_domain}"
|
78
69
|
end
|
79
70
|
|
80
|
-
# split host of
|
81
|
-
def
|
71
|
+
# split host of URL into organization and domain
|
72
|
+
def split_org_domain(uri)
|
73
|
+
Aspera.assert_type(uri, URI)
|
82
74
|
raise "No host found in URL.Please check URL format: https://myorg.#{SAAS_DOMAIN_PROD}" if uri.host.nil?
|
83
75
|
parts = uri.host.split('.', 2)
|
84
76
|
Aspera.assert(parts.length == 2){"expecting a public FQDN for #{PRODUCT_NAME}"}
|
85
|
-
|
77
|
+
parts[0] = nil if parts[0].eql?('api')
|
78
|
+
return %i{organization domain}.zip(parts).to_h
|
79
|
+
end
|
80
|
+
|
81
|
+
def saas_url?(url)
|
82
|
+
url.include?(SAAS_DOMAIN_PROD)
|
86
83
|
end
|
87
84
|
|
88
85
|
# @param url [String] URL of AoC public link
|
89
86
|
# @return [Hash] information about public link, or nil if not a public link
|
90
87
|
def link_info(url)
|
91
|
-
final_uri = Rest.new(base_url: url, redirect_max: MAX_AOC_URL_REDIRECT).
|
92
|
-
|
93
|
-
|
88
|
+
final_uri = Rest.new(base_url: url, redirect_max: MAX_AOC_URL_REDIRECT).call(operation: 'GET')[:http].uri
|
89
|
+
Log.log.trace1{Log.dump(:final_uri, final_uri)}
|
90
|
+
org_domain = split_org_domain(final_uri)
|
91
|
+
if (m = final_uri.path.match(%r{/oauth2/([^/]+)/login$}))
|
92
|
+
org_domain[:organization] = m[1] if org_domain[:organization].nil?
|
93
|
+
else
|
94
|
+
Log.log.debug{"path=#{final_uri.path} does not end with /login"}
|
95
|
+
end
|
96
|
+
raise 'AoC shall redirect to login page with a query' if final_uri.query.nil?
|
97
|
+
query = Rest.query_to_h(final_uri.query)
|
98
|
+
Log.log.trace1{Log.dump(:query, query)}
|
94
99
|
# is that a public link ?
|
95
|
-
if
|
100
|
+
if query.key?('token')
|
96
101
|
Log.log.warn{"Unknown pub link path: #{final_uri.path}"} unless PUBLIC_LINK_PATHS.include?(final_uri.path)
|
97
102
|
# ok we get it !
|
98
103
|
return {
|
99
|
-
instance_domain:
|
104
|
+
instance_domain: org_domain[:domain],
|
100
105
|
url: "https://#{final_uri.host}",
|
101
|
-
token:
|
106
|
+
token: query['token']
|
102
107
|
}
|
103
108
|
end
|
104
|
-
|
105
|
-
if decoded_query['state']
|
109
|
+
if query['state']
|
106
110
|
# can be a private link
|
107
|
-
state_uri = URI.parse(
|
108
|
-
if state_uri.query &&
|
109
|
-
decoded_state = Rest.
|
111
|
+
state_uri = URI.parse(query['state'])
|
112
|
+
if state_uri.query && query['redirect_uri']
|
113
|
+
decoded_state = Rest.query_to_h(state_uri.query)
|
110
114
|
if decoded_state.key?('short_link_url')
|
111
115
|
if (m = state_uri.path.match(%r{/files/workspaces/([0-9]+)/all/([0-9]+):([0-9]+)}))
|
112
|
-
redirect_uri = URI.parse(
|
113
|
-
|
116
|
+
redirect_uri = URI.parse(query['redirect_uri'])
|
117
|
+
org_domain = split_org_domain(redirect_uri)
|
114
118
|
return {
|
115
|
-
instance_domain:
|
116
|
-
organization:
|
119
|
+
instance_domain: org_domain[:domain],
|
120
|
+
organization: org_domain[:organization],
|
117
121
|
url: "https://#{redirect_uri.host}",
|
118
122
|
private_link: {
|
119
123
|
workspace_id: m[1],
|
@@ -125,10 +129,10 @@ module Aspera
|
|
125
129
|
end
|
126
130
|
end
|
127
131
|
end
|
128
|
-
|
132
|
+
Log.log.debug{Log.dump(:org_domain, org_domain)}
|
129
133
|
return {
|
130
|
-
instance_domain:
|
131
|
-
organization:
|
134
|
+
instance_domain: org_domain[:domain],
|
135
|
+
organization: org_domain[:organization]
|
132
136
|
}
|
133
137
|
end
|
134
138
|
end
|
@@ -149,7 +153,8 @@ module Aspera
|
|
149
153
|
@workspace_name = workspace
|
150
154
|
@cache_user_info = nil
|
151
155
|
@cache_url_token_info = nil
|
152
|
-
@
|
156
|
+
@workspace_info = nil
|
157
|
+
@home_info = nil
|
153
158
|
auth_params = {
|
154
159
|
type: :oauth2,
|
155
160
|
client_id: client_id,
|
@@ -187,6 +192,7 @@ module Aspera
|
|
187
192
|
}
|
188
193
|
# add jwt payload for global client id
|
189
194
|
auth_params[:payload][:org] = url_info[:organization] if GLOBAL_CLIENT_APPS.include?(auth_params[:client_id])
|
195
|
+
auth_params[:cache_ids] = [url_info[:organization]]
|
190
196
|
when :url_json
|
191
197
|
auth_params[:url] = {grant_type: 'url_token'} # URL arguments
|
192
198
|
auth_params[:json] = {url_token: url_info[:token]} # JSON body
|
@@ -206,7 +212,7 @@ module Aspera
|
|
206
212
|
return nil unless auth_params[:grant_method].eql?(:url_json)
|
207
213
|
return @cache_url_token_info unless @cache_url_token_info.nil?
|
208
214
|
# TODO: can there be several in list ?
|
209
|
-
@cache_url_token_info = read('url_tokens')
|
215
|
+
@cache_url_token_info = read('url_tokens').first
|
210
216
|
return @cache_url_token_info
|
211
217
|
end
|
212
218
|
|
@@ -225,7 +231,7 @@ module Aspera
|
|
225
231
|
# get our user's default information
|
226
232
|
@cache_user_info =
|
227
233
|
begin
|
228
|
-
read('self')
|
234
|
+
read('self')
|
229
235
|
rescue StandardError => e
|
230
236
|
raise e if exception
|
231
237
|
Log.log.debug{"ignoring error: #{e}"}
|
@@ -235,11 +241,20 @@ module Aspera
|
|
235
241
|
return @cache_user_info
|
236
242
|
end
|
237
243
|
|
238
|
-
|
244
|
+
def workspace
|
245
|
+
raise 'internal error: AoC workspace context is not set' if @workspace_info.nil?
|
246
|
+
@workspace_info
|
247
|
+
end
|
248
|
+
|
249
|
+
def home
|
250
|
+
raise 'internal error: AoC home context is not set' if @home_info.nil?
|
251
|
+
@home_info
|
252
|
+
end
|
253
|
+
|
254
|
+
# Set the application context
|
255
|
+
# @param application [Symbol,NilClass] :files or :packages
|
239
256
|
# @return [Hash] current context information: workspace, and home node/file if app is "Files"
|
240
|
-
def context(application
|
241
|
-
return @context_cache unless @context_cache.nil?
|
242
|
-
Aspera.assert(!application.nil?){'application must be set once'}
|
257
|
+
def context=(application)
|
243
258
|
Aspera.assert_values(application, %i[files packages])
|
244
259
|
ws_id =
|
245
260
|
if !public_link.nil?
|
@@ -249,9 +264,10 @@ module Aspera
|
|
249
264
|
Log.log.debug('Using workspace of private link')
|
250
265
|
private_link[:workspace_id]
|
251
266
|
elsif @workspace_name.eql?(DEFAULT_WORKSPACE)
|
252
|
-
|
253
|
-
|
254
|
-
|
267
|
+
if !current_user_info['default_workspace_id'].nil?
|
268
|
+
Log.log.debug('Using default workspace'.green)
|
269
|
+
current_user_info['default_workspace_id']
|
270
|
+
end
|
255
271
|
elsif @workspace_name.nil?
|
256
272
|
nil
|
257
273
|
else
|
@@ -261,39 +277,49 @@ module Aspera
|
|
261
277
|
if ws_id.nil?
|
262
278
|
nil
|
263
279
|
else
|
264
|
-
read("workspaces/#{ws_id}")
|
280
|
+
read("workspaces/#{ws_id}")
|
265
281
|
end
|
266
|
-
@
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
282
|
+
@workspace_info =
|
283
|
+
if ws_info.nil?
|
284
|
+
{
|
285
|
+
id: nil,
|
286
|
+
name: 'Shared folders'
|
287
|
+
}
|
288
|
+
else
|
289
|
+
{
|
290
|
+
id: ws_info['id'],
|
291
|
+
name: ws_info['name']
|
292
|
+
}
|
293
|
+
end
|
294
|
+
Log.log.debug{Log.dump(:context, @workspace_info)}
|
295
|
+
return nil unless application.eql?(:files)
|
296
|
+
@home_info =
|
297
|
+
if !public_link.nil?
|
298
|
+
assert_public_link_types(['view_shared_file'])
|
299
|
+
{
|
300
|
+
node_id: public_link['data']['node_id'],
|
301
|
+
file_id: public_link['data']['file_id']
|
302
|
+
}
|
303
|
+
elsif !private_link.nil?
|
304
|
+
{
|
305
|
+
node_id: private_link[:node_id],
|
306
|
+
file_id: private_link[:file_id]
|
307
|
+
}
|
308
|
+
elsif ws_info
|
309
|
+
{
|
310
|
+
node_id: ws_info['home_node_id'],
|
311
|
+
file_id: ws_info['home_file_id']
|
312
|
+
}
|
313
|
+
else
|
314
|
+
# not part of any workspace, but has some folder shared
|
315
|
+
user_info = current_user_info(exception: true) rescue {'read_only_home_node_id' => nil, 'read_only_home_file_id' => nil}
|
316
|
+
{
|
317
|
+
node_id: user_info['read_only_home_node_id'],
|
318
|
+
file_id: user_info['read_only_home_file_id']
|
319
|
+
}
|
320
|
+
end
|
321
|
+
raise "Cannot get user's home node id, check your default workspace or specify one" if @home_info[:node_id].to_s.empty?
|
322
|
+
Log.log.debug{Log.dump(:context, @home_info)}
|
297
323
|
end
|
298
324
|
|
299
325
|
# @param node_id [String] identifier of node in AoC
|
@@ -304,9 +330,9 @@ module Aspera
|
|
304
330
|
# @returns [Node] a node API for access key
|
305
331
|
def node_api_from(node_id:, workspace_id: nil, workspace_name: nil, scope: Node::SCOPE_USER, package_info: nil)
|
306
332
|
Aspera.assert_type(node_id, String)
|
307
|
-
node_info = read("nodes/#{node_id}")
|
333
|
+
node_info = read("nodes/#{node_id}")
|
308
334
|
if workspace_name.nil? && !workspace_id.nil?
|
309
|
-
workspace_name = read("workspaces/#{workspace_id}")[
|
335
|
+
workspace_name = read("workspaces/#{workspace_id}")['name']
|
310
336
|
end
|
311
337
|
app_info = {
|
312
338
|
api: self, # for callback
|
@@ -346,7 +372,7 @@ module Aspera
|
|
346
372
|
pkg_data['recipients'].first.is_a?(Hash) &&
|
347
373
|
pkg_data['recipients'].first.key?('type') &&
|
348
374
|
pkg_data['recipients'].first['type'].eql?('dropbox')
|
349
|
-
meta_schema = read("dropboxes/#{pkg_data['recipients'].first['id']}")[
|
375
|
+
meta_schema = read("dropboxes/#{pkg_data['recipients'].first['id']}")['metadata_schema']
|
350
376
|
if meta_schema.nil? || meta_schema.empty?
|
351
377
|
Log.log.debug('no metadata in shared inbox')
|
352
378
|
return
|
@@ -390,7 +416,7 @@ module Aspera
|
|
390
416
|
# email: user, else dropbox
|
391
417
|
entity_type = short_recipient_info.include?('@') ? 'contacts' : 'dropboxes'
|
392
418
|
begin
|
393
|
-
full_recipient_info = lookup_by_name(entity_type, short_recipient_info, {'current_workspace_id' => ws_id})
|
419
|
+
full_recipient_info = lookup_by_name(entity_type, short_recipient_info, query: {'current_workspace_id' => ws_id})
|
394
420
|
rescue RuntimeError => e
|
395
421
|
raise e unless e.message.start_with?(ENTITY_NOT_FOUND)
|
396
422
|
# dropboxes cannot be created on the fly
|
@@ -399,7 +425,7 @@ module Aspera
|
|
399
425
|
full_recipient_info = create('contacts', {
|
400
426
|
'current_workspace_id' => ws_id,
|
401
427
|
'email' => short_recipient_info
|
402
|
-
}.merge(new_user_option))
|
428
|
+
}.merge(new_user_option))
|
403
429
|
end
|
404
430
|
short_recipient_info = if entity_type.eql?('dropboxes')
|
405
431
|
{'id' => full_recipient_info['id'], 'type' => 'dropbox'}
|
@@ -422,13 +448,12 @@ module Aspera
|
|
422
448
|
case pkg_data['metadata']
|
423
449
|
when Array, NilClass # no action
|
424
450
|
when Hash
|
425
|
-
api_meta = []
|
426
|
-
|
427
|
-
api_meta.push({
|
451
|
+
api_meta = pkg_data['metadata'].map do |k, v|
|
452
|
+
{
|
428
453
|
# 'input_type' => 'single-dropdown',
|
429
454
|
'name' => k,
|
430
455
|
'values' => v.is_a?(Array) ? v : [v]
|
431
|
-
}
|
456
|
+
}
|
432
457
|
end
|
433
458
|
pkg_data['metadata'] = api_meta
|
434
459
|
else Aspera.error_unexpected_value(pkg_meta.class)
|
@@ -453,7 +478,7 @@ module Aspera
|
|
453
478
|
validate_metadata(package_data) if validate_meta
|
454
479
|
|
455
480
|
# create a new package container
|
456
|
-
created_package = create('packages', package_data)
|
481
|
+
created_package = create('packages', package_data)
|
457
482
|
|
458
483
|
package_node_api = node_api_from(
|
459
484
|
node_id: created_package['node_id'],
|
@@ -463,7 +488,7 @@ module Aspera
|
|
463
488
|
# tell AoC what to expect in package: 1 transfer (can also be done after transfer)
|
464
489
|
# TODO: if multi session was used we should probably tell
|
465
490
|
# also, currently no "multi-source" , i.e. only from client-side files, unless "node" agent is used
|
466
|
-
update("packages/#{created_package['id']}", {'sent' => true, 'transfers_expected' => 1})
|
491
|
+
update("packages/#{created_package['id']}", {'sent' => true, 'transfers_expected' => 1})
|
467
492
|
|
468
493
|
return {
|
469
494
|
spec: package_node_api.transfer_spec_gen4(created_package['contents_file_id'], Transfer::Spec::DIRECTION_SEND),
|
@@ -524,14 +549,14 @@ module Aspera
|
|
524
549
|
ID_AK_ADMIN = 'ASPERA_ACCESS_KEY_ADMIN'
|
525
550
|
# Callback from Plugins::Node
|
526
551
|
# add application specific tags to permissions creation
|
527
|
-
# @param
|
552
|
+
# @param perm_data [Hash] parameters for creating permissions
|
528
553
|
# @param app_info [Hash] application information
|
529
|
-
def permissions_set_create_params(
|
554
|
+
def permissions_set_create_params(perm_data:, app_info:)
|
530
555
|
# workspace shared folder:
|
531
556
|
# access_id = "#{ID_AK_ADMIN}_WS_#{app_info[:workspace_id]}"
|
532
|
-
|
557
|
+
defaults = {
|
533
558
|
# 'access_type' => 'user', # mandatory: user or group
|
534
|
-
# 'access_id' => access_id, # id of user or group
|
559
|
+
# 'access_id' => access_id, # id of user or group or special
|
535
560
|
'tags' => {
|
536
561
|
Transfer::Spec::TAG_RESERVED => {
|
537
562
|
'files' => {
|
@@ -543,6 +568,7 @@ module Aspera
|
|
543
568
|
'shared_by_name' => current_user_info['name'],
|
544
569
|
'shared_by_email' => current_user_info['email'],
|
545
570
|
# 'shared_with_name' => access_id,
|
571
|
+
# 'share_as' => new_name_for_folder,
|
546
572
|
'access_key' => app_info[:node_info]['access_key'],
|
547
573
|
'node' => app_info[:node_info]['name']
|
548
574
|
}
|
@@ -550,34 +576,42 @@ module Aspera
|
|
550
576
|
}
|
551
577
|
}
|
552
578
|
}
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
579
|
+
perm_data.deep_merge!(defaults)
|
580
|
+
tag_workspace = perm_data['tags'][Transfer::Spec::TAG_RESERVED]['files']['workspace']
|
581
|
+
case perm_data['with']
|
582
|
+
when NilClass
|
583
|
+
when ''
|
584
|
+
perm_data['access_type'] = 'user'
|
585
|
+
perm_data['access_id'] = "#{ID_AK_ADMIN}_WS_#{app_info[:workspace_id]}"
|
586
|
+
tag_workspace['shared_with_name'] = perm_data['access_id']
|
587
|
+
else
|
588
|
+
entity_info = lookup_by_name('contacts', perm_data['with'], query: {'current_workspace_id' => app_info[:workspace_id]})
|
589
|
+
perm_data['access_type'] = entity_info['source_type']
|
590
|
+
perm_data['access_id'] = entity_info['source_id']
|
591
|
+
tag_workspace['shared_with_name'] = entity_info['email']
|
592
|
+
end
|
593
|
+
perm_data.delete('with')
|
594
|
+
if perm_data.key?('as')
|
595
|
+
tag_workspace['share_as'] = perm_data['as']
|
596
|
+
perm_data.delete('as')
|
563
597
|
end
|
564
598
|
# optional
|
565
|
-
app_info[:opt_link_name] =
|
599
|
+
app_info[:opt_link_name] = perm_data.delete('link_name')
|
566
600
|
end
|
567
601
|
|
568
602
|
# Callback from Plugins::Node
|
569
603
|
# send shared folder event to AoC
|
570
|
-
# @param
|
604
|
+
# @param event_data [Hash] response from permission creation
|
571
605
|
# @param app_info [Hash] hash with app info
|
572
606
|
# @param types [Array] event types
|
573
|
-
def permissions_send_event(
|
607
|
+
def permissions_send_event(event_data:, app_info:, types: PERMISSIONS_CREATED)
|
574
608
|
Aspera.assert_type(types, Array)
|
575
609
|
Aspera.assert(!types.empty?)
|
576
610
|
event_creation = {
|
577
611
|
'types' => types,
|
578
612
|
'node_id' => app_info[:node_info]['id'],
|
579
613
|
'workspace_id' => app_info[:workspace_id],
|
580
|
-
'data' =>
|
614
|
+
'data' => event_data
|
581
615
|
}
|
582
616
|
# (optional). The name of the folder to be displayed to the destination user.
|
583
617
|
# Use it if its value is different from the "share_as" field.
|
data/lib/aspera/api/ats.rb
CHANGED
data/lib/aspera/api/cos_node.rb
CHANGED
@@ -19,7 +19,7 @@ module Aspera
|
|
19
19
|
Aspera.assert(service_credentials.key?(field)){"service_credentials must have a field: #{field}"}
|
20
20
|
end
|
21
21
|
# read endpoints from service provided in service credentials
|
22
|
-
endpoints = Aspera::Rest.new(base_url: service_credentials['endpoints']).read('')
|
22
|
+
endpoints = Aspera::Rest.new(base_url: service_credentials['endpoints']).read('')
|
23
23
|
Aspera::Log.dump('endpoints', endpoints)
|
24
24
|
endpoint = endpoints.dig('service-endpoints', 'regional', bucket_region, 'public', bucket_region)
|
25
25
|
raise "no such region: #{bucket_region}" if endpoint.nil?
|
data/lib/aspera/api/httpgw.rb
CHANGED
@@ -138,7 +138,7 @@ module Aspera
|
|
138
138
|
def upload(transfer_spec)
|
139
139
|
# identify this session uniquely
|
140
140
|
session_id = SecureRandom.uuid
|
141
|
-
@notify_cb&.call(
|
141
|
+
@notify_cb&.call(:pre_start, session_id: nil, info: 'starting')
|
142
142
|
# process files to send, modify `paths` in transfer_spec
|
143
143
|
files_to_send = process_upload_list(transfer_spec)
|
144
144
|
# total size of all files is last element
|
@@ -147,7 +147,7 @@ module Aspera
|
|
147
147
|
Log.log.trace1{Log.dump(:files_to_send, files_to_send)}
|
148
148
|
# TODO: check that this is available in endpoints: @api_info['endpoints']
|
149
149
|
upload_url = File.join(@gw_root_url, @upload_version, 'upload')
|
150
|
-
@notify_cb&.call(
|
150
|
+
@notify_cb&.call(:pre_start, session_id: nil, info: 'connecting wss')
|
151
151
|
# open web socket to end point (equivalent to Net::HTTP.start)
|
152
152
|
http_session = Rest.start_http_session(upload_url)
|
153
153
|
# get the underlying socket i/o
|
@@ -172,11 +172,11 @@ module Aspera
|
|
172
172
|
}
|
173
173
|
# start read thread after handshake
|
174
174
|
@ws_read_thread = Thread.new {process_read_thread}
|
175
|
-
@notify_cb&.call(
|
176
|
-
@notify_cb&.call(
|
175
|
+
@notify_cb&.call(:session_start, session_id: session_id)
|
176
|
+
@notify_cb&.call(:session_size, session_id: session_id, info: total_bytes_to_transfer)
|
177
177
|
sleep(1)
|
178
178
|
# notify progress bar
|
179
|
-
@notify_cb&.call(
|
179
|
+
@notify_cb&.call(:session_size, session_id: session_id, info: total_bytes_to_transfer)
|
180
180
|
# first step send transfer spec
|
181
181
|
ws_snd_json(MSG_SEND_TRANSFER_SPEC, transfer_spec)
|
182
182
|
# current file index
|
@@ -223,7 +223,7 @@ module Aspera
|
|
223
223
|
raise e
|
224
224
|
end
|
225
225
|
session_sent_bytes += slice_bin_data.length
|
226
|
-
@notify_cb&.call(
|
226
|
+
@notify_cb&.call(:transfer, session_id: session_id, info: session_sent_bytes)
|
227
227
|
slice_info[:slice] += 1
|
228
228
|
end
|
229
229
|
ensure
|
@@ -232,8 +232,8 @@ module Aspera
|
|
232
232
|
file_index += 1
|
233
233
|
end
|
234
234
|
# throttling may have skipped last one
|
235
|
-
@notify_cb&.call(
|
236
|
-
@notify_cb&.call(
|
235
|
+
@notify_cb&.call(:transfer, session_id: session_id, info: session_sent_bytes)
|
236
|
+
@notify_cb&.call(:end, session_id: session_id)
|
237
237
|
ws_send(ws_type: :close, data: nil)
|
238
238
|
Log.log.debug("Finished upload, waiting for end of #{THR_RECV} thread.")
|
239
239
|
@ws_read_thread.join
|
@@ -256,7 +256,7 @@ module Aspera
|
|
256
256
|
end
|
257
257
|
transfer_spec['download_name'] = download_name
|
258
258
|
end
|
259
|
-
creation = create('download', {'transfer_spec' => transfer_spec})
|
259
|
+
creation = create('download', {'transfer_spec' => transfer_spec})
|
260
260
|
transfer_uuid = creation['url'].split('/').last
|
261
261
|
file_name =
|
262
262
|
if transfer_spec['zip_required'] || transfer_spec['paths'].length > 1
|
@@ -274,6 +274,11 @@ module Aspera
|
|
274
274
|
return @api_info
|
275
275
|
end
|
276
276
|
|
277
|
+
# @return the base url of the gateway
|
278
|
+
def base_url
|
279
|
+
return @gw_root_url
|
280
|
+
end
|
281
|
+
|
277
282
|
# @param url [String] URL of the HTTP Gateway, without version
|
278
283
|
def initialize(
|
279
284
|
url:,
|
@@ -299,7 +304,7 @@ module Aspera
|
|
299
304
|
@synchronous = synchronous
|
300
305
|
@notify_cb = notify_cb
|
301
306
|
# get API info
|
302
|
-
@api_info = read('info')
|
307
|
+
@api_info = read('info').freeze
|
303
308
|
Log.log.debug{Log.dump(:api_info, @api_info)}
|
304
309
|
# web socket endpoint: by default use v2 (newer gateways), without base64 encoding
|
305
310
|
# is the latest supported? else revert to old api
|