aspera-cli 4.16.0 → 4.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +50 -19
- data/CONTRIBUTING.md +3 -1
- data/README.md +965 -793
- data/bin/asession +29 -21
- data/lib/aspera/{fasp/agent_alpha.rb → agent/alpha.rb} +26 -25
- data/lib/aspera/{fasp/agent_base.rb → agent/base.rb} +15 -12
- data/lib/aspera/{fasp/agent_connect.rb → agent/connect.rb} +13 -11
- data/lib/aspera/{fasp/agent_direct.rb → agent/direct.rb} +49 -53
- data/lib/aspera/{fasp/agent_httpgw.rb → agent/httpgw.rb} +20 -19
- data/lib/aspera/{fasp/agent_node.rb → agent/node.rb} +20 -33
- data/lib/aspera/{fasp/agent_trsdk.rb → agent/trsdk.rb} +11 -11
- data/lib/aspera/api/aoc.rb +586 -0
- data/lib/aspera/api/ats.rb +46 -0
- data/lib/aspera/api/cos_node.rb +95 -0
- data/lib/aspera/api/node.rb +344 -0
- data/lib/aspera/ascmd.rb +46 -10
- data/lib/aspera/{fasp → ascp}/installation.rb +5 -5
- data/lib/aspera/{fasp → ascp}/management.rb +3 -8
- data/lib/aspera/{fasp → ascp}/products.rb +1 -1
- data/lib/aspera/assert.rb +30 -30
- data/lib/aspera/cli/basic_auth_plugin.rb +11 -10
- data/lib/aspera/cli/extended_value.rb +1 -1
- data/lib/aspera/cli/formatter.rb +13 -13
- data/lib/aspera/cli/hints.rb +5 -5
- data/lib/aspera/cli/main.rb +35 -28
- data/lib/aspera/cli/manager.rb +25 -24
- data/lib/aspera/cli/plugin.rb +22 -15
- data/lib/aspera/cli/plugin_factory.rb +61 -0
- data/lib/aspera/cli/plugins/alee.rb +7 -7
- data/lib/aspera/cli/plugins/aoc.rb +83 -77
- data/lib/aspera/cli/plugins/ats.rb +32 -33
- data/lib/aspera/cli/plugins/bss.rb +3 -4
- data/lib/aspera/cli/plugins/config.rb +169 -186
- data/lib/aspera/cli/plugins/console.rb +8 -6
- data/lib/aspera/cli/plugins/cos.rb +19 -18
- data/lib/aspera/cli/plugins/faspex.rb +61 -54
- data/lib/aspera/cli/plugins/faspex5.rb +150 -103
- data/lib/aspera/cli/plugins/node.rb +68 -73
- data/lib/aspera/cli/plugins/orchestrator.rb +34 -44
- data/lib/aspera/cli/plugins/preview.rb +31 -31
- data/lib/aspera/cli/plugins/server.rb +31 -33
- data/lib/aspera/cli/plugins/shares.rb +13 -11
- data/lib/aspera/cli/sync_actions.rb +8 -8
- data/lib/aspera/cli/transfer_agent.rb +32 -19
- data/lib/aspera/cli/transfer_progress.rb +1 -1
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +5 -0
- data/lib/aspera/command_line_builder.rb +14 -14
- data/lib/aspera/coverage.rb +1 -2
- data/lib/aspera/data_repository.rb +1 -1
- data/lib/aspera/environment.rb +2 -3
- data/lib/aspera/faspex_gw.rb +5 -6
- data/lib/aspera/faspex_postproc.rb +1 -1
- data/lib/aspera/id_generator.rb +2 -2
- data/lib/aspera/json_rpc.rb +5 -5
- data/lib/aspera/keychain/encrypted_hash.rb +6 -6
- data/lib/aspera/keychain/macos_security.rb +27 -22
- data/lib/aspera/log.rb +2 -2
- data/lib/aspera/nagios.rb +3 -3
- data/lib/aspera/node_simulator.rb +5 -6
- data/lib/aspera/oauth/base.rb +143 -0
- data/lib/aspera/oauth/factory.rb +124 -0
- data/lib/aspera/oauth/generic.rb +34 -0
- data/lib/aspera/oauth/jwt.rb +51 -0
- data/lib/aspera/oauth/url_json.rb +31 -0
- data/lib/aspera/oauth/web.rb +50 -0
- data/lib/aspera/oauth.rb +5 -331
- data/lib/aspera/open_application.rb +7 -7
- data/lib/aspera/persistency_action_once.rb +4 -4
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/generator.rb +5 -5
- data/lib/aspera/preview/terminal.rb +3 -2
- data/lib/aspera/preview/utils.rb +3 -3
- data/lib/aspera/proxy_auto_config.rb +4 -4
- data/lib/aspera/rest.rb +175 -144
- data/lib/aspera/rest_errors_aspera.rb +3 -3
- data/lib/aspera/resumer.rb +77 -0
- data/lib/aspera/ssh.rb +6 -1
- data/lib/aspera/{fasp → transfer}/error.rb +3 -3
- data/lib/aspera/{fasp → transfer}/error_info.rb +1 -1
- data/lib/aspera/{fasp → transfer}/faux_file.rb +1 -1
- data/lib/aspera/{fasp → transfer}/parameters.rb +58 -89
- data/lib/aspera/{fasp/transfer_spec.rb → transfer/spec.rb} +18 -16
- data/lib/aspera/{fasp/parameters.yaml → transfer/spec.yaml} +4 -99
- data/lib/aspera/{fasp → transfer}/sync.rb +32 -32
- data/lib/aspera/{fasp → transfer}/uri.rb +9 -8
- data/lib/aspera/web_server_simple.rb +11 -3
- data.tar.gz.sig +0 -0
- metadata +36 -63
- metadata.gz.sig +0 -0
- data/lib/aspera/aoc.rb +0 -601
- data/lib/aspera/ats_api.rb +0 -47
- data/lib/aspera/cos_node.rb +0 -94
- data/lib/aspera/fasp/resume_policy.rb +0 -79
- data/lib/aspera/node.rb +0 -339
data/lib/aspera/cli/plugin.rb
CHANGED
@@ -19,6 +19,7 @@ module Aspera
|
|
19
19
|
MAX_PAGES = 'pmax'
|
20
20
|
# special identifier format: look for this name to find where supported
|
21
21
|
REGEX_LOOKUP_ID_BY_FIELD = /^%([^:]+):(.*)$/.freeze
|
22
|
+
INIT_PARAMS = %i[options transfer config formatter persistency only_manual].freeze
|
22
23
|
|
23
24
|
class << self
|
24
25
|
def declare_generic_options(options)
|
@@ -33,12 +34,18 @@ module Aspera
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
attr_accessor(*INIT_PARAMS)
|
38
|
+
|
39
|
+
def initialize(options:, transfer:, config:, formatter:, persistency:, only_manual:)
|
40
|
+
@options = options
|
41
|
+
@transfer = transfer
|
42
|
+
@config = config
|
43
|
+
@formatter = formatter
|
44
|
+
@persistency = persistency
|
45
|
+
@only_manual = only_manual
|
39
46
|
# check presence in descendant of mandatory method and constant
|
40
|
-
assert(respond_to?(:execute_action)){"Missing method 'execute_action' in #{self.class}"}
|
41
|
-
assert(self.class.constants.include?(:ACTIONS)){'ACTIONS shall be redefined by subclass'}
|
47
|
+
Aspera.assert(respond_to?(:execute_action)){"Missing method 'execute_action' in #{self.class}"}
|
48
|
+
Aspera.assert(self.class.constants.include?(:ACTIONS)){'ACTIONS shall be redefined by subclass'}
|
42
49
|
# manual header for all plugins
|
43
50
|
options.parser.separator('')
|
44
51
|
options.parser.separator("COMMAND: #{self.class.name.split('::').last.downcase}")
|
@@ -46,6 +53,11 @@ module Aspera
|
|
46
53
|
options.parser.separator('OPTIONS:')
|
47
54
|
end
|
48
55
|
|
56
|
+
def init_params
|
57
|
+
# return a hash of instance variables
|
58
|
+
INIT_PARAMS.map{|p| [p, instance_variable_get("@#{p}".to_sym)]}.to_h
|
59
|
+
end
|
60
|
+
|
49
61
|
# must be called AFTER the instance action, ... folder browse <call instance_identifier>
|
50
62
|
# @param description [String] description of the identifier
|
51
63
|
# @param as_option [Symbol] option name to use if identifier is an option
|
@@ -76,7 +88,7 @@ module Aspera
|
|
76
88
|
# @param id_result [String] key in result hash to use as identifier
|
77
89
|
# @param fields [Array] fields to display
|
78
90
|
def do_bulk_operation(command:, descr:, values: Hash, id_result: 'id', fields: :default)
|
79
|
-
assert(block_given?){'missing block'}
|
91
|
+
Aspera.assert(block_given?){'missing block'}
|
80
92
|
is_bulk = options.get_option(:bulk)
|
81
93
|
case values
|
82
94
|
when :identifier
|
@@ -238,23 +250,18 @@ module Aspera
|
|
238
250
|
value = default if value.nil?
|
239
251
|
unless type.nil?
|
240
252
|
type = [type] unless type.is_a?(Array)
|
241
|
-
assert(type.all?(Class)){"check types must be a Class, not #{type.map(&:class).join(',')}"}
|
253
|
+
Aspera.assert(type.all?(Class)){"check types must be a Class, not #{type.map(&:class).join(',')}"}
|
242
254
|
if bulk
|
243
|
-
assert_type(value, Array, exception_class: Cli::BadArgument)
|
255
|
+
Aspera.assert_type(value, Array, exception_class: Cli::BadArgument)
|
244
256
|
value.each do |v|
|
245
|
-
assert_values(v.class, type, exception_class: Cli::BadArgument)
|
257
|
+
Aspera.assert_values(v.class, type, exception_class: Cli::BadArgument)
|
246
258
|
end
|
247
259
|
else
|
248
|
-
assert_values(value.class, type, exception_class: Cli::BadArgument)
|
260
|
+
Aspera.assert_values(value.class, type, exception_class: Cli::BadArgument)
|
249
261
|
end
|
250
262
|
end
|
251
263
|
return value
|
252
264
|
end
|
253
|
-
|
254
|
-
# shortcuts helpers for plugin environment
|
255
|
-
%i[options transfer config formatter persistency].each do |name|
|
256
|
-
define_method(name){@agents[name]}
|
257
|
-
end
|
258
265
|
end # Plugin
|
259
266
|
end # Cli
|
260
267
|
end # Aspera
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
module Aspera
|
5
|
+
module Cli
|
6
|
+
# option is retrieved from another object using accessor
|
7
|
+
class PluginFactory
|
8
|
+
include Singleton
|
9
|
+
attr_reader :lookup_folders, :plugins
|
10
|
+
|
11
|
+
RUBY_FILE_EXT = '.rb'
|
12
|
+
PLUGINS_MODULE = 'Plugins'
|
13
|
+
private_constant :RUBY_FILE_EXT
|
14
|
+
class << self
|
15
|
+
# instantiate a plugin
|
16
|
+
# plugins must be Capitalized
|
17
|
+
def plugin_class(plugin_name_sym)
|
18
|
+
# Module.nesting[2] is Cli::Plugins
|
19
|
+
return Object.const_get("#{Module.nesting[2]}::#{PLUGINS_MODULE}::#{plugin_name_sym.to_s.capitalize}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@lookup_folders = []
|
25
|
+
@plugins = {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_plugin_info(path)
|
29
|
+
raise "ERROR: plugin path must end with #{RUBY_FILE_EXT}" if !path.end_with?(RUBY_FILE_EXT)
|
30
|
+
plugin_symbol = File.basename(path, RUBY_FILE_EXT).to_sym
|
31
|
+
req = path.sub(/#{RUBY_FILE_EXT}$/o, '')
|
32
|
+
if @plugins.key?(plugin_symbol)
|
33
|
+
Log.log.warn{"skipping plugin already registered: #{plugin_symbol}"}
|
34
|
+
return
|
35
|
+
end
|
36
|
+
@plugins[plugin_symbol] = {source: path, require_stanza: req}
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_lookup_folder(folder)
|
40
|
+
@lookup_folders.unshift(folder)
|
41
|
+
end
|
42
|
+
|
43
|
+
# find plugins in defined paths
|
44
|
+
def add_plugins_from_lookup_folders
|
45
|
+
@lookup_folders.each do |folder|
|
46
|
+
next unless File.directory?(folder)
|
47
|
+
# TODO: add gem root to load path ? and require short folder ?
|
48
|
+
# $LOAD_PATH.push(folder) if i[:add_path]
|
49
|
+
Dir.entries(folder).select{|file|file.end_with?(RUBY_FILE_EXT)}.each do |source|
|
50
|
+
add_plugin_info(File.join(folder, source))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def create(plugin_name_sym, **args)
|
56
|
+
# TODO: check that ancestor is Plugin?
|
57
|
+
self.class.plugin_class(plugin_name_sym).new(**args)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'aspera/aoc'
|
3
|
+
require 'aspera/api/aoc'
|
4
4
|
|
5
5
|
module Aspera
|
6
6
|
module Cli
|
7
7
|
module Plugins
|
8
|
-
class Alee <
|
8
|
+
class Alee < Cli::BasicAuthPlugin
|
9
9
|
ACTIONS = %i[entitlement].freeze
|
10
10
|
|
11
11
|
def execute_action
|
@@ -14,11 +14,11 @@ module Aspera
|
|
14
14
|
when :entitlement
|
15
15
|
entitlement_id = options.get_option(:username, mandatory: true)
|
16
16
|
customer_id = options.get_option(:password, mandatory: true)
|
17
|
-
api_metering = AoC.metering_api(entitlement_id, customer_id)
|
17
|
+
api_metering = Api::AoC.metering_api(entitlement_id, customer_id)
|
18
18
|
return {type: :single_object, data: api_metering.read('entitlement')[:data]}
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -4,10 +4,10 @@ require 'aspera/cli/plugins/node'
|
|
4
4
|
require 'aspera/cli/plugins/ats'
|
5
5
|
require 'aspera/cli/basic_auth_plugin'
|
6
6
|
require 'aspera/cli/transfer_agent'
|
7
|
-
require 'aspera/
|
8
|
-
require 'aspera/
|
9
|
-
require 'aspera/aoc'
|
10
|
-
require 'aspera/node'
|
7
|
+
require 'aspera/agent/node'
|
8
|
+
require 'aspera/transfer/spec'
|
9
|
+
require 'aspera/api/aoc'
|
10
|
+
require 'aspera/api/node'
|
11
11
|
require 'aspera/persistency_action_once'
|
12
12
|
require 'aspera/id_generator'
|
13
13
|
require 'aspera/assert'
|
@@ -17,11 +17,13 @@ require 'date'
|
|
17
17
|
module Aspera
|
18
18
|
module Cli
|
19
19
|
module Plugins
|
20
|
-
class Aoc <
|
20
|
+
class Aoc < Cli::BasicAuthPlugin
|
21
21
|
AOC_PATH_API_CLIENTS = 'admin/api-clients'
|
22
22
|
# default redirect for AoC web auth
|
23
|
-
|
24
|
-
|
23
|
+
REDIRECT_LOCALHOST = 'http://localhost:12345'
|
24
|
+
# OAuth methods supported
|
25
|
+
STD_AUTH_TYPES = %i[web jwt].freeze
|
26
|
+
private_constant :AOC_PATH_API_CLIENTS, :REDIRECT_LOCALHOST, :STD_AUTH_TYPES
|
25
27
|
class << self
|
26
28
|
def application_name
|
27
29
|
'Aspera on Cloud'
|
@@ -31,13 +33,13 @@ module Aspera
|
|
31
33
|
# no protocol ?
|
32
34
|
base_url = "https://#{base_url}" unless base_url.match?(%r{^[a-z]{1,6}://})
|
33
35
|
# only org provided ?
|
34
|
-
base_url = "#{base_url}.#{
|
36
|
+
base_url = "#{base_url}.#{Api::AoC::PROD_DOMAIN}" unless base_url.include?('.')
|
35
37
|
# AoC is only https
|
36
38
|
return nil unless base_url.start_with?('https://')
|
37
|
-
result = Rest.new(
|
39
|
+
result = Rest.new(base_url: base_url, redirect_max: 10).read('')
|
38
40
|
# Any AoC is on this domain
|
39
|
-
return nil unless result[:http].uri.host.end_with?(
|
40
|
-
Log.log.debug{
|
41
|
+
return nil unless result[:http].uri.host.end_with?(Api::AoC::PROD_DOMAIN)
|
42
|
+
Log.log.debug{"AoC Main page: #{result[:http].body.include?(Api::AoC::PRODUCT_NAME)}"}
|
41
43
|
base_url = result[:http].uri.to_s if result[:http].uri.path.include?('/public')
|
42
44
|
# either in standard domain, or product name in page
|
43
45
|
return {
|
@@ -48,7 +50,7 @@ module Aspera
|
|
48
50
|
|
49
51
|
def private_key_required?(url)
|
50
52
|
# pub link do not need private key
|
51
|
-
return AoC.link_info(url)[:token].nil?
|
53
|
+
return Api::AoC.link_info(url)[:token].nil?
|
52
54
|
end
|
53
55
|
|
54
56
|
# @param [Hash] env : options, formatter
|
@@ -61,9 +63,9 @@ module Aspera
|
|
61
63
|
options.declare(:use_generic_client, 'Wizard: AoC: use global or org specific jwt client id', values: :bool, default: true)
|
62
64
|
options.parse_options!
|
63
65
|
instance_url = options.get_option(:url, mandatory: true)
|
64
|
-
pub_link_info = AoC.link_info(instance_url)
|
66
|
+
pub_link_info = Api::AoC.link_info(instance_url)
|
65
67
|
if !pub_link_info[:token].nil?
|
66
|
-
pub_api = Rest.new(
|
68
|
+
pub_api = Rest.new(base_url: "https://#{URI.parse(pub_link_info[:url]).host}/api/v1")
|
67
69
|
pub_info = pub_api.read('env/url_token_check', {token: pub_link_info[:token]})[:data]
|
68
70
|
preset_value = {
|
69
71
|
link: instance_url
|
@@ -100,7 +102,7 @@ module Aspera
|
|
100
102
|
formatter.display_status('Navigate to: 𓃑 → Admin → Integrations → API Clients')
|
101
103
|
formatter.display_status('Check or create in integration:')
|
102
104
|
formatter.display_status("- name: #{@info[:name]}")
|
103
|
-
formatter.display_status("- redirect uri: #{
|
105
|
+
formatter.display_status("- redirect uri: #{REDIRECT_LOCALHOST}")
|
104
106
|
formatter.display_status('- origin: localhost')
|
105
107
|
formatter.display_status('Use the generated client id and secret in the following prompts.'.red)
|
106
108
|
end
|
@@ -113,13 +115,14 @@ module Aspera
|
|
113
115
|
formatter.display_status('We will use web authentication to bootstrap.')
|
114
116
|
auto_set_pub_key = true
|
115
117
|
auto_set_jwt = true
|
116
|
-
|
117
|
-
aoc_api.oauth.
|
118
|
-
aoc_api.oauth.
|
118
|
+
raise 'TODO'
|
119
|
+
# aoc_api.oauth.grant_method = :web
|
120
|
+
# aoc_api.oauth.scope = Api::AoC::SCOPE_FILES_ADMIN
|
121
|
+
# aoc_api.oauth.specific_parameters[:redirect_uri] = REDIRECT_LOCALHOST
|
119
122
|
end
|
120
123
|
myself = object.aoc_api.read('self')[:data]
|
121
124
|
if auto_set_pub_key
|
122
|
-
assert(myself['public_key'].empty?, exception_class: Cli::Error){'Public key is already set in profile (use --override=yes)'} unless option_override
|
125
|
+
Aspera.assert(myself['public_key'].empty?, exception_class: Cli::Error){'Public key is already set in profile (use --override=yes)'} unless option_override
|
123
126
|
formatter.display_status('Updating profile with the public key.')
|
124
127
|
aoc_api.update("users/#{myself['id']}", {'public_key' => pub_key_pem})
|
125
128
|
end
|
@@ -172,19 +175,19 @@ module Aspera
|
|
172
175
|
'received' => true,
|
173
176
|
'completed' => true}.freeze
|
174
177
|
|
175
|
-
def initialize(env)
|
176
|
-
super
|
178
|
+
def initialize(**env)
|
179
|
+
super
|
177
180
|
@cache_workspace_info = nil
|
178
181
|
@cache_home_node_file = nil
|
179
182
|
@cache_api_aoc = nil
|
180
|
-
options.declare(:auth, 'OAuth type of authentication', values:
|
183
|
+
options.declare(:auth, 'OAuth type of authentication', values: STD_AUTH_TYPES, default: :jwt)
|
181
184
|
options.declare(:client_id, 'OAuth API client identifier')
|
182
185
|
options.declare(:client_secret, 'OAuth API client secret')
|
183
|
-
options.declare(:scope, 'OAuth scope for AoC API calls', default: AoC::SCOPE_FILES_USER)
|
186
|
+
options.declare(:scope, 'OAuth scope for AoC API calls', default: Api::AoC::SCOPE_FILES_USER)
|
184
187
|
options.declare(:redirect_uri, 'OAuth API client redirect URI')
|
185
188
|
options.declare(:private_key, 'OAuth JWT RSA private key PEM value (prefix file path with @file:)')
|
186
189
|
options.declare(:passphrase, 'RSA private key passphrase')
|
187
|
-
options.declare(:workspace, 'Name of workspace', types: [String, NilClass], default:
|
190
|
+
options.declare(:workspace, 'Name of workspace', types: [String, NilClass], default: Api::AoC::DEFAULT_WORKSPACE)
|
188
191
|
options.declare(:new_user_option, 'New user creation option for unknown package recipients')
|
189
192
|
options.declare(:validate_metadata, 'Validate shared inbox metadata', values: :bool, default: true)
|
190
193
|
options.parse_options!
|
@@ -195,9 +198,9 @@ module Aspera
|
|
195
198
|
OPTIONS_NEW = %i[url auth client_id client_secret scope redirect_uri private_key passphrase username password workspace].freeze
|
196
199
|
|
197
200
|
def api_from_options(new_base_path)
|
198
|
-
create_values = {subpath: new_base_path, secret_finder:
|
201
|
+
create_values = {subpath: new_base_path, secret_finder: config}
|
199
202
|
# create an API object with the same options, but with a different subpath
|
200
|
-
return
|
203
|
+
return Api::AoC.new(**OPTIONS_NEW.each_with_object(create_values) { |i, m|m[i] = options.get_option(i) unless options.get_option(i).nil?})
|
201
204
|
rescue ArgumentError => e
|
202
205
|
if (m = e.message.match(/missing keyword: :(.*)$/))
|
203
206
|
raise Cli::Error, "Missing option: #{m[1]}"
|
@@ -206,7 +209,14 @@ module Aspera
|
|
206
209
|
end
|
207
210
|
|
208
211
|
def aoc_api
|
209
|
-
|
212
|
+
if @cache_api_aoc.nil?
|
213
|
+
@cache_api_aoc = api_from_options(Api::AoC::API_V1)
|
214
|
+
organization = @cache_api_aoc.read('organization')[:data]
|
215
|
+
if organization['http_gateway_enabled'] && organization['http_gateway_server_url']
|
216
|
+
transfer.httpgw_url_cb = lambda { organization['http_gateway_server_url'] }
|
217
|
+
# @cache_api_aoc.current_user_info['connect_disabled']
|
218
|
+
end
|
219
|
+
end
|
210
220
|
return @cache_api_aoc
|
211
221
|
end
|
212
222
|
|
@@ -214,7 +224,7 @@ module Aspera
|
|
214
224
|
# @return identifier
|
215
225
|
def get_resource_id_from_args(resource_class_path)
|
216
226
|
return instance_identifier do |field, value|
|
217
|
-
assert(field.eql?('name'), exception_class: Cli::BadArgument){'only selection by name is supported'}
|
227
|
+
Aspera.assert(field.eql?('name'), exception_class: Cli::BadArgument){'only selection by name is supported'}
|
218
228
|
aoc_api.lookup_by_name(resource_class_path, value)['id']
|
219
229
|
end
|
220
230
|
end
|
@@ -226,8 +236,8 @@ module Aspera
|
|
226
236
|
# Call block with same query using paging and response information
|
227
237
|
# @return [Hash] {data: , total: }
|
228
238
|
def api_call_paging(base_query={})
|
229
|
-
assert_type(base_query, Hash){'query'}
|
230
|
-
assert(block_given?)
|
239
|
+
Aspera.assert_type(base_query, Hash){'query'}
|
240
|
+
Aspera.assert(block_given?)
|
231
241
|
# set default large page if user does not specify own parameters. AoC Caps to 1000 anyway
|
232
242
|
base_query['per_page'] = 1000 unless base_query.key?('per_page')
|
233
243
|
max_items = base_query.delete(MAX_ITEMS)
|
@@ -265,8 +275,8 @@ module Aspera
|
|
265
275
|
|
266
276
|
# list all entities, given additional, default and user's queries
|
267
277
|
def result_list(resource_class_path, fields: nil, base_query: {}, default_query: {})
|
268
|
-
assert_type(base_query, Hash)
|
269
|
-
assert_type(default_query, Hash)
|
278
|
+
Aspera.assert_type(base_query, Hash)
|
279
|
+
Aspera.assert_type(default_query, Hash)
|
270
280
|
user_query = query_read_delete(default: default_query)
|
271
281
|
# caller may add specific modifications or checks
|
272
282
|
yield(user_query) if block_given?
|
@@ -277,11 +287,13 @@ module Aspera
|
|
277
287
|
if query.key?('dropbox_name')
|
278
288
|
# convenience: specify name instead of id
|
279
289
|
raise 'not both dropbox_name and dropbox_id' if query.key?('dropbox_id')
|
290
|
+
# TODO : craft a query that looks for dropbox only in current workspace
|
280
291
|
query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query['dropbox_name'])['id']
|
281
292
|
query.delete('dropbox_name')
|
282
293
|
end
|
283
294
|
query['workspace_id'] ||= aoc_api.context[:workspace_id] unless aoc_api.context[:workspace_id].eql?(:undefined)
|
284
|
-
|
295
|
+
# by default show dropbox packages only for dropboxes
|
296
|
+
query['exclude_dropbox_packages'] = !query.key?('dropbox_id') unless query.key?('exclude_dropbox_packages')
|
285
297
|
end
|
286
298
|
|
287
299
|
NODE4_EXT_COMMANDS = %i[transfer].concat(Node::COMMANDS_GEN4).freeze
|
@@ -297,7 +309,7 @@ module Aspera
|
|
297
309
|
scope: scope
|
298
310
|
)
|
299
311
|
file_id = top_node_api.read("access_keys/#{top_node_api.app_info[:node_info]['access_key']}")[:data]['root_file_id'] if file_id.nil?
|
300
|
-
node_plugin = Node.new(
|
312
|
+
node_plugin = Node.new(**init_params, api: top_node_api)
|
301
313
|
case command_repo
|
302
314
|
when *Node::COMMANDS_GEN4
|
303
315
|
return node_plugin.execute_command_gen4(command_repo, file_id)
|
@@ -309,20 +321,20 @@ module Aspera
|
|
309
321
|
source_folder = options.get_next_argument('folder of source files', type: String)
|
310
322
|
case push_pull
|
311
323
|
when :push
|
312
|
-
client_direction =
|
324
|
+
client_direction = Transfer::Spec::DIRECTION_SEND
|
313
325
|
client_folder = source_folder
|
314
326
|
server_folder = transfer.destination_folder(client_direction)
|
315
327
|
when :pull
|
316
|
-
client_direction =
|
328
|
+
client_direction = Transfer::Spec::DIRECTION_RECEIVE
|
317
329
|
client_folder = transfer.destination_folder(client_direction)
|
318
330
|
server_folder = source_folder
|
319
|
-
else error_unreachable_line
|
331
|
+
else Aspera.error_unreachable_line
|
320
332
|
end
|
321
333
|
client_apfid = top_node_api.resolve_api_fid(file_id, client_folder)
|
322
334
|
server_apfid = top_node_api.resolve_api_fid(file_id, server_folder)
|
323
335
|
# force node as transfer agent
|
324
|
-
|
325
|
-
url: client_apfid[:api].
|
336
|
+
transfer.agent_instance = Agent::Node.new({
|
337
|
+
url: client_apfid[:api].base_url,
|
326
338
|
username: client_apfid[:api].app_info[:node_info]['access_key'],
|
327
339
|
password: client_apfid[:api].oauth_token,
|
328
340
|
root_id: client_apfid[:file_id]
|
@@ -337,14 +349,14 @@ module Aspera
|
|
337
349
|
server_apfid[:file_id],
|
338
350
|
client_direction,
|
339
351
|
add_ts)))
|
340
|
-
else error_unreachable_line
|
352
|
+
else Aspera.error_unreachable_line
|
341
353
|
end # command_repo
|
342
|
-
error_unreachable_line
|
354
|
+
Aspera.error_unreachable_line
|
343
355
|
end # execute_nodegen4_command
|
344
356
|
|
345
357
|
def execute_admin_action
|
346
358
|
# upgrade scope to admin
|
347
|
-
aoc_api.oauth.
|
359
|
+
aoc_api.oauth.scope = Api::AoC::SCOPE_FILES_ADMIN
|
348
360
|
command_admin = options.get_next_command(%i[ats resource usage_reports analytics subscription auth_providers])
|
349
361
|
case command_admin
|
350
362
|
when :auth_providers
|
@@ -411,15 +423,15 @@ module Aspera
|
|
411
423
|
result = bss_api.create('graphql', {'variables' => {'organization_id' => org['id']}, 'query' => graphql_query})[:data]['data']
|
412
424
|
return {type: :single_object, data: result['aoc']['bssSubscription']}
|
413
425
|
when :ats
|
414
|
-
ats_api = Rest.new(aoc_api.params.deep_merge({
|
415
|
-
base_url: "#{aoc_api.
|
416
|
-
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
426
|
+
ats_api = Rest.new(**aoc_api.params.deep_merge({
|
427
|
+
base_url: "#{aoc_api.base_url}/admin/ats/pub/v1",
|
428
|
+
auth: {scope: Api::AoC::SCOPE_FILES_ADMIN_USER}
|
417
429
|
}))
|
418
|
-
return Ats.new(
|
430
|
+
return Ats.new(**init_params).execute_action_gen(ats_api)
|
419
431
|
when :analytics
|
420
|
-
analytics_api = Rest.new(aoc_api.params.deep_merge({
|
421
|
-
base_url: "#{aoc_api.
|
422
|
-
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
432
|
+
analytics_api = Rest.new(**aoc_api.params.deep_merge({
|
433
|
+
base_url: "#{aoc_api.base_url.gsub('/api/v1', '')}/analytics/v2",
|
434
|
+
auth: {scope: Api::AoC::SCOPE_FILES_ADMIN_USER}
|
423
435
|
}))
|
424
436
|
command_analytics = options.get_next_command(%i[application_events transfers])
|
425
437
|
case command_analytics
|
@@ -435,14 +447,14 @@ module Aspera
|
|
435
447
|
when :organizations then aoc_api.current_user_info['organization_id']
|
436
448
|
when :users then aoc_api.current_user_info['id']
|
437
449
|
when :nodes then aoc_api.current_user_info['id'] # TODO: consistent ? # rubocop:disable Lint/DuplicateBranch
|
438
|
-
else error_unreachable_line
|
450
|
+
else Aspera.error_unreachable_line
|
439
451
|
end
|
440
452
|
filter = options.get_option(:query) || {}
|
441
453
|
filter['limit'] ||= 100
|
442
454
|
if options.get_option(:once_only, mandatory: true)
|
443
455
|
saved_date = []
|
444
456
|
start_date_persistency = PersistencyActionOnce.new(
|
445
|
-
manager:
|
457
|
+
manager: persistency,
|
446
458
|
data: saved_date,
|
447
459
|
id: IdGenerator.from_list([
|
448
460
|
'aoc_ana_date',
|
@@ -549,7 +561,7 @@ module Aspera
|
|
549
561
|
# init context
|
550
562
|
aoc_api.context(:files)
|
551
563
|
return execute_nodegen4_command(command_repo, res_id)
|
552
|
-
else error_unexpected_value(command)
|
564
|
+
else Aspera.error_unexpected_value(command)
|
553
565
|
end
|
554
566
|
when :usage_reports
|
555
567
|
return result_list('usage_reports', base_query: {workspace_id: aoc_api.context(:files)[:workspace_id]})
|
@@ -574,10 +586,10 @@ module Aspera
|
|
574
586
|
when :reminder
|
575
587
|
# send an email reminder with list of orgs
|
576
588
|
user_email = options.get_option(:username, mandatory: true)
|
577
|
-
Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").create('organization_reminders', {email: user_email})[:data]
|
589
|
+
Rest.new(base_url: "#{Api::AoC.api_base_url}/#{Api::AoC::API_V1}").create('organization_reminders', {email: user_email})[:data]
|
578
590
|
return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
|
579
591
|
when :servers
|
580
|
-
return {type: :object_list, data: Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
|
592
|
+
return {type: :object_list, data: Rest.new(base_url: "#{Api::AoC.api_base_url}/#{Api::AoC::API_V1}").read('servers')[:data]}
|
581
593
|
when :bearer_token
|
582
594
|
return {type: :text, data: aoc_api.oauth_token}
|
583
595
|
when :organization
|
@@ -659,7 +671,7 @@ module Aspera
|
|
659
671
|
if options.get_option(:once_only, mandatory: true)
|
660
672
|
# TODO: add query info to id
|
661
673
|
skip_ids_persistency = PersistencyActionOnce.new(
|
662
|
-
manager:
|
674
|
+
manager: persistency,
|
663
675
|
data: skip_ids_data,
|
664
676
|
id: IdGenerator.from_list(
|
665
677
|
['aoc_recv',
|
@@ -670,12 +682,12 @@ module Aspera
|
|
670
682
|
case ids_to_download
|
671
683
|
when ExtendedValue::ALL, ExtendedValue::INIT
|
672
684
|
query = query_read_delete(default: PACKAGE_RECEIVED_BASE_QUERY)
|
673
|
-
assert_type(query, Hash){'query'}
|
685
|
+
Aspera.assert_type(query, Hash){'query'}
|
674
686
|
resolve_dropbox_name_default_ws_id(query)
|
675
687
|
# remove from list the ones already downloaded
|
676
688
|
all_ids = api_read_all('packages', query)[:data].map{|e|e['id']}
|
677
689
|
if ids_to_download.eql?(ExtendedValue::INIT)
|
678
|
-
assert(skip_ids_persistency){'Only with option once_only'}
|
690
|
+
Aspera.assert(skip_ids_persistency){'Only with option once_only'}
|
679
691
|
skip_ids_persistency.data.clear.concat(all_ids)
|
680
692
|
skip_ids_persistency.save
|
681
693
|
return Main.result_status("Initialized skip for #{skip_ids_persistency.data.count} package(s)")
|
@@ -690,7 +702,7 @@ module Aspera
|
|
690
702
|
formatter.display_status("found #{ids_to_download.length} package(s).")
|
691
703
|
ids_to_download.each do |package_id|
|
692
704
|
package_info = aoc_api.read("packages/#{package_id}")[:data]
|
693
|
-
formatter.display_status("downloading package: #{package_info['name']}")
|
705
|
+
formatter.display_status("downloading package: [#{package_info['id']}] #{package_info['name']}")
|
694
706
|
package_node_api = aoc_api.node_api_from(
|
695
707
|
node_id: package_info['node_id'],
|
696
708
|
workspace_id: aoc_api.context[:workspace_id],
|
@@ -699,7 +711,7 @@ module Aspera
|
|
699
711
|
statuses = transfer.start(
|
700
712
|
package_node_api.transfer_spec_gen4(
|
701
713
|
package_info['contents_file_id'],
|
702
|
-
|
714
|
+
Transfer::Spec::DIRECTION_RECEIVE,
|
703
715
|
{'paths'=> [{'source' => '.'}]}),
|
704
716
|
rest_token: package_node_api)
|
705
717
|
result_transfer.push({'package' => package_id, Main::STATUS_FIELD => statuses})
|
@@ -722,19 +734,19 @@ module Aspera
|
|
722
734
|
end
|
723
735
|
when :delete
|
724
736
|
return do_bulk_operation(command: package_command, descr: 'identifier', values: identifier) do |id|
|
725
|
-
assert_values(id.class, [String, Integer]){'identifier'}
|
737
|
+
Aspera.assert_values(id.class, [String, Integer]){'identifier'}
|
726
738
|
aoc_api.delete("packages/#{id}")[:data]
|
727
739
|
end
|
728
740
|
when *Node::NODE4_READ_ACTIONS
|
729
741
|
package_id = instance_identifier
|
730
742
|
package_info = aoc_api.read("packages/#{package_id}")[:data]
|
731
|
-
return execute_nodegen4_command(package_command, package_info['node_id'], file_id: package_info['file_id'], scope:
|
743
|
+
return execute_nodegen4_command(package_command, package_info['node_id'], file_id: package_info['file_id'], scope: Api::Node::SCOPE_USER)
|
732
744
|
end
|
733
745
|
when :files
|
734
746
|
command_repo = options.get_next_command([:short_link].concat(NODE4_EXT_COMMANDS))
|
735
747
|
case command_repo
|
736
748
|
when *NODE4_EXT_COMMANDS
|
737
|
-
return execute_nodegen4_command(command_repo, aoc_api.context[:home_node_id], file_id: aoc_api.context[:home_file_id], scope:
|
749
|
+
return execute_nodegen4_command(command_repo, aoc_api.context[:home_node_id], file_id: aoc_api.context[:home_file_id], scope: Api::Node::SCOPE_USER)
|
738
750
|
when :short_link
|
739
751
|
link_type = options.get_next_argument('link type', expected: %i[public private])
|
740
752
|
short_link_command = options.get_next_command(%i[create delete list])
|
@@ -752,7 +764,7 @@ module Aspera
|
|
752
764
|
purpose = case link_type
|
753
765
|
when :public then 'token_auth_redirection'
|
754
766
|
when :private then 'shared_folder_auth_link'
|
755
|
-
else error_unreachable_line
|
767
|
+
else Aspera.error_unreachable_line
|
756
768
|
end
|
757
769
|
case short_link_command
|
758
770
|
when :delete
|
@@ -812,7 +824,7 @@ module Aspera
|
|
812
824
|
if link_type.eql?(:public)
|
813
825
|
# TODO: merge with node permissions ?
|
814
826
|
# TODO: access level as arg
|
815
|
-
access_levels =
|
827
|
+
access_levels = Api::Node::ACCESS_LEVELS # ['delete','list','mkdir','preview','read','rename','write']
|
816
828
|
folder_name = File.basename(folder_dest)
|
817
829
|
perm_data = {
|
818
830
|
'file_id' => shared_apfid[:file_id],
|
@@ -841,9 +853,7 @@ module Aspera
|
|
841
853
|
when :automation
|
842
854
|
Log.log.warn('BETA: work under progress')
|
843
855
|
# automation api is not in the same place
|
844
|
-
|
845
|
-
automation_rest_params[:base_url].gsub!('/api/', '/automation/')
|
846
|
-
automation_api = Rest.new(automation_rest_params)
|
856
|
+
automation_api = Rest.new(**aoc_api.params.merge(base_url: aoc_api.base_url.gsub('/api/', '/automation/')))
|
847
857
|
command_automation = options.get_next_command(%i[workflows instances])
|
848
858
|
case command_automation
|
849
859
|
when :instances
|
@@ -878,19 +888,15 @@ module Aspera
|
|
878
888
|
uri = URI.parse(url)
|
879
889
|
server = WebServerSimple.new(uri)
|
880
890
|
server.mount(uri.path, Faspex4GWServlet, aoc_api, aoc_api.context(:files)[:workspace_id])
|
881
|
-
trap('INT') { server.shutdown }
|
882
|
-
formatter.display_status("Faspex 4 gateway listening on #{url}")
|
883
|
-
Log.log.info("Listening on #{url}")
|
884
|
-
# this is blocking until server exits
|
885
891
|
server.start
|
886
892
|
return Main.result_status('Gateway terminated')
|
887
|
-
else error_unreachable_line
|
893
|
+
else Aspera.error_unreachable_line
|
888
894
|
end # action
|
889
|
-
error_unreachable_line
|
895
|
+
Aspera.error_unreachable_line
|
890
896
|
end
|
891
897
|
|
892
898
|
private :execute_admin_action
|
893
|
-
end
|
894
|
-
end
|
895
|
-
end
|
896
|
-
end
|
899
|
+
end
|
900
|
+
end
|
901
|
+
end
|
902
|
+
end
|