aspera-cli 4.26.1 → 4.26.2
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 +19 -1
- data/CONTRIBUTING.md +2 -5
- data/bin/ascli +2 -2
- data/lib/aspera/agent/direct.rb +1 -1
- data/lib/aspera/agent/factory.rb +4 -0
- data/lib/aspera/agent/httpgw.rb +1 -1
- data/lib/aspera/agent/node.rb +2 -2
- data/lib/aspera/api/aoc.rb +43 -36
- data/lib/aspera/api/cos_node.rb +1 -1
- data/lib/aspera/api/faspex.rb +7 -6
- data/lib/aspera/api/node.rb +7 -7
- data/lib/aspera/ascmd.rb +4 -4
- data/lib/aspera/ascp/installation.rb +6 -2
- data/lib/aspera/cli/context.rb +58 -0
- data/lib/aspera/cli/extended_value.rb +3 -2
- data/lib/aspera/cli/formatter.rb +83 -184
- data/lib/aspera/cli/http.rb +167 -0
- data/lib/aspera/cli/manager.rb +3 -2
- data/lib/aspera/cli/plugins/alee.rb +2 -2
- data/lib/aspera/cli/plugins/aoc.rb +78 -67
- data/lib/aspera/cli/plugins/ats.rb +16 -16
- data/lib/aspera/cli/plugins/base.rb +18 -12
- data/lib/aspera/cli/plugins/config.rb +166 -438
- data/lib/aspera/cli/plugins/console.rb +7 -7
- data/lib/aspera/cli/plugins/cos.rb +2 -2
- data/lib/aspera/cli/plugins/factory.rb +3 -0
- data/lib/aspera/cli/plugins/faspex.rb +21 -21
- data/lib/aspera/cli/plugins/faspex5.rb +64 -44
- data/lib/aspera/cli/plugins/faspio.rb +1 -1
- data/lib/aspera/cli/plugins/httpgw.rb +2 -2
- data/lib/aspera/cli/plugins/node.rb +79 -79
- data/lib/aspera/cli/plugins/orchestrator.rb +21 -26
- data/lib/aspera/cli/plugins/preview.rb +9 -9
- data/lib/aspera/cli/plugins/server.rb +7 -7
- data/lib/aspera/cli/plugins/shares.rb +2 -2
- data/lib/aspera/cli/preset_manager.rb +235 -0
- data/lib/aspera/cli/result.rb +310 -0
- data/lib/aspera/cli/{main.rb → runner.rb} +14 -155
- data/lib/aspera/cli/sync_actions.rb +14 -10
- data/lib/aspera/cli/terminal_formatter.rb +65 -0
- data/lib/aspera/cli/transfer_progress.rb +6 -6
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +5 -6
- data/lib/aspera/command_line_builder.rb +1 -1
- data/lib/aspera/data_repository.rb +4 -0
- data/lib/aspera/dot_container.rb +1 -1
- data/lib/aspera/environment.rb +22 -3
- data/lib/aspera/faspex_gw.rb +1 -1
- data/lib/aspera/json_rpc.rb +6 -5
- data/lib/aspera/keychain/base.rb +1 -1
- data/lib/aspera/keychain/encrypted_hash.rb +1 -1
- data/lib/aspera/keychain/factory.rb +1 -1
- data/lib/aspera/keychain/macos_security.rb +1 -1
- data/lib/aspera/log.rb +6 -2
- data/lib/aspera/nagios.rb +2 -2
- data/lib/aspera/oauth/base.rb +5 -5
- data/lib/aspera/oauth/boot.rb +43 -0
- data/lib/aspera/oauth/factory.rb +37 -13
- data/lib/aspera/oauth/web.rb +2 -2
- data/lib/aspera/oauth.rb +1 -0
- data/lib/aspera/persistency_action_once.rb +2 -2
- data/lib/aspera/preview/file_types.rb +4 -0
- data/lib/aspera/products/connect.rb +3 -0
- data/lib/aspera/products/transferd.rb +2 -2
- data/lib/aspera/proxy_auto_config.rb +3 -3
- data/lib/aspera/rest.rb +8 -4
- data/lib/aspera/rest_error_analyzer.rb +4 -0
- data/lib/aspera/rest_list.rb +10 -3
- data/lib/aspera/schema/IBM Aspera Faspex API-5.0-enhanced.yaml +14 -4
- data/lib/aspera/schema/IBM Aspera on Cloud API-0.2.6-enhanced.yaml +827 -88
- data/lib/aspera/schema/async_tables.yaml +361 -0
- data/lib/aspera/schema/reader.rb +1 -1
- data/lib/aspera/schema/registry.rb +13 -6
- data/lib/aspera/secret_hider.rb +4 -0
- data/lib/aspera/sync/database.rb +14 -10
- data/lib/aspera/sync/operations.rb +5 -5
- data/lib/aspera/temp_file_manager.rb +4 -0
- data/lib/aspera/transfer/parameters.rb +4 -4
- data/lib/aspera/transfer/resumer.rb +1 -1
- data/lib/aspera/transfer/spec.schema.yaml +17 -8
- data/lib/aspera/transfer/uri.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +21 -14
- metadata.gz.sig +0 -0
|
@@ -42,7 +42,7 @@ module Aspera
|
|
|
42
42
|
url = options&.delete(:url)
|
|
43
43
|
if !url.nil?
|
|
44
44
|
uri = URI.parse(url)
|
|
45
|
-
Aspera.assert(uri.scheme.eql?('https')
|
|
45
|
+
Aspera.assert(uri.scheme.eql?('https'), 'only https')
|
|
46
46
|
options[:protocol] = 'htps' # cspell: disable-line
|
|
47
47
|
raise Error, 'host required in URL' if uri.host.nil?
|
|
48
48
|
options[:server] = uri.host
|
data/lib/aspera/log.rb
CHANGED
|
@@ -54,6 +54,10 @@ $VERBOSE = old_verbose
|
|
|
54
54
|
|
|
55
55
|
module Aspera
|
|
56
56
|
# Singleton object for logging
|
|
57
|
+
#
|
|
58
|
+
# @!method self.instance
|
|
59
|
+
# Returns the singleton instance of Log
|
|
60
|
+
# @return [Log] the singleton instance
|
|
57
61
|
class Log
|
|
58
62
|
include Singleton
|
|
59
63
|
|
|
@@ -80,7 +84,7 @@ module Aspera
|
|
|
80
84
|
# @yieldreturn [Object] Computed object to dump (alternative to object parameter)
|
|
81
85
|
def dump(name, object = nil, level: :debug, &block)
|
|
82
86
|
return unless instance.logger.send(:"#{level}?")
|
|
83
|
-
Aspera.assert(object.nil? || block.nil
|
|
87
|
+
Aspera.assert(object.nil? || block.nil?, 'Use either object, or block, not both')
|
|
84
88
|
object = yield if block_given?
|
|
85
89
|
instance.logger.send(level, obj_dump(name, object))
|
|
86
90
|
end
|
|
@@ -168,7 +172,7 @@ module Aspera
|
|
|
168
172
|
# Get symbol of debug level of underlying logger
|
|
169
173
|
# @return [Symbol] One of LEVELS
|
|
170
174
|
def level
|
|
171
|
-
Aspera.assert(Logger::SEVERITY_LABEL.key?(@logger.level))
|
|
175
|
+
Aspera.assert(Logger::SEVERITY_LABEL.key?(@logger.level), 'unexpected logger level value')
|
|
172
176
|
Logger::SEVERITY_LABEL[@logger.level].downcase
|
|
173
177
|
end
|
|
174
178
|
|
data/lib/aspera/nagios.rb
CHANGED
|
@@ -24,7 +24,7 @@ module Aspera
|
|
|
24
24
|
# Process results of a analysis and display status and exit with code
|
|
25
25
|
def process(data)
|
|
26
26
|
Aspera.assert_type(data, Array)
|
|
27
|
-
Aspera.assert(!data.empty
|
|
27
|
+
Aspera.assert(!data.empty?, 'data is empty')
|
|
28
28
|
%w[status component message].each do |c|
|
|
29
29
|
Aspera.assert(data.first.key?(c)){"result must have #{c}"}
|
|
30
30
|
end
|
|
@@ -79,7 +79,7 @@ module Aspera
|
|
|
79
79
|
# Readable status list
|
|
80
80
|
# @return [Array] of Hash
|
|
81
81
|
def status_list
|
|
82
|
-
Aspera.assert(!@data.empty
|
|
82
|
+
Aspera.assert(!@data.empty?, 'missing result')
|
|
83
83
|
@data.map{ |i| {'status' => LEVELS[i[:code]].to_s, 'component' => i[:comp], 'message' => i[:msg]}}
|
|
84
84
|
end
|
|
85
85
|
end
|
data/lib/aspera/oauth/base.rb
CHANGED
|
@@ -15,15 +15,15 @@ module Aspera
|
|
|
15
15
|
class Base
|
|
16
16
|
Aspera.require_method!(:create_token)
|
|
17
17
|
# @param params [Hash] Parameters for token creation (client_id, client_secret, scope, etc...)
|
|
18
|
-
# @param use_query [Boolean] Provide parameters in query instead of body
|
|
19
18
|
# @param path_token [String] API end point to create a token from base URL
|
|
19
|
+
# @param use_query [Boolean] Provide parameters in query instead of body
|
|
20
20
|
# @param token_field [String] Field in result that contains the token
|
|
21
21
|
# @param cache_ids [Array] List of unique identifiers for cache id generation
|
|
22
22
|
# @param **rest_params [Hash] Parameters for REST
|
|
23
23
|
def initialize(
|
|
24
24
|
params: {},
|
|
25
|
+
path_token: 'token',
|
|
25
26
|
use_query: false,
|
|
26
|
-
path_token: 'token',
|
|
27
27
|
token_field: Factory::TOKEN_FIELD,
|
|
28
28
|
cache_ids: [],
|
|
29
29
|
**rest_params
|
|
@@ -42,10 +42,10 @@ module Aspera
|
|
|
42
42
|
|
|
43
43
|
# The OAuth API Object
|
|
44
44
|
attr_reader :api
|
|
45
|
-
# Sub path to generate token
|
|
46
|
-
attr_reader :path_token
|
|
47
45
|
# Parameters to generate token
|
|
48
46
|
attr_reader :params
|
|
47
|
+
# Sub path to generate token
|
|
48
|
+
attr_reader :path_token
|
|
49
49
|
|
|
50
50
|
# Helper method to create token as per RFC
|
|
51
51
|
# @return [HTTPResponse]
|
|
@@ -122,7 +122,7 @@ module Aspera
|
|
|
122
122
|
token_data = JSON.parse(json_data)
|
|
123
123
|
Factory.instance.persist_mgr.put(@token_cache_id, json_data)
|
|
124
124
|
end
|
|
125
|
-
Aspera.assert(token_data.key?(@token_field)){"API error: No such field in answer: #{@token_field}"}
|
|
125
|
+
Aspera.assert(token_data.key?(@token_field)){"API error: No such field in answer: #{@token_field}"} unless token_data.nil?
|
|
126
126
|
# ok we shall have a token here
|
|
127
127
|
return token_data[@token_field]
|
|
128
128
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'aspera/oauth/base'
|
|
4
|
+
require 'aspera/assert'
|
|
5
|
+
require 'json'
|
|
6
|
+
|
|
7
|
+
module Aspera
|
|
8
|
+
module OAuth
|
|
9
|
+
# Token provider bootstrapped from an existing cookie (e.g. AoC browser cookie).
|
|
10
|
+
# Injects the bearer token and optional refresh token directly into the cache.
|
|
11
|
+
# Never generates a new token from scratch — raises if cache+refresh are both exhausted.
|
|
12
|
+
class Boot < Base
|
|
13
|
+
# @param cookie [String, nil] Raw cookie string (--password), nil to rely on existing cache
|
|
14
|
+
# @param username [String, nil] Expected subject; if provided, must match token's `sub` claim
|
|
15
|
+
# @param **base_params Forwarded to Base (base_url:, params: {client_id:, scope:}, etc.)
|
|
16
|
+
def initialize(cookie: nil, username: nil, **base_params)
|
|
17
|
+
if cookie.nil?
|
|
18
|
+
# No cookie: rely on existing cache, identified by username if provided
|
|
19
|
+
Aspera.assert(username, 'Provide --password (cookie) on first use, or --username for cache lookup', type: ParameterError)
|
|
20
|
+
super(**base_params, cache_ids: [username])
|
|
21
|
+
else
|
|
22
|
+
cookies = cookie.split('; ').map{ |p| p.split('=', 2)}.to_h
|
|
23
|
+
Aspera.assert(cookies.key?('aoc.token'), '--password cookie does not contain aoc.token', type: ParameterError)
|
|
24
|
+
token = cookies['aoc.token']
|
|
25
|
+
decoded = Factory.instance.decode_token(token)
|
|
26
|
+
Aspera.assert_type(decoded, Hash){'Boot: token is not a decodable JWT'}
|
|
27
|
+
sub = decoded['sub']
|
|
28
|
+
Aspera.assert(username.nil? || username.eql?(sub)){"Boot: --username #{username} does not match token subject #{sub}"}
|
|
29
|
+
super(**base_params, cache_ids: [sub])
|
|
30
|
+
token_data = {Factory::TOKEN_FIELD => token}
|
|
31
|
+
token_data['refresh_token'] = cookies['aoc.refresh'] if cookies.key?('aoc.refresh')
|
|
32
|
+
Factory.instance.persist_mgr.put(@token_cache_id, JSON.generate(token_data))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Should never be reached: if cache and refresh are both exhausted, re-authenticate via browser
|
|
37
|
+
def create_token
|
|
38
|
+
Aspera.report_error(AssertError, 'Boot: token expired and no refresh available — re-authenticate in browser')
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
Factory.instance.register_token_creator(Boot)
|
|
42
|
+
end
|
|
43
|
+
end
|
data/lib/aspera/oauth/factory.rb
CHANGED
|
@@ -7,10 +7,14 @@ require 'base64'
|
|
|
7
7
|
module Aspera
|
|
8
8
|
module OAuth
|
|
9
9
|
# Factory to create tokens and manage their cache
|
|
10
|
+
#
|
|
11
|
+
# @!method self.instance
|
|
12
|
+
# Returns the singleton instance of Factory
|
|
13
|
+
# @return [Factory] the singleton instance
|
|
10
14
|
class Factory
|
|
11
15
|
include Singleton
|
|
12
16
|
|
|
13
|
-
#
|
|
17
|
+
# prefix for persistency of tokens (simplify garbage collect)
|
|
14
18
|
PERSIST_CATEGORY_TOKEN = 'token'
|
|
15
19
|
# prefix for bearer authorization when in header
|
|
16
20
|
SPACE_BEARER_AUTH_SCHEME = 'Bearer '
|
|
@@ -19,18 +23,23 @@ module Aspera
|
|
|
19
23
|
private_constant :PERSIST_CATEGORY_TOKEN, :SPACE_BEARER_AUTH_SCHEME
|
|
20
24
|
|
|
21
25
|
class << self
|
|
26
|
+
# Format a token for use in Authorization header
|
|
22
27
|
# @param token [String] The token alone
|
|
23
28
|
# @return [String] Value suitable for Authorization header
|
|
24
29
|
def bearer_authorization(token)
|
|
25
30
|
return "#{SPACE_BEARER_AUTH_SCHEME}#{token}"
|
|
26
31
|
end
|
|
27
32
|
|
|
28
|
-
#
|
|
33
|
+
# Check if the authorization contains a bearer token
|
|
34
|
+
# @param authorization [String] The authorization header value
|
|
35
|
+
# @return [Boolean] true if the authorization contains a bearer token, i.e. auth scheme is bearer
|
|
29
36
|
def bearer_auth?(authorization)
|
|
30
37
|
return authorization.start_with?(SPACE_BEARER_AUTH_SCHEME)
|
|
31
38
|
end
|
|
32
39
|
|
|
33
40
|
# Extract only token from Authorization (remove scheme)
|
|
41
|
+
# @param authorization [String] The authorization header value
|
|
42
|
+
# @return [String] The bearer token without the scheme prefix
|
|
34
43
|
def bearer_token(authorization)
|
|
35
44
|
Aspera.assert(bearer_auth?(authorization)){'not a bearer token, wrong prefix scheme'}
|
|
36
45
|
return authorization.delete_prefix(SPACE_BEARER_AUTH_SCHEME)
|
|
@@ -40,12 +49,14 @@ module Aspera
|
|
|
40
49
|
# @param url [String] Base URL of the OAuth server
|
|
41
50
|
# @param creator_class [Class] Class of the token creator
|
|
42
51
|
# @param params [Array] List of parameters (can be nested) to uniquely identify the token
|
|
43
|
-
# @return a unique cache identifier
|
|
52
|
+
# @return [String] a unique cache identifier
|
|
44
53
|
def cache_id(url, creator_class, *params)
|
|
45
54
|
return IdGenerator.from_list(PERSIST_CATEGORY_TOKEN, url, Factory.class_to_id(creator_class), params)
|
|
46
55
|
end
|
|
47
56
|
|
|
48
|
-
#
|
|
57
|
+
# Convert a class name to snake_case symbol
|
|
58
|
+
# @param creator_class [Class] The class to convert
|
|
59
|
+
# @return [Symbol] snake_case version of class name
|
|
49
60
|
def class_to_id(creator_class)
|
|
50
61
|
return creator_class.name.split('::').last.capital_to_snake.to_sym
|
|
51
62
|
end
|
|
@@ -53,6 +64,7 @@ module Aspera
|
|
|
53
64
|
|
|
54
65
|
private
|
|
55
66
|
|
|
67
|
+
# Initialize the factory with default parameters and empty collections
|
|
56
68
|
def initialize
|
|
57
69
|
# persistency manager
|
|
58
70
|
@persist = nil
|
|
@@ -73,12 +85,16 @@ module Aspera
|
|
|
73
85
|
|
|
74
86
|
attr_reader :parameters
|
|
75
87
|
|
|
88
|
+
# Set the persistence manager for token caching
|
|
89
|
+
# @param manager [Object] The persistence manager instance
|
|
76
90
|
def persist_mgr=(manager)
|
|
77
91
|
@persist = manager
|
|
78
92
|
# cleanup expired tokens
|
|
79
93
|
@persist.garbage_collect(PERSIST_CATEGORY_TOKEN, @parameters[:token_cache_max_age])
|
|
80
94
|
end
|
|
81
95
|
|
|
96
|
+
# Get or initialize the persistence manager
|
|
97
|
+
# @return [Object] The persistence manager instance
|
|
82
98
|
def persist_mgr
|
|
83
99
|
if @persist.nil?
|
|
84
100
|
# use OAuth::Factory.instance.persist_mgr=PersistencyFolder.new)
|
|
@@ -91,11 +107,14 @@ module Aspera
|
|
|
91
107
|
return @persist
|
|
92
108
|
end
|
|
93
109
|
|
|
94
|
-
#
|
|
110
|
+
# Delete all existing tokens in cache
|
|
111
|
+
# @return [void]
|
|
95
112
|
def flush_tokens
|
|
96
113
|
persist_mgr.garbage_collect(PERSIST_CATEGORY_TOKEN)
|
|
97
114
|
end
|
|
98
115
|
|
|
116
|
+
# Retrieve all persisted tokens with their decoded information
|
|
117
|
+
# @return [Array<Hash>] Array of token information hashes
|
|
99
118
|
def persisted_tokens
|
|
100
119
|
data = persist_mgr.current_items(PERSIST_CATEGORY_TOKEN)
|
|
101
120
|
data.each.map do |k, v|
|
|
@@ -134,12 +153,16 @@ module Aspera
|
|
|
134
153
|
return info
|
|
135
154
|
end
|
|
136
155
|
|
|
137
|
-
#
|
|
156
|
+
# Register a bearer token decoder for inspecting token properties
|
|
157
|
+
# @param method [Proc] The decoder lambda/proc to register
|
|
158
|
+
# @return [void]
|
|
138
159
|
def register_decoder(method)
|
|
139
160
|
@decoders.push(method)
|
|
140
161
|
end
|
|
141
162
|
|
|
142
|
-
#
|
|
163
|
+
# Decode a token using all registered decoders
|
|
164
|
+
# @param token [String] The token to decode
|
|
165
|
+
# @return [Hash, nil] Decoded token data or nil if no decoder succeeded
|
|
143
166
|
def decode_token(token)
|
|
144
167
|
@decoders.each do |decoder|
|
|
145
168
|
result = decoder.call(token) rescue nil
|
|
@@ -148,10 +171,9 @@ module Aspera
|
|
|
148
171
|
return
|
|
149
172
|
end
|
|
150
173
|
|
|
151
|
-
#
|
|
152
|
-
# @param
|
|
153
|
-
# @
|
|
154
|
-
# @param id_create called to generate unique id for token, for cache
|
|
174
|
+
# Register a token creation method
|
|
175
|
+
# @param creator_class [Class] The token creator class to register
|
|
176
|
+
# @return [void]
|
|
155
177
|
def register_token_creator(creator_class)
|
|
156
178
|
Aspera.assert_type(creator_class, Class)
|
|
157
179
|
id = Factory.class_to_id(creator_class)
|
|
@@ -159,7 +181,9 @@ module Aspera
|
|
|
159
181
|
@token_type_classes[id] = creator_class
|
|
160
182
|
end
|
|
161
183
|
|
|
162
|
-
#
|
|
184
|
+
# Create a token creator instance for the specified grant method
|
|
185
|
+
# @param parameters [Hash] Parameters including :grant_method and creator-specific options
|
|
186
|
+
# @return [Object] An instance of the registered token creator class
|
|
163
187
|
def create(**parameters)
|
|
164
188
|
Aspera.assert_type(parameters, Hash)
|
|
165
189
|
id = parameters[:grant_method]
|
|
@@ -169,6 +193,6 @@ module Aspera
|
|
|
169
193
|
end
|
|
170
194
|
end
|
|
171
195
|
# JSON Web Signature (JWS) compact serialization: https://datatracker.ietf.org/doc/html/rfc7515
|
|
172
|
-
Factory.instance.register_decoder(lambda{ |token| parts = token.split('.'); Aspera.
|
|
196
|
+
Factory.instance.register_decoder(lambda{ |token| parts = token.split('.'); Aspera.assert_values(parts.length, [3]){'JWS token parts'}; JSON.parse(Base64.decode64(parts[1]))}) # rubocop:disable Style/Semicolon
|
|
173
197
|
end
|
|
174
198
|
end
|
data/lib/aspera/oauth/web.rb
CHANGED
|
@@ -22,8 +22,8 @@ module Aspera
|
|
|
22
22
|
@redirect_uri = redirect_uri
|
|
23
23
|
@path_authorize = path_authorize
|
|
24
24
|
uri = URI.parse(@redirect_uri)
|
|
25
|
-
Aspera.
|
|
26
|
-
Aspera.assert(!uri.port.nil
|
|
25
|
+
Aspera.assert_values(uri.scheme, %w[http https]){'redirect_uri scheme must be http or https'}
|
|
26
|
+
Aspera.assert(!uri.port.nil?, 'redirect_uri must have a port')
|
|
27
27
|
# TODO: we could check that host is localhost or local address, as we are going to listen locally
|
|
28
28
|
end
|
|
29
29
|
|
data/lib/aspera/oauth.rb
CHANGED
|
@@ -23,9 +23,9 @@ module Aspera
|
|
|
23
23
|
# @param :merge Optional merge data from file to current data
|
|
24
24
|
def initialize(manager:, data:, id:, delete: DELETE_DEFAULT, parse: PARSE_DEFAULT, format: FORMAT_DEFAULT, merge: MERGE_DEFAULT)
|
|
25
25
|
Aspera.assert(MANAGER_METHODS.all?{ |i| manager.respond_to?(i)}){"Manager must answer to #{MANAGER_METHODS}"}
|
|
26
|
-
Aspera.assert(!data.nil
|
|
26
|
+
Aspera.assert(!data.nil?, 'data must not be nil')
|
|
27
27
|
Aspera.assert_type(id, String)
|
|
28
|
-
Aspera.assert(!id.empty
|
|
28
|
+
Aspera.assert(!id.empty?, 'id must not be empty')
|
|
29
29
|
Aspera.assert_type(delete, Proc)
|
|
30
30
|
Aspera.assert_type(parse, Proc)
|
|
31
31
|
Aspera.assert_type(format, Proc)
|
|
@@ -8,6 +8,10 @@ require 'marcel'
|
|
|
8
8
|
module Aspera
|
|
9
9
|
module Preview
|
|
10
10
|
# function conversion_type returns one of the types: CONVERSION_TYPES
|
|
11
|
+
#
|
|
12
|
+
# @!method self.instance
|
|
13
|
+
# Returns the singleton instance of FileTypes
|
|
14
|
+
# @return [FileTypes] the singleton instance
|
|
11
15
|
class FileTypes
|
|
12
16
|
include Singleton
|
|
13
17
|
|
|
@@ -29,7 +29,7 @@ module Aspera
|
|
|
29
29
|
|
|
30
30
|
# @return the path to folder where SDK is or should be installed
|
|
31
31
|
def sdk_directory
|
|
32
|
-
Aspera.assert(!@sdk_dir.nil
|
|
32
|
+
Aspera.assert(!@sdk_dir.nil?, 'SDK path was not initialized')
|
|
33
33
|
@sdk_dir
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -52,7 +52,7 @@ module Aspera
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
|
-
Aspera.assert(!result.nil
|
|
55
|
+
Aspera.assert(!result.nil?, 'Port not found in daemon logs')
|
|
56
56
|
Log.log.debug{"Got port #{result} from log"}
|
|
57
57
|
return result
|
|
58
58
|
end
|
|
@@ -14,7 +14,7 @@ module URI
|
|
|
14
14
|
# @yieldparam url [String] The URL to find proxy for
|
|
15
15
|
# @yieldreturn [String, nil] Proxy URL or nil to fallback to original method
|
|
16
16
|
def register_proxy_finder
|
|
17
|
-
Aspera.assert(block_given
|
|
17
|
+
Aspera.assert(block_given?, 'block required for register_proxy_finder')
|
|
18
18
|
# overload the method in URI : call user's provided block and fallback to original method
|
|
19
19
|
define_method(:find_proxy){ |env_vars = ENV| yield(to_s) || find_proxy_orig(env_vars)}
|
|
20
20
|
end
|
|
@@ -116,12 +116,12 @@ END_OF_JAVASCRIPT
|
|
|
116
116
|
parts = item.strip.split
|
|
117
117
|
case parts.shift
|
|
118
118
|
when 'DIRECT'
|
|
119
|
-
Aspera.assert(parts.empty
|
|
119
|
+
Aspera.assert(parts.empty?, 'DIRECT has no param')
|
|
120
120
|
Log.log.debug('ignoring proxy DIRECT')
|
|
121
121
|
when 'PROXY'
|
|
122
122
|
addr_port = parts.shift
|
|
123
123
|
Aspera.assert_type(addr_port, String)
|
|
124
|
-
Aspera.assert(parts.empty
|
|
124
|
+
Aspera.assert(parts.empty?, 'PROXY shall have one param')
|
|
125
125
|
begin
|
|
126
126
|
# PAC proxy addresses are <host>:<port>
|
|
127
127
|
if /:[0-9]+$/.match?(addr_port)
|
data/lib/aspera/rest.rb
CHANGED
|
@@ -30,6 +30,10 @@ module Aspera
|
|
|
30
30
|
# @param download_partial_suffix [String] suffix for partial download
|
|
31
31
|
# @param session_cb [lambda] lambda called on new HTTP session. Takes the Net::HTTP as arg. Used to change parameters on creation.
|
|
32
32
|
# @param progress_bar [Object] progress bar object called for file transfer
|
|
33
|
+
#
|
|
34
|
+
# @!method self.instance
|
|
35
|
+
# Returns the singleton instance of RestParameters
|
|
36
|
+
# @return [RestParameters] the singleton instance
|
|
33
37
|
class RestParameters
|
|
34
38
|
include Singleton
|
|
35
39
|
|
|
@@ -102,7 +106,7 @@ module Aspera
|
|
|
102
106
|
when Hash
|
|
103
107
|
URI.encode_www_form(h_to_query_array(query))
|
|
104
108
|
when Array
|
|
105
|
-
Aspera.assert(query.all?{ |i| i.is_a?(Array) && i.length.eql?(2)}
|
|
109
|
+
Aspera.assert(query.all?{ |i| i.is_a?(Array) && i.length.eql?(2)}, 'Query must be array of arrays of 2 elements')
|
|
106
110
|
URI.encode_www_form(query) # remove nil values
|
|
107
111
|
else Aspera.error_unexpected_value(query.class){'query type'}
|
|
108
112
|
end.gsub('%5B%5D=', '[]=')
|
|
@@ -316,7 +320,7 @@ module Aspera
|
|
|
316
320
|
# default is no auth
|
|
317
321
|
@auth_params = auth
|
|
318
322
|
Aspera.assert_type(@auth_params, Hash)
|
|
319
|
-
Aspera.assert(@auth_params.key?(:type)
|
|
323
|
+
Aspera.assert(@auth_params.key?(:type), 'no auth type defined')
|
|
320
324
|
@not_auth_codes = not_auth_codes
|
|
321
325
|
Aspera.assert_type(@not_auth_codes, Array)
|
|
322
326
|
# persistent session
|
|
@@ -333,7 +337,7 @@ module Aspera
|
|
|
333
337
|
# @return the OAuth object (create, or cached if already created)
|
|
334
338
|
def oauth
|
|
335
339
|
if @oauth.nil?
|
|
336
|
-
Aspera.assert(@auth_params[:type].eql?(:oauth2)
|
|
340
|
+
Aspera.assert(@auth_params[:type].eql?(:oauth2), 'no OAuth defined')
|
|
337
341
|
oauth_parameters = @auth_params.reject{ |k, _v| k.eql?(:type)}
|
|
338
342
|
Log.dump(:oauth_parameters, oauth_parameters)
|
|
339
343
|
@oauth = OAuth::Factory.instance.create(**oauth_parameters)
|
|
@@ -374,7 +378,7 @@ module Aspera
|
|
|
374
378
|
Log.dump(:headers, headers, level: :trace1)
|
|
375
379
|
Aspera.assert_type(subpath, String)
|
|
376
380
|
# We must have a way to check return code
|
|
377
|
-
Aspera.assert(exception || !ret.eql?(:data))
|
|
381
|
+
Aspera.assert(exception || !ret.eql?(:data), 'ret: :data requires exception handler')
|
|
378
382
|
if headers.nil?
|
|
379
383
|
headers = @headers.clone
|
|
380
384
|
else
|
|
@@ -7,6 +7,10 @@ require 'net/http'
|
|
|
7
7
|
|
|
8
8
|
module Aspera
|
|
9
9
|
# analyze error codes returned by REST calls and raise ruby exception
|
|
10
|
+
#
|
|
11
|
+
# @!method self.instance
|
|
12
|
+
# Returns the singleton instance of RestErrorAnalyzer
|
|
13
|
+
# @return [RestErrorAnalyzer] the singleton instance
|
|
10
14
|
class RestErrorAnalyzer
|
|
11
15
|
include Singleton
|
|
12
16
|
|
data/lib/aspera/rest_list.rb
CHANGED
|
@@ -50,6 +50,7 @@ module Aspera
|
|
|
50
50
|
# @return [Array<(Array<Hash>, Integer)>] items, total_count
|
|
51
51
|
def list_entities_limit_offset_total_count(
|
|
52
52
|
entity:,
|
|
53
|
+
operation: 'GET',
|
|
53
54
|
items_key: nil,
|
|
54
55
|
query: nil
|
|
55
56
|
)
|
|
@@ -67,9 +68,15 @@ module Aspera
|
|
|
67
68
|
# Merge default parameters, by default 100 per page
|
|
68
69
|
query = {'limit'=> PER_PAGE_DEFAULT}.merge(query)
|
|
69
70
|
total_count = nil
|
|
71
|
+
call_args = {
|
|
72
|
+
operation: operation,
|
|
73
|
+
subpath: entity,
|
|
74
|
+
query: query,
|
|
75
|
+
headers: {'Accept' => Mime::JSON}
|
|
76
|
+
}
|
|
70
77
|
loop do
|
|
71
78
|
query['offset'] = offset
|
|
72
|
-
page_result =
|
|
79
|
+
page_result = call(**call_args)
|
|
73
80
|
Aspera.assert_type(page_result[items_key], Array)
|
|
74
81
|
result.concat(page_result[items_key])
|
|
75
82
|
# Reach the limit set by user ?
|
|
@@ -97,7 +104,7 @@ module Aspera
|
|
|
97
104
|
# @param query [Hash] Additional query parameters (Default: `:default`)
|
|
98
105
|
def lookup_entity_by_field(entity:, value:, field: 'name', items_key: nil, query: :default)
|
|
99
106
|
if query.eql?(:default)
|
|
100
|
-
Aspera.
|
|
107
|
+
Aspera.assert_values(field, ['name']){'Default query field'}
|
|
101
108
|
query = {'q'=> value}
|
|
102
109
|
end
|
|
103
110
|
lookup_entity_generic(entity: entity, field: field, value: value){list_entities_limit_offset_total_count(entity: entity, items_key: items_key, query: query).first}
|
|
@@ -113,7 +120,7 @@ module Aspera
|
|
|
113
120
|
# @return [Hash] The unique matching object.
|
|
114
121
|
# @raise [Cli::BadIdentifier] If 0 or >1 matches are found.
|
|
115
122
|
def lookup_entity_generic(entity:, value:, field: 'name')
|
|
116
|
-
Aspera.assert(block_given
|
|
123
|
+
Aspera.assert(block_given?, 'block required for lookup_entity_generic')
|
|
117
124
|
found = yield
|
|
118
125
|
Aspera.assert_array_all(found, Hash)
|
|
119
126
|
found = found.select{ |i| i[field].eql?(value)}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
# DO NOT EDIT THIS FILE MANUALLY
|
|
2
|
+
# This file is automatically downloaded from:
|
|
3
|
+
# https://raw.githubusercontent.com/laurent-martin/aspera-api-examples/refs/heads/main/openapi/IBM%20Aspera%20Faspex%20API-5.0-enhanced.yaml
|
|
4
|
+
# Use 'rake tools:openapi' to update this file
|
|
5
|
+
|
|
1
6
|
openapi: 3.1.0
|
|
2
7
|
info:
|
|
3
8
|
title: IBM Aspera Faspex API
|
|
@@ -32646,7 +32651,12 @@ components:
|
|
|
32646
32651
|
maxLength: 255
|
|
32647
32652
|
minLength: 1
|
|
32648
32653
|
expiration_policy:
|
|
32649
|
-
description:
|
|
32654
|
+
description: |-
|
|
32655
|
+
The expiration policy for the package.
|
|
32656
|
+
* `none`: Default, for no expiration policy (a package will not be marked for deletion based on recipient downloads).
|
|
32657
|
+
* `delete_after_all_download` for deleting a package after ALL users do a full download of the package (download of all files/folders in the package).
|
|
32658
|
+
* `delete_after_any_download` for deleting a package after ANY user fully downloads.
|
|
32659
|
+
* `delete_after_expiration_date` for deleting a package after the date set in expiration_date parameter.
|
|
32650
32660
|
type: string
|
|
32651
32661
|
default: none
|
|
32652
32662
|
enum:
|
|
@@ -40721,9 +40731,9 @@ components:
|
|
|
40721
40731
|
type: boolean
|
|
40722
40732
|
can_have_public_url:
|
|
40723
40733
|
description: |-
|
|
40724
|
-
Specifies whether the user can share public submission submission links
|
|
40725
|
-
|
|
40726
|
-
|
|
40734
|
+
Specifies whether the user can share public submission submission links.
|
|
40735
|
+
A user can share public submission links to invite external users to
|
|
40736
|
+
send packages to the user.
|
|
40727
40737
|
type: string
|
|
40728
40738
|
default: default
|
|
40729
40739
|
enum:
|