aspera-cli 4.26.2 → 4.27.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 +310 -21
- data/CONTRIBUTING.md +99 -14
- data/TODO.md +50 -0
- data/bin/ascli +3 -3
- data/docs/README.md +10977 -0
- data/docs/test-mcp-with-ai.md +202 -0
- data/lib/aspera/agent/base.rb +29 -7
- data/lib/aspera/agent/connect.rb +58 -21
- data/lib/aspera/agent/desktop.rb +53 -18
- data/lib/aspera/agent/direct.rb +71 -40
- data/lib/aspera/agent/factory.rb +3 -3
- data/lib/aspera/agent/httpgw.rb +55 -14
- data/lib/aspera/agent/node.rb +34 -2
- data/lib/aspera/agent/transferd.rb +48 -12
- data/lib/aspera/api/alee.rb +1 -1
- data/lib/aspera/api/aoc.rb +42 -44
- data/lib/aspera/api/cos_node.rb +10 -9
- data/lib/aspera/api/faspex.rb +16 -15
- data/lib/aspera/api/httpgw.rb +23 -23
- data/lib/aspera/api/node.rb +51 -70
- data/lib/aspera/api/queries/bss_subscription_account.graphql +18 -0
- data/lib/aspera/api/queries/bss_subscription_usage.graphql +18 -0
- data/lib/aspera/ascmd.rb +32 -30
- data/lib/aspera/ascp/installation.rb +75 -69
- data/lib/aspera/ascp/management.rb +7 -8
- data/lib/aspera/assert.rb +12 -13
- data/lib/aspera/cli/ascp_actions.rb +155 -0
- data/lib/aspera/cli/async_transfer_store.rb +125 -0
- data/lib/aspera/cli/bootstrapper.rb +197 -0
- data/lib/aspera/cli/command_registry.rb +145 -0
- data/lib/aspera/cli/command_spec.rb +141 -0
- data/lib/aspera/cli/context.rb +19 -6
- data/lib/aspera/cli/error.rb +16 -0
- data/lib/aspera/cli/extended_value.rb +27 -26
- data/lib/aspera/cli/formatter.rb +95 -59
- data/lib/aspera/cli/gem_checker.rb +65 -0
- data/lib/aspera/cli/hints.rb +3 -3
- data/lib/aspera/cli/http.rb +74 -30
- data/lib/aspera/cli/info.rb +2 -0
- data/lib/aspera/cli/mailer.rb +97 -0
- data/lib/aspera/cli/mcp_tool.rb +225 -0
- data/lib/aspera/cli/option_declarator.rb +77 -0
- data/lib/aspera/cli/options.schema.yaml +634 -7
- data/lib/aspera/cli/parser.rb +1217 -0
- data/lib/aspera/cli/plugins/alee.rb +20 -22
- data/lib/aspera/cli/plugins/aoc.rb +1178 -881
- data/lib/aspera/cli/plugins/ats.rb +205 -162
- data/lib/aspera/cli/plugins/base.rb +703 -175
- data/lib/aspera/cli/plugins/basic_auth.rb +7 -9
- data/lib/aspera/cli/plugins/config.rb +434 -757
- data/lib/aspera/cli/plugins/console.rb +107 -65
- data/lib/aspera/cli/plugins/cos.rb +46 -33
- data/lib/aspera/cli/plugins/factory.rb +6 -6
- data/lib/aspera/cli/plugins/faspex5.rb +627 -388
- data/lib/aspera/cli/plugins/faspio.rb +54 -51
- data/lib/aspera/cli/plugins/httpgw.rb +18 -25
- data/lib/aspera/cli/plugins/mcp.rb +279 -0
- data/lib/aspera/cli/plugins/node.rb +988 -840
- data/lib/aspera/cli/plugins/oauth.rb +7 -10
- data/lib/aspera/cli/plugins/orchestrator.rb +112 -135
- data/lib/aspera/cli/plugins/preview.rb +195 -157
- data/lib/aspera/cli/plugins/server.rb +141 -91
- data/lib/aspera/cli/plugins/shares.rb +343 -110
- data/lib/aspera/cli/preset_actions.rb +159 -0
- data/lib/aspera/cli/preset_manager.rb +82 -39
- data/lib/aspera/cli/result.rb +78 -26
- data/lib/aspera/cli/runner.rb +323 -153
- data/lib/aspera/cli/secret_finder.rb +40 -0
- data/lib/aspera/cli/special_values.rb +1 -0
- data/lib/aspera/cli/sync_actions.rb +89 -64
- data/lib/aspera/cli/terminal_formatter.rb +3 -3
- data/lib/aspera/cli/transfer_actions.rb +90 -0
- data/lib/aspera/cli/transfer_agent.rb +129 -64
- data/lib/aspera/cli/transfer_progress.rb +9 -9
- data/lib/aspera/cli/vault_manager.rb +79 -0
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +28 -30
- data/lib/aspera/colors.rb +3 -3
- data/lib/aspera/command_line_builder.rb +34 -34
- data/lib/aspera/command_line_converter.rb +1 -1
- data/lib/aspera/coverage.rb +1 -2
- data/lib/aspera/data_repository.rb +2 -1
- data/lib/aspera/dot_container.rb +12 -12
- data/lib/aspera/environment.rb +30 -23
- data/lib/aspera/exec_spec.rb +13 -0
- data/lib/aspera/faspex_gw.rb +5 -5
- data/lib/aspera/faspex_postproc.rb +16 -10
- data/lib/aspera/graphql.rb +37 -0
- data/lib/aspera/hash_ext.rb +8 -2
- data/lib/aspera/json_rpc/client.rb +62 -0
- data/lib/aspera/json_rpc/version.rb +7 -0
- data/lib/aspera/keychain/base.rb +10 -3
- data/lib/aspera/keychain/encrypted_hash.rb +92 -17
- data/lib/aspera/keychain/factory.rb +20 -8
- data/lib/aspera/keychain/hashicorp_vault.rb +1 -1
- data/lib/aspera/keychain/macos_security.rb +23 -25
- data/lib/aspera/keychain/one_password_api.rb +86 -0
- data/lib/aspera/keychain/one_password_base.rb +34 -0
- data/lib/aspera/keychain/one_password_cli.rb +98 -0
- data/lib/aspera/link_header.rb +82 -0
- data/lib/aspera/log.rb +29 -15
- data/lib/aspera/markdown.rb +90 -7
- data/lib/aspera/nagios.rb +8 -8
- data/lib/aspera/node_simulator.rb +35 -27
- data/lib/aspera/oauth/base.rb +9 -10
- data/lib/aspera/oauth/boot.rb +5 -5
- data/lib/aspera/oauth/factory.rb +12 -10
- data/lib/aspera/oauth/jwt.rb +9 -11
- data/lib/aspera/oauth/web.rb +6 -6
- data/lib/aspera/persistency_action_once.rb +12 -12
- data/lib/aspera/persistency_folder.rb +18 -11
- data/lib/aspera/preview/file_types.rb +5 -5
- data/lib/aspera/preview/generator.rb +52 -49
- data/lib/aspera/preview/options.rb +3 -2
- data/lib/aspera/preview/terminal.rb +5 -5
- data/lib/aspera/preview/utils.rb +66 -19
- data/lib/aspera/products/connect.rb +2 -2
- data/lib/aspera/products/desktop.rb +1 -1
- data/lib/aspera/products/other.rb +3 -3
- data/lib/aspera/products/transferd.rb +4 -4
- data/lib/aspera/proxy_auto_config.rb +15 -14
- data/lib/aspera/rest.rb +159 -151
- data/lib/aspera/rest_error_analyzer.rb +6 -6
- data/lib/aspera/rest_errors_aspera.rb +0 -10
- data/lib/aspera/rest_list.rb +11 -10
- data/lib/aspera/schema/IBM Aspera Node API-4.4.6.yaml +6232 -0
- data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0.yaml +249 -0
- data/lib/aspera/schema/IBM Aspera on Cloud API-0.2.6-enhanced.yaml +1853 -510
- data/lib/aspera/schema/IBM_Aspera_Shares.yaml +4653 -0
- data/lib/aspera/schema/documentation.rb +65 -28
- data/lib/aspera/schema/reader.rb +136 -13
- data/lib/aspera/schema/registry.rb +60 -8
- data/lib/aspera/secret_hider.rb +12 -7
- data/lib/aspera/ssh.rb +64 -31
- data/lib/aspera/ssl.rb +5 -5
- data/lib/aspera/sync/conf.schema.yaml +2 -2
- data/lib/aspera/sync/database.rb +2 -2
- data/lib/aspera/sync/operations.rb +22 -25
- data/lib/aspera/temp_file_manager.rb +25 -5
- data/lib/aspera/timer_limiter.rb +1 -1
- data/lib/aspera/transfer/faux_file.rb +24 -11
- data/lib/aspera/transfer/parameters.rb +36 -34
- data/lib/aspera/transfer/result.rb +74 -0
- data/lib/aspera/transfer/resumer.rb +10 -10
- data/lib/aspera/transfer/spec.rb +18 -1
- data/lib/aspera/transfer/spec.schema.yaml +12 -3
- data/lib/aspera/uri_reader.rb +52 -15
- data/lib/aspera/web_auth.rb +8 -7
- data/lib/aspera/web_server_simple.rb +15 -12
- data/lib/aspera/yaml.rb +5 -4
- data.tar.gz.sig +0 -0
- metadata +34 -6
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/manager.rb +0 -766
- data/lib/aspera/cli/plugins/faspex.rb +0 -539
- data/lib/aspera/json_rpc.rb +0 -52
- data/lib/aspera/transfer/uri.rb +0 -56
data/lib/aspera/api/aoc.rb
CHANGED
|
@@ -25,23 +25,23 @@ module Aspera
|
|
|
25
25
|
|
|
26
26
|
class AppInfo
|
|
27
27
|
# @return [Aspera::Api::AoC] Rest Api object
|
|
28
|
-
attr_reader
|
|
28
|
+
attr_reader :api
|
|
29
29
|
# @return [Hash, nil] Package information, `"files"` or `"packages"`
|
|
30
|
-
attr_reader
|
|
30
|
+
attr_reader :package
|
|
31
31
|
# @return [Hash] Result of GET /nodes/:id
|
|
32
|
-
attr_reader
|
|
32
|
+
attr_reader :node_info
|
|
33
33
|
# @return [String] Workspace id
|
|
34
|
-
attr_reader
|
|
34
|
+
attr_reader :workspace_id
|
|
35
35
|
# @return [String] Workspace name
|
|
36
|
-
attr_reader
|
|
36
|
+
attr_reader :workspace_name
|
|
37
37
|
# @return [String, nil] "Share as" link name
|
|
38
38
|
attr_accessor :opt_link_name
|
|
39
39
|
|
|
40
40
|
# @param api [Api::Aoc] Rest Api object
|
|
41
41
|
# @param package [Hash,nil] package information or nil
|
|
42
42
|
# @param node_info [Hash] Result of GET /nodes/:id
|
|
43
|
-
# @param workspace_id
|
|
44
|
-
# @param workspace_name [String]
|
|
43
|
+
# @param workspace_id [String] Workspace identifier
|
|
44
|
+
# @param workspace_name [String] Workspace name
|
|
45
45
|
def initialize(api, package, node_info, workspace_id, workspace_name)
|
|
46
46
|
@api = api
|
|
47
47
|
@package = package
|
|
@@ -65,11 +65,11 @@ module Aspera
|
|
|
65
65
|
MAX_AOC_URL_REDIRECT = 10
|
|
66
66
|
CLIENT_ID_PREFIX = 'aspera.'
|
|
67
67
|
# Well-known AoC global client apps
|
|
68
|
-
GLOBAL_CLIENT_APPS = DataRepository::ELEMENTS.select{ |i| i.to_s.start_with?(CLIENT_ID_PREFIX)}.freeze
|
|
68
|
+
GLOBAL_CLIENT_APPS = DataRepository::ELEMENTS.select { |i| i.to_s.start_with?(CLIENT_ID_PREFIX) }.freeze
|
|
69
69
|
# cookie prefix so that console can decode identity
|
|
70
70
|
COOKIE_PREFIX_CONSOLE_AOC = 'aspera.aoc'
|
|
71
|
-
# path in URL of public links
|
|
72
|
-
PUBLIC_LINK_PATHS = %w[/packages/public/receive /packages/public/send /files/public /public/files /public/package /public/send].freeze
|
|
71
|
+
# path in URL of public links (warning if not in list)
|
|
72
|
+
PUBLIC_LINK_PATHS = %w[/packages/public/receive /packages/public/send /files/public /public/files /public/files/ /public/package /public/send /public/send/package].freeze
|
|
73
73
|
JWT_AUDIENCE = 'https://api.asperafiles.com/api/v1/oauth2/token'
|
|
74
74
|
OAUTH_API_SUBPATH = 'api/v1/oauth2'
|
|
75
75
|
# minimum fields for user info if retrieval fails
|
|
@@ -123,9 +123,9 @@ module Aspera
|
|
|
123
123
|
# split host of URL into organization and domain
|
|
124
124
|
def split_org_domain(uri)
|
|
125
125
|
Aspera.assert_type(uri, URI)
|
|
126
|
-
Aspera.assert(!uri.host.nil?){"No host found in URL. Please check URL format: https://myorg.#{SAAS_DOMAIN_PROD}"}
|
|
126
|
+
Aspera.assert(!uri.host.nil?) { "No host found in URL. Please check URL format: https://myorg.#{SAAS_DOMAIN_PROD}" }
|
|
127
127
|
parts = uri.host.split('.', 2)
|
|
128
|
-
Aspera.assert(parts.length == 2){"expecting a public FQDN for #{PRODUCT_NAME}"}
|
|
128
|
+
Aspera.assert(parts.length == 2) { "expecting a public FQDN for #{PRODUCT_NAME}" }
|
|
129
129
|
parts[0] = nil if parts[0].eql?('api')
|
|
130
130
|
return %i{organization domain}.zip(parts).to_h
|
|
131
131
|
end
|
|
@@ -146,14 +146,14 @@ module Aspera
|
|
|
146
146
|
if (m = final_uri.path.match(%r{/oauth2/([^/]+)/login$}))
|
|
147
147
|
org_domain[:organization] = m[1] if org_domain[:organization].nil?
|
|
148
148
|
else
|
|
149
|
-
Log.log.debug{"path=#{final_uri.path} does not end with /login"}
|
|
149
|
+
Log.log.debug { "path=#{final_uri.path} does not end with /login" }
|
|
150
150
|
end
|
|
151
151
|
Aspera.assert(!final_uri.query.nil?, 'AoC shall redirect to login page with a query', type: Error)
|
|
152
152
|
query = Rest.query_to_h(final_uri.query)
|
|
153
153
|
Log.dump(:query, query, level: :trace1)
|
|
154
154
|
# is that a public link ?
|
|
155
155
|
if query.key?('token')
|
|
156
|
-
Log.log.warn{"Unknown pub link path: #{final_uri.path}"} unless PUBLIC_LINK_PATHS.include?(final_uri.path)
|
|
156
|
+
Log.log.warn { "Unknown pub link path: #{final_uri.path}" } unless PUBLIC_LINK_PATHS.include?(final_uri.path)
|
|
157
157
|
# ok we get it !
|
|
158
158
|
return {
|
|
159
159
|
instance_domain: org_domain[:domain],
|
|
@@ -198,7 +198,7 @@ module Aspera
|
|
|
198
198
|
# @option return [Array<Hash>] :items The list of items
|
|
199
199
|
# @option return [Integer] :total The total number of items
|
|
200
200
|
def call_paging(query: {})
|
|
201
|
-
Aspera.assert_type(query, Hash){'query'}
|
|
201
|
+
Aspera.assert_type(query, Hash) { 'query' }
|
|
202
202
|
Aspera.assert(block_given?, 'block required for call_paging')
|
|
203
203
|
# set default large page if user does not specify own parameters. AoC Caps to 1000 anyway
|
|
204
204
|
query['per_page'] = 1000 unless query.key?('per_page')
|
|
@@ -257,10 +257,10 @@ module Aspera
|
|
|
257
257
|
when 'download' then %w[list preview read]
|
|
258
258
|
when 'upload' then %w[mkdir write]
|
|
259
259
|
when Array
|
|
260
|
-
Aspera.assert_array_all(levels, String){'access_levels'}
|
|
261
|
-
levels.each{ |level| Aspera.assert_values(level, Node::ACCESS_LEVELS){'access_level'}}
|
|
260
|
+
Aspera.assert_array_all(levels, String) { 'access_levels' }
|
|
261
|
+
levels.each { |level| Aspera.assert_values(level, Node::ACCESS_LEVELS) { 'access_level' } }
|
|
262
262
|
levels
|
|
263
|
-
else Aspera.error_unexpected_value(levels){"access_levels must be a list of #{Node::ACCESS_LEVELS.join(', ')} or one of edit, preview, download, upload"}
|
|
263
|
+
else Aspera.error_unexpected_value(levels) { "access_levels must be a list of #{Node::ACCESS_LEVELS.join(', ')} or one of edit, preview, download, upload" }
|
|
264
264
|
end
|
|
265
265
|
end
|
|
266
266
|
end
|
|
@@ -269,7 +269,6 @@ module Aspera
|
|
|
269
269
|
attr_accessor :ws_ids
|
|
270
270
|
|
|
271
271
|
# By default: no workspace
|
|
272
|
-
# @param
|
|
273
272
|
def initialize(
|
|
274
273
|
scope: nil,
|
|
275
274
|
subpath: API_V1,
|
|
@@ -298,8 +297,7 @@ module Aspera
|
|
|
298
297
|
# default values for client id
|
|
299
298
|
client_id, client_secret = self.class.get_client_info if client_id.nil?
|
|
300
299
|
# access key secrets are provided out of band to get node api access
|
|
301
|
-
#
|
|
302
|
-
# value: associated secret
|
|
300
|
+
# maps access key (String) to its associated secret (String)
|
|
303
301
|
@secret_finder = secret_finder
|
|
304
302
|
@cache_user_info = nil
|
|
305
303
|
@cache_url_token_info = nil
|
|
@@ -354,7 +352,7 @@ module Aspera
|
|
|
354
352
|
when :none
|
|
355
353
|
auth_params.clear
|
|
356
354
|
auth_params[:type] = :none
|
|
357
|
-
else Aspera.error_unexpected_value(auth_params[:grant_method]){'auth, use one of: web, jwt, boot'}
|
|
355
|
+
else Aspera.error_unexpected_value(auth_params[:grant_method]) { 'auth, use one of: web, jwt, boot' }
|
|
358
356
|
end
|
|
359
357
|
super(**base_args)
|
|
360
358
|
end
|
|
@@ -371,7 +369,7 @@ module Aspera
|
|
|
371
369
|
|
|
372
370
|
# @param expected [Array<String>] Link types
|
|
373
371
|
def assert_public_link_types(expected)
|
|
374
|
-
Aspera.assert_values(public_link['purpose'], expected){'public link type'}
|
|
372
|
+
Aspera.assert_values(public_link['purpose'], expected) { 'public link type' }
|
|
375
373
|
end
|
|
376
374
|
|
|
377
375
|
def additional_persistence_ids
|
|
@@ -398,10 +396,10 @@ module Aspera
|
|
|
398
396
|
read('self')
|
|
399
397
|
rescue Aspera::RestCallError => e
|
|
400
398
|
raise if exception || e.message.include?('invalid_grant')
|
|
401
|
-
Log.log.debug{"Ignoring error: (#{e.class}) #{e}"}
|
|
399
|
+
Log.log.debug { "Ignoring error: (#{e.class}) #{e}" }
|
|
402
400
|
{}
|
|
403
401
|
end
|
|
404
|
-
USER_INFO_FIELDS_MIN.each{ |f| @cache_user_info[f] = nil if @cache_user_info[f].nil?}
|
|
402
|
+
USER_INFO_FIELDS_MIN.each { |f| @cache_user_info[f] = nil if @cache_user_info[f].nil? }
|
|
405
403
|
return @cache_user_info
|
|
406
404
|
end
|
|
407
405
|
|
|
@@ -480,17 +478,17 @@ module Aspera
|
|
|
480
478
|
# @param workspace_name [String,nil] workspace name
|
|
481
479
|
# @param scope [String,nil] e.g. Node::Scope::USER, or Node::Scope::ADMIN, or nil (requires secret)
|
|
482
480
|
# @param package_info [Hash,nil] created package information
|
|
483
|
-
# @
|
|
481
|
+
# @return [Node] a node API for access key
|
|
484
482
|
def node_api_from(node_id:, workspace_id: nil, workspace_name: nil, scope: Node::Scope::USER, package_info: nil)
|
|
485
483
|
Aspera.assert_type(node_id, String)
|
|
486
484
|
node_info = read("nodes/#{node_id}")
|
|
487
485
|
workspace_name = read("workspaces/#{workspace_id}")['name'] if workspace_name.nil? && !workspace_id.nil?
|
|
488
486
|
app_info = AppInfo.new(self, package_info, node_info, workspace_id, workspace_name)
|
|
489
487
|
node_params = {base_url: node_info['url']}
|
|
490
|
-
ak_secret = @secret_finder&.
|
|
488
|
+
ak_secret = @secret_finder&.lookup(url: node_info['url'], username: node_info['access_key'])
|
|
491
489
|
# If secret is available, or no scope, use basic auth
|
|
492
490
|
if scope.nil? || ak_secret
|
|
493
|
-
Aspera.assert(ak_secret, type: Error){"Secret not found for access key #{node_info['access_key']}@#{node_info['url']}"}
|
|
491
|
+
Aspera.assert(ak_secret, type: Error) { "Secret not found for access key #{node_info['access_key']}@#{node_info['url']}" }
|
|
494
492
|
node_params[:auth] = {
|
|
495
493
|
type: :basic,
|
|
496
494
|
username: node_info['access_key'],
|
|
@@ -521,21 +519,21 @@ module Aspera
|
|
|
521
519
|
Log.log.debug('no metadata in shared inbox')
|
|
522
520
|
return
|
|
523
521
|
end
|
|
524
|
-
Aspera.assert(pkg_data.key?('metadata')){"package requires metadata: #{meta_schema}"}
|
|
522
|
+
Aspera.assert(pkg_data.key?('metadata')) { "package requires metadata: #{meta_schema}" }
|
|
525
523
|
pkg_meta = pkg_data['metadata']
|
|
526
|
-
Aspera.assert_type(pkg_meta, Array){'metadata'}
|
|
524
|
+
Aspera.assert_type(pkg_meta, Array) { 'metadata' }
|
|
527
525
|
Log.dump(:metadata, pkg_meta)
|
|
528
526
|
pkg_meta.each do |field|
|
|
529
|
-
Aspera.assert_type(field, Hash){'metadata field'}
|
|
527
|
+
Aspera.assert_type(field, Hash) { 'metadata field' }
|
|
530
528
|
Aspera.assert(field.key?('name'), 'metadata field must have name')
|
|
531
529
|
Aspera.assert(field.key?('values'), 'metadata field must have values')
|
|
532
|
-
Aspera.assert_type(field['values'], Array){'metadata field values'}
|
|
533
|
-
Aspera.assert(meta_schema.any?{ |i| i['name'].eql?(field['name'])}){"unknown metadata field: #{field['name']}"}
|
|
530
|
+
Aspera.assert_type(field['values'], Array) { 'metadata field values' }
|
|
531
|
+
Aspera.assert(meta_schema.any? { |i| i['name'].eql?(field['name']) }) { "unknown metadata field: #{field['name']}" }
|
|
534
532
|
end
|
|
535
533
|
meta_schema.each do |field|
|
|
536
|
-
provided = pkg_meta.select{ |i| i['name'].eql?(field['name'])}
|
|
537
|
-
Aspera.assert(provided.count <= 1, type: Error){"only one field with name #{field['name']} allowed"}
|
|
538
|
-
Aspera.assert(!provided.empty?, type: Error){"missing mandatory field: #{field['name']}"} if field['required']
|
|
534
|
+
provided = pkg_meta.select { |i| i['name'].eql?(field['name']) }
|
|
535
|
+
Aspera.assert(provided.count <= 1, type: Error) { "only one field with name #{field['name']} allowed" }
|
|
536
|
+
Aspera.assert(!provided.empty?, type: Error) { "missing mandatory field: #{field['name']}" } if field['required']
|
|
539
537
|
end
|
|
540
538
|
end
|
|
541
539
|
|
|
@@ -545,19 +543,19 @@ module Aspera
|
|
|
545
543
|
# @param package_data [Hash] The whole package creation payload
|
|
546
544
|
# @param rcpt_lst_field [String] The field in structure, i.e. recipients or bcc_recipients
|
|
547
545
|
# @param new_user_option [Hash] Additional fields for contact creation
|
|
548
|
-
# @return nil
|
|
546
|
+
# @return [nil] `package_data` is modified in place
|
|
549
547
|
def resolve_package_recipients(package_data, rcpt_lst_field, new_user_option)
|
|
550
548
|
return unless package_data.key?(rcpt_lst_field)
|
|
551
|
-
Aspera.assert_type(package_data[rcpt_lst_field], Array){rcpt_lst_field}
|
|
549
|
+
Aspera.assert_type(package_data[rcpt_lst_field], Array) { rcpt_lst_field }
|
|
552
550
|
new_user_option = {'package_contact' => true} if new_user_option.nil?
|
|
553
|
-
Aspera.assert_type(new_user_option, Hash){'new_user_option'}
|
|
551
|
+
Aspera.assert_type(new_user_option, Hash) { 'new_user_option' }
|
|
554
552
|
ws_id = package_data['workspace_id']
|
|
555
553
|
# list with resolved elements
|
|
556
554
|
resolved_list = []
|
|
557
555
|
package_data[rcpt_lst_field].each do |short_recipient_info|
|
|
558
556
|
case short_recipient_info
|
|
559
557
|
when Hash # native API information, check keys
|
|
560
|
-
Aspera.assert(short_recipient_info.keys.sort.eql?(%w[id type])){"#{rcpt_lst_field} element shall have fields: id and type"}
|
|
558
|
+
Aspera.assert(short_recipient_info.keys.sort.eql?(%w[id type])) { "#{rcpt_lst_field} element shall have fields: id and type" }
|
|
561
559
|
when String # CLI helper: need to resolve provided name to type/id
|
|
562
560
|
# email: user, else dropbox
|
|
563
561
|
entity_type = short_recipient_info.include?('@') ? 'contacts' : 'dropboxes'
|
|
@@ -565,7 +563,7 @@ module Aspera
|
|
|
565
563
|
full_recipient_info = lookup_with_q(entity_type, value: short_recipient_info, query: {'workspace_id' => ws_id})
|
|
566
564
|
rescue EntityNotFound
|
|
567
565
|
# dropboxes cannot be created on the fly
|
|
568
|
-
Aspera.assert_values(entity_type, %w[contacts], type: Error){"No such shared inbox in workspace #{ws_id}"}
|
|
566
|
+
Aspera.assert_values(entity_type, %w[contacts], type: Error) { "No such shared inbox in workspace #{ws_id}" }
|
|
569
567
|
# unknown user: create it as external user
|
|
570
568
|
full_recipient_info = create('contacts', {
|
|
571
569
|
'current_workspace_id' => ws_id,
|
|
@@ -577,7 +575,7 @@ module Aspera
|
|
|
577
575
|
else
|
|
578
576
|
{'id' => full_recipient_info['source_id'], 'type' => full_recipient_info['source_type']}
|
|
579
577
|
end
|
|
580
|
-
else Aspera.error_unexpected_value(short_recipient_info.class.name){"#{rcpt_lst_field} item must be a String (email, shared inbox) or Hash (id,type)"}
|
|
578
|
+
else Aspera.error_unexpected_value(short_recipient_info.class.name) { "#{rcpt_lst_field} item must be a String (email, shared inbox) or Hash (id,type)" }
|
|
581
579
|
end
|
|
582
580
|
# add original or resolved recipient info
|
|
583
581
|
resolved_list.push(short_recipient_info)
|
|
@@ -609,7 +607,7 @@ module Aspera
|
|
|
609
607
|
# @param package_data [Hash] package creation (with extensions...)
|
|
610
608
|
# @param validate_meta [TrueClass,FalseClass] true to validate parameters locally
|
|
611
609
|
# @param new_user_option [Hash,NilClass] options if an unknown user is specified
|
|
612
|
-
# @return transfer spec, node api and package information
|
|
610
|
+
# @return [Array] transfer spec, node api and package information
|
|
613
611
|
def create_package_simple(package_data, validate_meta, new_user_option)
|
|
614
612
|
update_package_metadata_for_api(package_data)
|
|
615
613
|
# list of files to include in package, optional
|
|
@@ -671,7 +669,7 @@ module Aspera
|
|
|
671
669
|
# Console cookie
|
|
672
670
|
################
|
|
673
671
|
# we are sure that fields are not nil
|
|
674
|
-
cookie_elements = [app_info.app, current_user_info['name'] || 'public link', current_user_info['email'] || 'none'].map{ |e| Base64.strict_encode64(e)}
|
|
672
|
+
cookie_elements = [app_info.app, current_user_info['name'] || 'public link', current_user_info['email'] || 'none'].map { |e| Base64.strict_encode64(e) }
|
|
675
673
|
cookie_elements.unshift(COOKIE_PREFIX_CONSOLE_AOC)
|
|
676
674
|
transfer_spec['cookie'] = cookie_elements.join(':')
|
|
677
675
|
# Application tags
|
data/lib/aspera/api/cos_node.rb
CHANGED
|
@@ -12,19 +12,20 @@ module Aspera
|
|
|
12
12
|
IBM_CLOUD_TOKEN_URL = 'https://iam.cloud.ibm.com/identity'
|
|
13
13
|
TOKEN_FIELD = 'delegated_refresh_token'
|
|
14
14
|
FASP_INFO_KEYS = %w[ATSEndpoint AccessKey].freeze
|
|
15
|
+
SERVICE_CREDS_PARAMS = %w[apikey resource_instance_id endpoints]
|
|
15
16
|
class << self
|
|
16
17
|
def parameters_from_svc_credentials(service_credentials, bucket_region)
|
|
17
18
|
# check necessary contents
|
|
18
|
-
Aspera.assert_type(service_credentials, Hash){'service_credentials'}
|
|
19
|
+
Aspera.assert_type(service_credentials, Hash) { 'service_credentials' }
|
|
19
20
|
Log.dump(:service_credentials, service_credentials)
|
|
20
|
-
|
|
21
|
-
Aspera.assert(service_credentials.key?(field)){"service_credentials must have a field: #{field}"}
|
|
21
|
+
SERVICE_CREDS_PARAMS.each do |field|
|
|
22
|
+
Aspera.assert(service_credentials.key?(field)) { "service_credentials must have a field: #{field}" }
|
|
22
23
|
end
|
|
23
24
|
# read endpoints from service provided in service credentials
|
|
24
25
|
endpoints = Aspera::Rest.new(base_url: service_credentials['endpoints']).read('')
|
|
25
26
|
Log.dump(:endpoints, endpoints)
|
|
26
27
|
endpoint = endpoints.dig('service-endpoints', 'regional', bucket_region, 'public', bucket_region)
|
|
27
|
-
|
|
28
|
+
Aspera.assert(!endpoint.nil?) { "no such region: #{bucket_region}" }
|
|
28
29
|
return {
|
|
29
30
|
instance_id: service_credentials['resource_instance_id'],
|
|
30
31
|
api_key: service_credentials['apikey'],
|
|
@@ -34,8 +35,8 @@ module Aspera
|
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
def initialize(instance_id:, api_key:, endpoint:, bucket:, auth_url: IBM_CLOUD_TOKEN_URL)
|
|
37
|
-
Aspera.assert_type(instance_id, String){'resource instance id (crn)'}
|
|
38
|
-
Aspera.assert_type(endpoint, String){'endpoint'}
|
|
38
|
+
Aspera.assert_type(instance_id, String) { 'resource instance id (crn)' }
|
|
39
|
+
Aspera.assert_type(endpoint, String) { 'endpoint' }
|
|
39
40
|
endpoint = "https://#{endpoint}" unless endpoint.start_with?('http')
|
|
40
41
|
@auth_url = auth_url
|
|
41
42
|
@api_key = api_key
|
|
@@ -61,10 +62,10 @@ module Aspera
|
|
|
61
62
|
ret: :resp
|
|
62
63
|
).body
|
|
63
64
|
ats_info = XmlSimple.xml_in(xml_result_text, {'ForceArray' => false})
|
|
64
|
-
Log.dump(:ats_info, ats_info)
|
|
65
|
-
Aspera.assert_hash_all(ats_info, String, nil){'ats_info'}
|
|
65
|
+
Log.dump(:ats_info, ats_info.reject { |k, _| k == 'AccessKey' })
|
|
66
|
+
Aspera.assert_hash_all(ats_info, String, nil) { 'ats_info' }
|
|
66
67
|
Aspera.assert((FASP_INFO_KEYS - ats_info.keys).empty?, 'ats_info missing required keys')
|
|
67
|
-
Aspera.assert_hash_all(ats_info['AccessKey'], String, String){'ats_info'}
|
|
68
|
+
Aspera.assert_hash_all(ats_info['AccessKey'], String, String) { 'ats_info' }
|
|
68
69
|
@storage_credentials = {
|
|
69
70
|
'type' => 'token',
|
|
70
71
|
'token' => {TOKEN_FIELD => nil}
|
data/lib/aspera/api/faspex.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'aspera/assert'
|
|
3
4
|
require 'aspera/rest'
|
|
4
5
|
require 'aspera/oauth/base'
|
|
5
6
|
require 'aspera/rest_list'
|
|
@@ -11,9 +12,9 @@ module Aspera
|
|
|
11
12
|
class << self
|
|
12
13
|
attr_accessor :additional_info
|
|
13
14
|
end
|
|
14
|
-
# @param context
|
|
15
|
-
# @param redirect_uri
|
|
16
|
-
# @param path_authorize
|
|
15
|
+
# @param context [String] The `context` query parameter in public link
|
|
16
|
+
# @param redirect_uri [String] URI of web UI login
|
|
17
|
+
# @param path_authorize [String] Path to provide passcode
|
|
17
18
|
def initialize(
|
|
18
19
|
context:,
|
|
19
20
|
redirect_uri:,
|
|
@@ -125,7 +126,7 @@ module Aspera
|
|
|
125
126
|
mfa_code
|
|
126
127
|
]
|
|
127
128
|
class << self
|
|
128
|
-
# @return true if the URL is a public link
|
|
129
|
+
# @return [Boolean] true if the URL is a public link
|
|
129
130
|
def public_link?(url)
|
|
130
131
|
url.include?('?context=')
|
|
131
132
|
end
|
|
@@ -138,15 +139,15 @@ module Aspera
|
|
|
138
139
|
end
|
|
139
140
|
attr_reader :pub_link_context
|
|
140
141
|
|
|
141
|
-
# @param url
|
|
142
|
-
# @param auth
|
|
143
|
-
# @param password
|
|
144
|
-
# @param client_id
|
|
145
|
-
# @param client_secret
|
|
146
|
-
# @param redirect_uri
|
|
147
|
-
# @param username
|
|
148
|
-
# @param private_key
|
|
149
|
-
# @param passphrase
|
|
142
|
+
# @param url [String] Faspex URL, can be a public link
|
|
143
|
+
# @param auth [Symbol] Authentication method: :boot (token in header), :web (open browser), :jwt (client_id + private key), :public_link (context in URL)
|
|
144
|
+
# @param password [String, nil] For :boot auth, the token copied directly from browser in developer mode
|
|
145
|
+
# @param client_id [String, nil] For :web and :jwt auth, the client_id of web UI application
|
|
146
|
+
# @param client_secret [String, nil] For :web auth, the client_secret of web UI application (not needed for :jwt)
|
|
147
|
+
# @param redirect_uri [String, nil] For :web auth, the redirect_uri of web UI application (must be the same as in application configuration)
|
|
148
|
+
# @param username [String, nil] For :jwt auth, the username of the user to impersonate
|
|
149
|
+
# @param private_key [String, nil] For :jwt auth, the private key to sign JWT token
|
|
150
|
+
# @param passphrase [String, nil] For :jwt auth, the passphrase of the private key
|
|
150
151
|
def initialize(
|
|
151
152
|
url:,
|
|
152
153
|
auth:,
|
|
@@ -169,7 +170,7 @@ module Aspera
|
|
|
169
170
|
Log.dump(:final_url, final_url, level: :trace1)
|
|
170
171
|
# Get context from query
|
|
171
172
|
encoded_context = Rest.query_to_h(URI.parse(final_url).query)['context']
|
|
172
|
-
|
|
173
|
+
Aspera.assert(!encoded_context.nil?, type: ParameterError) { 'Bad faspex5 public link, missing context in query' }
|
|
173
174
|
# public link information (contains passcode and allowed usage)
|
|
174
175
|
@pub_link_context = JSON.parse(Base64.decode64(encoded_context))
|
|
175
176
|
Log.dump(:pub_link_context, @pub_link_context, level: :trace1)
|
|
@@ -237,7 +238,7 @@ module Aspera
|
|
|
237
238
|
headers: {typ: 'JWT'}
|
|
238
239
|
}
|
|
239
240
|
}
|
|
240
|
-
else Aspera.error_unexpected_value(auth, type: ParameterError){'auth'}
|
|
241
|
+
else Aspera.error_unexpected_value(auth, type: ParameterError) { 'auth' }
|
|
241
242
|
end
|
|
242
243
|
)
|
|
243
244
|
end
|
data/lib/aspera/api/httpgw.rb
CHANGED
|
@@ -60,7 +60,7 @@ module Aspera
|
|
|
60
60
|
|
|
61
61
|
# send data on http gw web socket
|
|
62
62
|
def ws_send(ws_type:, data:)
|
|
63
|
-
Log.log.trace1{"#{LOG_WS_SEND}sending: #{ws_type} (#{data&.length || 0} bytes)"}
|
|
63
|
+
Log.log.trace1 { "#{LOG_WS_SEND}sending: #{ws_type} (#{data&.length || 0} bytes)" }
|
|
64
64
|
@shared_info[:count][:sent_general] += 1 if ws_type.eql?(:binary)
|
|
65
65
|
frame_generator = ::WebSocket::Frame::Outgoing::Client.new(data: data, type: ws_type, version: @ws_handshake.version)
|
|
66
66
|
@ws_io.write(frame_generator.to_s)
|
|
@@ -72,16 +72,16 @@ module Aspera
|
|
|
72
72
|
@shared_info[:read_exception].nil? &&
|
|
73
73
|
(((@shared_info[:count][:sent_general] - @shared_info[:count][:received_general]) > 1) ||
|
|
74
74
|
((@shared_info[:count][:received_v2_delimiter] - @shared_info[:count][:sent_v2_delimiter]) > 1))
|
|
75
|
-
Log.log.trace1{"#{LOG_WS_SEND}#{'timeout'.blue}: #{@shared_info[:count]}"} if !@shared_info[:cond_var].wait(@shared_info[:mutex], 2.0)
|
|
75
|
+
Log.log.trace1 { "#{LOG_WS_SEND}#{'timeout'.blue}: #{@shared_info[:count]}" } if !@shared_info[:cond_var].wait(@shared_info[:mutex], 2.0)
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
raise @shared_info[:read_exception] unless @shared_info[:read_exception].nil?
|
|
80
|
-
Log.log.trace2{"#{LOG_WS_SEND}counts: #{@shared_info[:count]}"}
|
|
80
|
+
Log.log.trace2 { "#{LOG_WS_SEND}counts: #{@shared_info[:count]}" }
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
# Check header ourself and give precise error message, as websocket will only throw error without details
|
|
84
|
-
# @param [String] Response Header
|
|
84
|
+
# @param header [String] Response Header
|
|
85
85
|
# @return [String] Response Header
|
|
86
86
|
def validated_ws_response_header(header)
|
|
87
87
|
first_line = header.split("\r\n").first
|
|
@@ -91,7 +91,7 @@ module Aspera
|
|
|
91
91
|
|
|
92
92
|
# message processing for read thread
|
|
93
93
|
def process_received_message(message)
|
|
94
|
-
Log.log.debug{"#{LOG_WS_RECV}message: [#{message}] (#{message.class})"}
|
|
94
|
+
Log.log.debug { "#{LOG_WS_RECV}message: [#{message}] (#{message.class})" }
|
|
95
95
|
if message.eql?(MSG_RECV_DATA_RECEIVED_SIGNAL)
|
|
96
96
|
@shared_info[:mutex].synchronize do
|
|
97
97
|
@shared_info[:count][:received_general] += 1
|
|
@@ -119,21 +119,21 @@ module Aspera
|
|
|
119
119
|
|
|
120
120
|
# main function of read thread
|
|
121
121
|
def process_read_thread
|
|
122
|
-
Log.log.debug{"#{LOG_WS_RECV}read thread started"}
|
|
122
|
+
Log.log.debug { "#{LOG_WS_RECV}read thread started" }
|
|
123
123
|
frame_parser = ::WebSocket::Frame::Incoming::Client.new(version: @ws_handshake.version)
|
|
124
124
|
until @ws_io.eof?
|
|
125
125
|
begin
|
|
126
126
|
# ready byte by byte until frame is ready
|
|
127
127
|
# blocking read
|
|
128
128
|
byte = @ws_io.read(1)
|
|
129
|
-
Log.log.trace2{"#{LOG_WS_RECV}read: #{byte} (#{byte.class}) eof=#{@ws_io.eof?}"}
|
|
129
|
+
Log.log.trace2 { "#{LOG_WS_RECV}read: #{byte} (#{byte.class}) eof=#{@ws_io.eof?}" }
|
|
130
130
|
frame_parser << byte
|
|
131
131
|
frame_ok = frame_parser.next
|
|
132
132
|
next if frame_ok.nil?
|
|
133
133
|
process_received_message(frame_ok.data.to_s)
|
|
134
|
-
Log.log.trace2{"#{LOG_WS_RECV}counts: #{@shared_info[:count]}"}
|
|
134
|
+
Log.log.trace2 { "#{LOG_WS_RECV}counts: #{@shared_info[:count]}" }
|
|
135
135
|
rescue => e
|
|
136
|
-
Log.log.debug{"#{LOG_WS_RECV}Exception: #{e}"}
|
|
136
|
+
Log.log.debug { "#{LOG_WS_RECV}Exception: #{e}" }
|
|
137
137
|
@shared_info[:mutex].synchronize do
|
|
138
138
|
@shared_info[:read_exception] = e
|
|
139
139
|
@shared_info[:cond_var].signal
|
|
@@ -144,7 +144,7 @@ module Aspera
|
|
|
144
144
|
Log.log.debug do
|
|
145
145
|
"#{LOG_WS_RECV}exception: #{@shared_info[:read_exception]},cls=#{@shared_info[:read_exception].class})"
|
|
146
146
|
end unless @shared_info[:read_exception].nil?
|
|
147
|
-
Log.log.debug{"#{LOG_WS_RECV}read thread stopped (ws eof=#{@ws_io.eof?})"}
|
|
147
|
+
Log.log.debug { "#{LOG_WS_RECV}read thread stopped (ws eof=#{@ws_io.eof?})" }
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
def upload(transfer_spec)
|
|
@@ -170,7 +170,7 @@ module Aspera
|
|
|
170
170
|
# Get whole HTTP response header, Check and process
|
|
171
171
|
# no need to check `finished?` or result of `<<` (true), as we give the whole header at once
|
|
172
172
|
@ws_handshake << validated_ws_response_header(@ws_io.readuntil("\r\n\r\n"))
|
|
173
|
-
Log.log.debug{"#{LOG_WS_SEND}handshake success"}
|
|
173
|
+
Log.log.debug { "#{LOG_WS_SEND}handshake success" }
|
|
174
174
|
# data shared between main thread and read thread
|
|
175
175
|
@shared_info = {
|
|
176
176
|
read_exception: nil, # error message if any in callback
|
|
@@ -184,7 +184,7 @@ module Aspera
|
|
|
184
184
|
cond_var: ConditionVariable.new
|
|
185
185
|
}
|
|
186
186
|
# start read thread after handshake
|
|
187
|
-
@ws_read_thread = Thread.new{process_read_thread}
|
|
187
|
+
@ws_read_thread = Thread.new { process_read_thread }
|
|
188
188
|
@notify_cb&.call(:session_start, session_id: session_id)
|
|
189
189
|
@notify_cb&.call(:session_size, session_id: session_id, info: total_bytes_to_transfer)
|
|
190
190
|
sleep(1)
|
|
@@ -210,7 +210,7 @@ module Aspera
|
|
|
210
210
|
fileIndex: file_index
|
|
211
211
|
}
|
|
212
212
|
file = file_to_send[:file]
|
|
213
|
-
file = File.open(file) unless file.is_a?(Transfer::FauxFile)
|
|
213
|
+
file = File.open(file) unless file.is_a?(Transfer::FauxFile) # rubocop:disable Style/FileOpen
|
|
214
214
|
begin
|
|
215
215
|
until file.eof?
|
|
216
216
|
slice_bin_data = file.read(@upload_chunk_size)
|
|
@@ -224,7 +224,7 @@ module Aspera
|
|
|
224
224
|
# send once, before data, at beginning
|
|
225
225
|
ws_snd_json(MSG_SEND_SLICE_UPLOAD, slice_info) if slice_info[:slice].eql?(0)
|
|
226
226
|
ws_send(ws_type: :binary, data: slice_bin_data)
|
|
227
|
-
Log.log.trace1{"#{LOG_WS_SEND}buffer: file: #{file_index}, slice: #{slice_info[:slice]}/#{last_slice}"}
|
|
227
|
+
Log.log.trace1 { "#{LOG_WS_SEND}buffer: file: #{file_index}, slice: #{slice_info[:slice]}/#{last_slice}" }
|
|
228
228
|
# send once, after data, at end
|
|
229
229
|
ws_snd_json(MSG_SEND_SLICE_UPLOAD, slice_info) if slice_info[:slice].eql?(last_slice)
|
|
230
230
|
end
|
|
@@ -232,7 +232,7 @@ module Aspera
|
|
|
232
232
|
raise @shared_info[:read_exception] unless @shared_info[:read_exception].nil?
|
|
233
233
|
raise e
|
|
234
234
|
rescue Net::ReadTimeout => e
|
|
235
|
-
Log.log.warn{'A timeout condition using HTTPGW may signal a permission problem on destination. Check ascp logs on httpgw.'}
|
|
235
|
+
Log.log.warn { 'A timeout condition using HTTPGW may signal a permission problem on destination. Check ascp logs on httpgw.' }
|
|
236
236
|
raise e
|
|
237
237
|
end
|
|
238
238
|
session_sent_bytes += slice_bin_data.length
|
|
@@ -250,7 +250,7 @@ module Aspera
|
|
|
250
250
|
ws_send(ws_type: :close, data: nil)
|
|
251
251
|
Log.log.debug("Finished upload, waiting for end of #{THR_RECV} thread.")
|
|
252
252
|
@ws_read_thread.join
|
|
253
|
-
Log.log.debug{'Read thread joined'}
|
|
253
|
+
Log.log.debug { 'Read thread joined' }
|
|
254
254
|
ensure
|
|
255
255
|
# session no more used
|
|
256
256
|
@ws_io = nil
|
|
@@ -284,14 +284,14 @@ module Aspera
|
|
|
284
284
|
File.basename(default_file_name)
|
|
285
285
|
end
|
|
286
286
|
file_path = File.join(transfer_spec['destination_root'], file_name)
|
|
287
|
-
call(operation: 'GET', subpath: "download/#{transfer_uuid}",
|
|
287
|
+
call(operation: 'GET', subpath: "download/#{transfer_uuid}", save_to: file_path)
|
|
288
288
|
end
|
|
289
289
|
|
|
290
290
|
def info
|
|
291
291
|
return @api_info
|
|
292
292
|
end
|
|
293
293
|
|
|
294
|
-
# @return the base url of the gateway
|
|
294
|
+
# @return [String] the base url of the gateway
|
|
295
295
|
def base_url
|
|
296
296
|
return @gw_root_url
|
|
297
297
|
end
|
|
@@ -308,7 +308,7 @@ module Aspera
|
|
|
308
308
|
Log.dump(:gw_url, url)
|
|
309
309
|
# add scheme if missing
|
|
310
310
|
url = "https://#{url}" unless url.match?(%r{^[a-z]{1,6}://})
|
|
311
|
-
|
|
311
|
+
Aspera.assert(url.start_with?('https://'), type: Error) { 'GW URL shall be with scheme https' }
|
|
312
312
|
# remove trailing slash and version (o=only once) if present
|
|
313
313
|
# TODO: issue warning ?
|
|
314
314
|
url = url.chomp('/').gsub(%r{/#{API_V1}$}o, '')
|
|
@@ -326,8 +326,8 @@ module Aspera
|
|
|
326
326
|
# web socket endpoint: by default use v2 (newer gateways), without base64 encoding
|
|
327
327
|
# is the latest supported? else revert to old api
|
|
328
328
|
if !@upload_version.eql?(API_V1)
|
|
329
|
-
if !@api_info['endpoints'].any?{ |i| i.include?(@upload_version)}
|
|
330
|
-
Log.log.warn{"API version #{@upload_version} not supported, reverting to #{API_V1}"}
|
|
329
|
+
if !@api_info['endpoints'].any? { |i| i.include?(@upload_version) }
|
|
330
|
+
Log.log.warn { "API version #{@upload_version} not supported, reverting to #{API_V1}" }
|
|
331
331
|
@upload_version = API_V1
|
|
332
332
|
end
|
|
333
333
|
end
|
|
@@ -386,7 +386,7 @@ module Aspera
|
|
|
386
386
|
size: file_size
|
|
387
387
|
})
|
|
388
388
|
else
|
|
389
|
-
Log.log.warn{"Ignoring non file/directory: #{entry_path}"}
|
|
389
|
+
Log.log.warn { "Ignoring non file/directory: #{entry_path}" }
|
|
390
390
|
end
|
|
391
391
|
end
|
|
392
392
|
end
|
|
@@ -394,7 +394,7 @@ module Aspera
|
|
|
394
394
|
raise "File not found: #{source_path}"
|
|
395
395
|
end
|
|
396
396
|
end
|
|
397
|
-
transfer_spec['paths'] = files_to_send.map{ |i| {'source' => i[:name]}}
|
|
397
|
+
transfer_spec['paths'] = files_to_send.map { |i| {'source' => i[:name]} }
|
|
398
398
|
files_to_send.push(total_bytes_to_transfer)
|
|
399
399
|
return files_to_send
|
|
400
400
|
end
|