aspera-cli 4.7.0 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +1267 -999
  4. data/bin/ascli +20 -1
  5. data/bin/asession +37 -34
  6. data/docs/test_env.conf +7 -3
  7. data/examples/aoc.rb +13 -12
  8. data/examples/dascli +23 -0
  9. data/examples/faspex4.rb +34 -29
  10. data/examples/{transfer.rb → node.rb} +31 -59
  11. data/examples/server.rb +93 -0
  12. data/lib/aspera/aoc.rb +153 -143
  13. data/lib/aspera/ascmd.rb +56 -45
  14. data/lib/aspera/ats_api.rb +9 -6
  15. data/lib/aspera/cli/basic_auth_plugin.rb +18 -16
  16. data/lib/aspera/cli/extended_value.rb +33 -30
  17. data/lib/aspera/cli/formater.rb +105 -111
  18. data/lib/aspera/cli/info.rb +3 -2
  19. data/lib/aspera/cli/listener/line_dump.rb +1 -0
  20. data/lib/aspera/cli/listener/logger.rb +1 -0
  21. data/lib/aspera/cli/listener/progress.rb +13 -12
  22. data/lib/aspera/cli/listener/progress_multi.rb +21 -20
  23. data/lib/aspera/cli/main.rb +110 -90
  24. data/lib/aspera/cli/manager.rb +99 -88
  25. data/lib/aspera/cli/plugin.rb +98 -39
  26. data/lib/aspera/cli/plugins/alee.rb +6 -5
  27. data/lib/aspera/cli/plugins/aoc.rb +581 -450
  28. data/lib/aspera/cli/plugins/ats.rb +84 -83
  29. data/lib/aspera/cli/plugins/bss.rb +30 -27
  30. data/lib/aspera/cli/plugins/config.rb +488 -397
  31. data/lib/aspera/cli/plugins/console.rb +17 -15
  32. data/lib/aspera/cli/plugins/cos.rb +26 -35
  33. data/lib/aspera/cli/plugins/faspex.rb +206 -172
  34. data/lib/aspera/cli/plugins/faspex5.rb +109 -74
  35. data/lib/aspera/cli/plugins/node.rb +379 -189
  36. data/lib/aspera/cli/plugins/orchestrator.rb +71 -65
  37. data/lib/aspera/cli/plugins/preview.rb +131 -122
  38. data/lib/aspera/cli/plugins/server.rb +50 -150
  39. data/lib/aspera/cli/plugins/shares.rb +61 -27
  40. data/lib/aspera/cli/plugins/sync.rb +15 -14
  41. data/lib/aspera/cli/transfer_agent.rb +75 -64
  42. data/lib/aspera/cli/version.rb +2 -1
  43. data/lib/aspera/colors.rb +29 -28
  44. data/lib/aspera/command_line_builder.rb +50 -43
  45. data/lib/aspera/cos_node.rb +64 -38
  46. data/lib/aspera/data_repository.rb +1 -0
  47. data/lib/aspera/environment.rb +33 -10
  48. data/lib/aspera/fasp/agent_base.rb +35 -30
  49. data/lib/aspera/fasp/agent_connect.rb +35 -30
  50. data/lib/aspera/fasp/agent_direct.rb +68 -60
  51. data/lib/aspera/fasp/agent_httpgw.rb +71 -64
  52. data/lib/aspera/fasp/agent_node.rb +24 -23
  53. data/lib/aspera/fasp/agent_trsdk.rb +19 -20
  54. data/lib/aspera/fasp/error.rb +2 -1
  55. data/lib/aspera/fasp/error_info.rb +79 -68
  56. data/lib/aspera/fasp/installation.rb +130 -126
  57. data/lib/aspera/fasp/listener.rb +1 -0
  58. data/lib/aspera/fasp/parameters.rb +71 -60
  59. data/lib/aspera/fasp/parameters.yaml +69 -17
  60. data/lib/aspera/fasp/resume_policy.rb +14 -11
  61. data/lib/aspera/fasp/transfer_spec.rb +6 -5
  62. data/lib/aspera/fasp/uri.rb +25 -24
  63. data/lib/aspera/faspex_gw.rb +83 -72
  64. data/lib/aspera/hash_ext.rb +23 -13
  65. data/lib/aspera/id_generator.rb +16 -13
  66. data/lib/aspera/keychain/encrypted_hash.rb +61 -46
  67. data/lib/aspera/keychain/macos_security.rb +26 -24
  68. data/lib/aspera/log.rb +35 -39
  69. data/lib/aspera/nagios.rb +36 -28
  70. data/lib/aspera/node.rb +19 -19
  71. data/lib/aspera/oauth.rb +120 -100
  72. data/lib/aspera/open_application.rb +25 -22
  73. data/lib/aspera/persistency_action_once.rb +9 -8
  74. data/lib/aspera/persistency_folder.rb +13 -9
  75. data/lib/aspera/preview/file_types.rb +261 -266
  76. data/lib/aspera/preview/generator.rb +74 -73
  77. data/lib/aspera/preview/image_error.png +0 -0
  78. data/lib/aspera/preview/options.rb +7 -6
  79. data/lib/aspera/preview/utils.rb +30 -33
  80. data/lib/aspera/preview/video_error.png +0 -0
  81. data/lib/aspera/proxy_auto_config.rb +27 -23
  82. data/lib/aspera/rest.rb +73 -74
  83. data/lib/aspera/rest_call_error.rb +1 -0
  84. data/lib/aspera/rest_error_analyzer.rb +23 -19
  85. data/lib/aspera/rest_errors_aspera.rb +43 -40
  86. data/lib/aspera/secret_hider.rb +74 -0
  87. data/lib/aspera/ssh.rb +13 -10
  88. data/lib/aspera/sync.rb +49 -47
  89. data/lib/aspera/temp_file_manager.rb +7 -5
  90. data/lib/aspera/timer_limiter.rb +9 -8
  91. data/lib/aspera/uri_reader.rb +17 -18
  92. data/lib/aspera/web_auth.rb +17 -15
  93. data.tar.gz.sig +5 -0
  94. metadata +119 -35
  95. metadata.gz.sig +0 -0
  96. data/bin/dascli +0 -13
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'aspera/cli/basic_auth_plugin'
3
4
  require 'aspera/cli/extended_value'
4
5
  require 'aspera/cli/version'
6
+ require 'aspera/cli/formater'
5
7
  require 'aspera/fasp/installation'
6
8
  require 'aspera/fasp/parameters'
7
9
  require 'aspera/fasp/transfer_spec'
@@ -27,37 +29,37 @@ module Aspera
27
29
  # manage the CLI config file
28
30
  class Config < Plugin
29
31
  # folder in $HOME for application files (config, cache)
30
- ASPERA_HOME_FOLDER_NAME='.aspera'
32
+ ASPERA_HOME_FOLDER_NAME = '.aspera'
31
33
  # default config file
32
34
  DEFAULT_CONFIG_FILENAME = 'config.yaml'
33
35
  # reserved preset names
34
- CONF_PRESET_CONFIG='config'
35
- CONF_PRESET_VERSION='version'
36
- CONF_PRESET_DEFAULT='default'
37
- CONF_PRESET_GLOBAL='global_common_defaults'
38
- CONF_PRESET_SECRETS='default_secrets' # pragma: allowlist secret
36
+ CONF_PRESET_CONFIG = 'config'
37
+ CONF_PRESET_VERSION = 'version'
38
+ CONF_PRESET_DEFAULT = 'default'
39
+ CONF_PRESET_GLOBAL = 'global_common_defaults'
40
+ CONF_PRESET_SECRETS = 'default_secrets' # pragma: allowlist secret
39
41
  CONF_PLUGIN_SYM = :config # Plugins::Config.name.split('::').last.downcase.to_sym
40
42
  CONF_GLOBAL_SYM = :config
41
43
  # old tool name
42
44
  PROGRAM_NAME_V1 = 'aslmcli'
43
45
  PROGRAM_NAME_V2 = 'mlia'
44
46
  # default redirect for AoC web auth
45
- DEFAULT_REDIRECT='http://localhost:12345'
47
+ DEFAULT_REDIRECT = 'http://localhost:12345'
46
48
  # folder containing custom plugins in user's config folder
47
- ASPERA_PLUGINS_FOLDERNAME='plugins'
48
- RUBY_FILE_EXT='.rb'
49
- AOC_COMMAND_V1='files'
50
- AOC_COMMAND_V2='aspera'
51
- AOC_COMMAND_V3='aoc'
52
- AOC_COMMAND_CURRENT=AOC_COMMAND_V3
53
- SERVER_COMMAND='server'
49
+ ASPERA_PLUGINS_FOLDERNAME = 'plugins'
50
+ RUBY_FILE_EXT = '.rb'
51
+ AOC_COMMAND_V1 = 'files'
52
+ AOC_COMMAND_V2 = 'aspera'
53
+ AOC_COMMAND_V3 = 'aoc'
54
+ AOC_COMMAND_CURRENT = AOC_COMMAND_V3
55
+ SERVER_COMMAND = 'server'
54
56
  CONNECT_WEB_URL = 'https://d3gcli72yxqn2z.cloudfront.net/connect'
55
57
  CONNECT_VERSIONS = 'connectversions.js'
56
58
  TRANSFER_SDK_ARCHIVE_URL = 'https://ibm.biz/aspera_transfer_sdk'
57
- DEMO='demo'
58
- DEMO_SERVER_PRESET='demoserver'
59
- AOC_PATH_API_CLIENTS='admin/api-clients'
60
- EMAIL_TEST_TEMPLATE=<<~END_OF_TEMPLATE
59
+ DEMO = 'demo'
60
+ DEMO_SERVER_PRESET = 'demoserver'
61
+ AOC_PATH_API_CLIENTS = 'admin/api-clients'
62
+ EMAIL_TEST_TEMPLATE = <<~END_OF_TEMPLATE
61
63
  From: <%=from_name%> <<%=from_email%>>
62
64
  To: <<%=to%>>
63
65
  Subject: Amelia email test
@@ -65,33 +67,33 @@ module Aspera
65
67
  It worked !
66
68
  END_OF_TEMPLATE
67
69
  # special extended values
68
- EXTV_INCLUDE_PRESETS=:incps
69
- EXTV_PRESET=:preset
70
- PRESET_DIG_SEPARATOR='.'
71
- DEFAULT_CHECK_NEW_VERSION_DAYS=7
72
- DEFAULT_PRIV_KEY_FILENAME='aspera_aoc_key' # pragma: allowlist secret
73
- DEFAULT_PRIVKEY_LENGTH=4096
70
+ EXTV_INCLUDE_PRESETS = :incps
71
+ EXTV_PRESET = :preset
72
+ PRESET_DIG_SEPARATOR = '.'
73
+ DEFAULT_CHECK_NEW_VERSION_DAYS = 7
74
+ DEFAULT_PRIV_KEY_FILENAME = 'aspera_aoc_key' # pragma: allowlist secret
75
+ DEFAULT_PRIVKEY_LENGTH = 4096
74
76
  private_constant :DEFAULT_CONFIG_FILENAME,:CONF_PRESET_CONFIG,:CONF_PRESET_VERSION,:CONF_PRESET_DEFAULT,
75
- :CONF_PRESET_GLOBAL,:PROGRAM_NAME_V1,:PROGRAM_NAME_V2,:DEFAULT_REDIRECT,:ASPERA_PLUGINS_FOLDERNAME,
76
- :RUBY_FILE_EXT,:AOC_COMMAND_V1,:AOC_COMMAND_V2,:AOC_COMMAND_V3,:AOC_COMMAND_CURRENT,:DEMO,
77
- :TRANSFER_SDK_ARCHIVE_URL,:AOC_PATH_API_CLIENTS,:DEMO_SERVER_PRESET,:EMAIL_TEST_TEMPLATE,:EXTV_INCLUDE_PRESETS,
78
- :EXTV_PRESET,:DEFAULT_CHECK_NEW_VERSION_DAYS,:DEFAULT_PRIV_KEY_FILENAME,:SERVER_COMMAND,:CONF_PRESET_SECRETS,
79
- :PRESET_DIG_SEPARATOR
77
+ :CONF_PRESET_GLOBAL,:PROGRAM_NAME_V1,:PROGRAM_NAME_V2,:DEFAULT_REDIRECT,:ASPERA_PLUGINS_FOLDERNAME,
78
+ :RUBY_FILE_EXT,:AOC_COMMAND_V1,:AOC_COMMAND_V2,:AOC_COMMAND_V3,:AOC_COMMAND_CURRENT,:DEMO,
79
+ :TRANSFER_SDK_ARCHIVE_URL,:AOC_PATH_API_CLIENTS,:DEMO_SERVER_PRESET,:EMAIL_TEST_TEMPLATE,:EXTV_INCLUDE_PRESETS,
80
+ :EXTV_PRESET,:DEFAULT_CHECK_NEW_VERSION_DAYS,:DEFAULT_PRIV_KEY_FILENAME,:SERVER_COMMAND,:CONF_PRESET_SECRETS,
81
+ :PRESET_DIG_SEPARATOR
80
82
  def initialize(env,params)
81
83
  raise 'env and params must be Hash' unless env.is_a?(Hash) && params.is_a?(Hash)
82
- raise 'missing param' unless [:name,:help,:version,:gem].sort.eql?(params.keys.sort)
84
+ raise 'missing param' unless %i[name help version gem].sort.eql?(params.keys.sort)
83
85
  super(env)
84
- @info=params
85
- @main_folder=default_app_main_folder
86
- @plugins={}
87
- @plugin_lookup_folders=[]
88
- @use_plugin_defaults=true
89
- @config_presets=nil
90
- @connect_versions=nil
91
- @vault=nil
92
- @conf_file_default=File.join(@main_folder,DEFAULT_CONFIG_FILENAME)
93
- @option_config_file=@conf_file_default
94
- @pac_exec=nil
86
+ @info = params
87
+ @main_folder = default_app_main_folder
88
+ @plugins = {}
89
+ @plugin_lookup_folders = []
90
+ @use_plugin_defaults = true
91
+ @config_presets = nil
92
+ @connect_versions = nil
93
+ @vault = nil
94
+ @conf_file_default = File.join(@main_folder,DEFAULT_CONFIG_FILENAME)
95
+ @option_config_file = @conf_file_default
96
+ @pac_exec = nil
95
97
  Log.log.debug("#{@info[:name]} folder: #{@main_folder}")
96
98
  # set folder for FASP SDK
97
99
  add_plugin_lookup_folder(self.class.gem_plugins_folder)
@@ -113,7 +115,7 @@ module Aspera
113
115
  options.set_obj_attr(:use_product,self,:option_use_product)
114
116
  options.set_obj_attr(:preset,self,:option_preset)
115
117
  options.set_obj_attr(:plugin_folder,self,:option_plugin_folder)
116
- options.add_opt_switch(:no_default,'-N','do not load default configuration for plugin') { @use_plugin_defaults=false }
118
+ options.add_opt_switch(:no_default,'-N','do not load default configuration for plugin') { @use_plugin_defaults = false }
117
119
  options.add_opt_boolean(:override,'Wizard: override existing value')
118
120
  options.add_opt_boolean(:use_generic_client,'Wizard: AoC: use global or org specific jwt client id')
119
121
  options.add_opt_boolean(:default,'Wizard: set as default configuration for specified plugin (also: update)')
@@ -140,9 +142,9 @@ module Aspera
140
142
  options.set_option(:sdk_folder,File.join(@main_folder,'sdk'))
141
143
  options.set_option(:override,:no)
142
144
  options.parse_options!
143
- pac_script=options.get_option(:fpac,:optional)
145
+ pac_script = options.get_option(:fpac)
144
146
  # create PAC executor
145
- @pac_exec=Aspera::ProxyAutoConfig.new(pac_script).register_uri_generic unless pac_script.nil?
147
+ @pac_exec = Aspera::ProxyAutoConfig.new(pac_script).register_uri_generic unless pac_script.nil?
146
148
  end
147
149
 
148
150
  # env var name to override the app's main folder
@@ -153,72 +155,81 @@ module Aspera
153
155
 
154
156
  def default_app_main_folder
155
157
  # find out application main folder
156
- app_folder=ENV[conf_dir_env_var]
158
+ app_folder = ENV[conf_dir_env_var]
157
159
  # if env var undefined or empty
158
160
  if app_folder.nil? || app_folder.empty?
159
- user_home_folder=Dir.home
161
+ user_home_folder = Dir.home
160
162
  raise CliError,"Home folder does not exist: #{user_home_folder}. Check your user environment or use #{conf_dir_env_var}." unless Dir.exist?(user_home_folder)
161
- app_folder=File.join(user_home_folder,ASPERA_HOME_FOLDER_NAME,@info[:name])
163
+ app_folder = File.join(user_home_folder,ASPERA_HOME_FOLDER_NAME,@info[:name])
162
164
  end
163
165
  return app_folder
164
166
  end
165
167
 
166
168
  def check_gem_version
167
- latest_version=begin
168
- Rest.new(base_url: 'https://rubygems.org/api/v1').read("versions/#{@info[:gem]}/latest.json")[:data]['version']
169
- rescue StandardError
170
- Log.log.warn('Could not retrieve latest gem version on rubygems.')
171
- '0'
172
- end
169
+ latest_version =
170
+ begin
171
+ Rest.new(base_url: 'https://rubygems.org/api/v1').read("versions/#{@info[:gem]}/latest.json")[:data]['version']
172
+ rescue StandardError
173
+ Log.log.warn('Could not retrieve latest gem version on rubygems.')
174
+ '0'
175
+ end
173
176
  if Gem::Version.new(Environment.ruby_version) < Gem::Version.new(RUBY_FUTURE_MINIMUM_VERSION)
174
- Log.log.warn("Note that a future version will require Ruby version #{RUBY_FUTURE_MINIMUM_VERSION} at minimum, you are using #{Environment.ruby_version}")
177
+ Log.log.warn("Note that a future version will require Ruby version #{RUBY_FUTURE_MINIMUM_VERSION} at minimum, "\
178
+ "you are using #{Environment.ruby_version}")
175
179
  end
176
- return {name: @info[:gem], current: Aspera::Cli::VERSION, latest: latest_version, need_update: Gem::Version.new(Aspera::Cli::VERSION) < Gem::Version.new(latest_version)}
180
+ return {
181
+ name: @info[:gem],
182
+ current: Aspera::Cli::VERSION,
183
+ latest: latest_version,
184
+ need_update: Gem::Version.new(Aspera::Cli::VERSION) < Gem::Version.new(latest_version)
185
+ }
177
186
  end
178
187
 
179
188
  def periodic_check_newer_gem_version
180
189
  # get verification period
181
- delay_days=options.get_option(:version_check_days,:mandatory)
190
+ delay_days = options.get_option(:version_check_days,is_type: :mandatory)
182
191
  Log.log.info("check days: #{delay_days}")
183
192
  # check only if not zero day
184
193
  return if delay_days.eql?(0)
185
194
  # get last date from persistency
186
- last_check_array=[]
187
- check_date_persist=PersistencyActionOnce.new(
188
- manager: persistency,
189
- data: last_check_array,
190
- id: 'version_last_check')
195
+ last_check_array = []
196
+ check_date_persist = PersistencyActionOnce.new(
197
+ manager: persistency,
198
+ data: last_check_array,
199
+ id: 'version_last_check')
191
200
  # get persisted date or nil
192
- current_date=Date.today
193
- last_check_days = begin
194
- current_date-Date.strptime(last_check_array.first, '%Y/%m/%d')
195
- rescue StandardError
196
- # negative value will force check
197
- -1
198
- end
201
+ current_date = Date.today
202
+ last_check_days =
203
+ begin
204
+ current_date - Date.strptime(last_check_array.first, '%Y/%m/%d')
205
+ rescue StandardError
206
+ # negative value will force check
207
+ -1
208
+ end
199
209
  Log.log.debug("days elapsed: #{last_check_days}")
200
210
  return if last_check_days < delay_days
201
211
  # generate timestamp
202
- last_check_array[0]=current_date.strftime('%Y/%m/%d')
212
+ last_check_array[0] = current_date.strftime('%Y/%m/%d')
203
213
  check_date_persist.save
204
214
  # compare this version and the one on internet
205
- check_data=check_gem_version
206
- Log.log.warn("A new version is available: #{check_data[:latest]}. You have #{check_data[:current]}. Upgrade with: gem update #{check_data[:name]}") if check_data[:need_update]
215
+ check_data = check_gem_version
216
+ Log.log.warn("A new version is available: #{check_data[:latest]}. "\
217
+ "You have #{check_data[:current]}. Upgrade with: gem update #{check_data[:name]}") if check_data[:need_update]
207
218
  end
208
219
 
209
220
  # retrieve structure from cloud (CDN) with all versions available
210
221
  def connect_versions
211
222
  if @connect_versions.nil?
212
- api_connect_cdn=Rest.new({base_url: CONNECT_WEB_URL})
213
- javascript=api_connect_cdn.call({operation: 'GET',subpath: CONNECT_VERSIONS})
223
+ api_connect_cdn = Rest.new({base_url: CONNECT_WEB_URL})
224
+ javascript = api_connect_cdn.call({operation: 'GET',subpath: CONNECT_VERSIONS})
214
225
  # get result on one line
215
- connect_versions_javascript=javascript[:http].body.gsub(/\r?\n\s*/,'')
226
+ connect_versions_javascript = javascript[:http].body.gsub(/\r?\n\s*/,'')
216
227
  Log.log.debug("javascript=[\n#{connect_versions_javascript}\n]")
217
228
  # get javascript object only
218
- found=connect_versions_javascript.match(/^.*? = (.*);/)
229
+ found = connect_versions_javascript.match(/^.*? = (.*);/)
219
230
  raise CliError,'Problen when getting connect versions from internet' if found.nil?
220
- alldata=JSON.parse(found[1])
221
- @connect_versions=alldata['entries']
231
+ alldata = JSON.parse(found[1])
232
+ @connect_versions = alldata['entries']
222
233
  end
223
234
  return @connect_versions
224
235
  end
@@ -228,9 +239,9 @@ module Aspera
228
239
  # try to find: conffile[conffile["default"][plugin_str]]
229
240
  # @param plugin_name_sym : symbol for plugin name
230
241
  def add_plugin_default_preset(plugin_name_sym)
231
- default_config_name=get_plugin_default_config_name(plugin_name_sym)
242
+ default_config_name = get_plugin_default_config_name(plugin_name_sym)
232
243
  Log.log.debug("add_plugin_default_preset:#{plugin_name_sym}:#{default_config_name}")
233
- options.add_option_preset(preset_by_name(default_config_name),:unshift) unless default_config_name.nil?
244
+ options.add_option_preset(preset_by_name(default_config_name),op: :unshift) unless default_config_name.nil?
234
245
  return nil
235
246
  end
236
247
 
@@ -240,7 +251,9 @@ module Aspera
240
251
  require 'openssl'
241
252
  priv_key = OpenSSL::PKey::RSA.new(length)
242
253
  File.write(private_key_path,priv_key.to_s)
243
- File.write(private_key_path+'.pub',priv_key.public_key.to_s)
254
+ File.chmod(0400,private_key_path)
255
+ File.write(private_key_path + '.pub',priv_key.public_key.to_s)
256
+ File.chmod(0400,private_key_path + '.pub')
244
257
  nil
245
258
  end
246
259
 
@@ -268,16 +281,6 @@ module Aspera
268
281
  # Module.nesting[2] is Aspera::Cli::Plugins
269
282
  return Object.const_get("#{module_full_name}::#{plugin_name_sym.to_s.capitalize}")
270
283
  end
271
-
272
- def flatten_all_config(t)
273
- r=[]
274
- t.each do |k,v|
275
- v.each do |kk,vv|
276
- r.push({'config'=>k,'parameter'=>kk,'value'=>vv})
277
- end
278
- end
279
- return r
280
- end
281
284
  end
282
285
 
283
286
  # set parameter and value in global config
@@ -285,14 +288,14 @@ module Aspera
285
288
  # @return preset name that contains global default
286
289
  def set_global_default(key,value)
287
290
  # get default preset if it exists
288
- global_default_preset_name=get_plugin_default_config_name(CONF_GLOBAL_SYM)
291
+ global_default_preset_name = get_plugin_default_config_name(CONF_GLOBAL_SYM)
289
292
  if global_default_preset_name.nil?
290
- global_default_preset_name=CONF_PRESET_GLOBAL
291
- @config_presets[CONF_PRESET_DEFAULT]||={}
292
- @config_presets[CONF_PRESET_DEFAULT][CONF_GLOBAL_SYM.to_s]=global_default_preset_name
293
+ global_default_preset_name = CONF_PRESET_GLOBAL
294
+ @config_presets[CONF_PRESET_DEFAULT] ||= {}
295
+ @config_presets[CONF_PRESET_DEFAULT][CONF_GLOBAL_SYM.to_s] = global_default_preset_name
293
296
  end
294
- @config_presets[global_default_preset_name]||={}
295
- @config_presets[global_default_preset_name][key.to_s]=value
297
+ @config_presets[global_default_preset_name] ||= {}
298
+ @config_presets[global_default_preset_name][key.to_s] = value
296
299
  self.format.display_status("Updated: #{global_default_preset_name}: #{key} <- #{value}")
297
300
  save_presets_to_config_file
298
301
  return global_default_preset_name
@@ -310,12 +313,12 @@ module Aspera
310
313
  # @param include_path used to detect and avoid include loops
311
314
  def preset_by_name(config_name, include_path=[])
312
315
  raise CliError,'loop in include' if include_path.include?(config_name)
313
- include_path=include_path.clone # avoid messing up if there are multiple branches
314
- current=@config_presets
316
+ include_path = include_path.clone # avoid messing up if there are multiple branches
317
+ current = @config_presets
315
318
  config_name.split(PRESET_DIG_SEPARATOR).each do |name|
316
319
  raise CliError,"not a Hash: #{include_path} (#{current.class})" unless current.is_a?(Hash)
317
320
  include_path.push(name)
318
- current=current[name]
321
+ current = current[name]
319
322
  raise CliError,"no such config preset: #{include_path}" if nil?
320
323
  end
321
324
  case current
@@ -331,10 +334,10 @@ module Aspera
331
334
  def expanded_with_preset_includes(hash_val, include_path=[])
332
335
  raise CliError,"#{EXTV_INCLUDE_PRESETS} requires a Hash, have #{hash_val.class}" unless hash_val.is_a?(Hash)
333
336
  if hash_val.has_key?(EXTV_INCLUDE_PRESETS)
334
- memory=hash_val.clone
335
- includes=memory[EXTV_INCLUDE_PRESETS]
337
+ memory = hash_val.clone
338
+ includes = memory[EXTV_INCLUDE_PRESETS]
336
339
  memory.delete(EXTV_INCLUDE_PRESETS)
337
- hash_val={}
340
+ hash_val = {}
338
341
  raise "#{EXTV_INCLUDE_PRESETS} must be an Array" unless includes.is_a?(Array)
339
342
  raise "#{EXTV_INCLUDE_PRESETS} must contain names" unless includes.map(&:class).uniq.eql?([String])
340
343
  includes.each do |preset_name|
@@ -379,13 +382,13 @@ module Aspera
379
382
  end
380
383
 
381
384
  def convert_preset_path(old_name,new_name,files_to_copy)
382
- old_subpath=File.join('',ASPERA_HOME_FOLDER_NAME,old_name,'')
383
- new_subpath=File.join('',ASPERA_HOME_FOLDER_NAME,new_name,'')
385
+ old_subpath = File.join('',ASPERA_HOME_FOLDER_NAME,old_name,'')
386
+ new_subpath = File.join('',ASPERA_HOME_FOLDER_NAME,new_name,'')
384
387
  # convert possible keys located in config folder
385
388
  @config_presets.values.select{|p|p.is_a?(Hash)}.each do |preset|
386
- preset.values.select{|v|v.is_a?(String) and v.include?(old_subpath)}.each do |value|
387
- old_val=value.clone
388
- included_path=File.expand_path(old_val.gsub(/^@file:/,''))
389
+ preset.values.select{|v|v.is_a?(String) && v.include?(old_subpath)}.each do |value|
390
+ old_val = value.clone
391
+ included_path = File.expand_path(old_val.gsub(/^@file:/,''))
389
392
  files_to_copy.push(included_path) unless files_to_copy.include?(included_path) || !File.exist?(included_path)
390
393
  value.gsub!(old_subpath,new_subpath)
391
394
  Log.log.warn("Converted config value: #{old_val} -> #{value}")
@@ -394,9 +397,9 @@ module Aspera
394
397
  end
395
398
 
396
399
  def convert_preset_plugin_name(old_name,new_name)
397
- default_preset=@config_presets[CONF_PRESET_DEFAULT]
400
+ default_preset = @config_presets[CONF_PRESET_DEFAULT]
398
401
  return unless default_preset.is_a?(Hash) && default_preset.has_key?(old_name)
399
- default_preset[new_name]=default_preset[old_name]
402
+ default_preset[new_name] = default_preset[old_name]
400
403
  default_preset.delete(old_name)
401
404
  Log.log.warn("Converted plugin default: #{old_name} -> #{new_name}")
402
405
  end
@@ -406,65 +409,65 @@ module Aspera
406
409
  def read_config_file
407
410
  begin
408
411
  Log.log.debug("config file is: #{@option_config_file}".red)
409
- conf_file_v1=File.join(Dir.home,ASPERA_HOME_FOLDER_NAME,PROGRAM_NAME_V1,DEFAULT_CONFIG_FILENAME)
410
- conf_file_v2=File.join(Dir.home,ASPERA_HOME_FOLDER_NAME,PROGRAM_NAME_V2,DEFAULT_CONFIG_FILENAME)
412
+ conf_file_v1 = File.join(Dir.home,ASPERA_HOME_FOLDER_NAME,PROGRAM_NAME_V1,DEFAULT_CONFIG_FILENAME)
413
+ conf_file_v2 = File.join(Dir.home,ASPERA_HOME_FOLDER_NAME,PROGRAM_NAME_V2,DEFAULT_CONFIG_FILENAME)
411
414
  # files search for configuration, by default the one given by user
412
- search_files=[@option_config_file]
415
+ search_files = [@option_config_file]
413
416
  # if default file, then also look for older versions
414
417
  search_files.push(conf_file_v2,conf_file_v1) if @option_config_file.eql?(@conf_file_default)
415
418
  # find first existing file (or nil)
416
- conf_file_to_load=search_files.select{|f| File.exist?(f)}.first
419
+ conf_file_to_load = search_files.find{|f| File.exist?(f)}
417
420
  # require save if old version of file
418
- save_required= !@option_config_file.eql?(conf_file_to_load)
421
+ save_required = !@option_config_file.eql?(conf_file_to_load)
419
422
  # if no file found, create default config
420
423
  if conf_file_to_load.nil?
421
424
  Log.log.warn("No config file found. Creating empty configuration file: #{@option_config_file}")
422
- @config_presets={CONF_PRESET_CONFIG=>{CONF_PRESET_VERSION=>@info[:version]}}
425
+ @config_presets = {CONF_PRESET_CONFIG => {CONF_PRESET_VERSION => @info[:version]}}
423
426
  else
424
427
  Log.log.debug("loading #{@option_config_file}")
425
- @config_presets=YAML.load_file(conf_file_to_load)
428
+ @config_presets = YAML.load_file(conf_file_to_load)
426
429
  end
427
- files_to_copy=[]
430
+ files_to_copy = []
428
431
  Log.log.debug("Available_presets: #{@config_presets}")
429
432
  raise 'Expecting YAML Hash' unless @config_presets.is_a?(Hash)
430
433
  # check there is at least the config section
431
434
  if !@config_presets.has_key?(CONF_PRESET_CONFIG)
432
435
  raise "Cannot find key: #{CONF_PRESET_CONFIG}"
433
436
  end
434
- version=@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]
437
+ version = @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]
435
438
  if version.nil?
436
439
  raise 'No version found in config section.'
437
440
  end
438
441
  # oldest compatible conf file format, update to latest version when an incompatible change is made
439
442
  # check compatibility of version of conf file
440
- config_tested_version='0.4.5'
443
+ config_tested_version = '0.4.5'
441
444
  if Gem::Version.new(version) < Gem::Version.new(config_tested_version)
442
445
  raise "Unsupported config file version #{version}. Expecting min version #{config_tested_version}"
443
446
  end
444
- config_tested_version='0.6.15'
447
+ config_tested_version = '0.6.15'
445
448
  if Gem::Version.new(version) < Gem::Version.new(config_tested_version)
446
449
  convert_preset_plugin_name(AOC_COMMAND_V1,AOC_COMMAND_V2)
447
- version=@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]=config_tested_version
448
- save_required=true
450
+ version = @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION] = config_tested_version
451
+ save_required = true
449
452
  end
450
- config_tested_version='0.8.10'
453
+ config_tested_version = '0.8.10'
451
454
  if Gem::Version.new(version) <= Gem::Version.new(config_tested_version)
452
455
  convert_preset_path(PROGRAM_NAME_V1,PROGRAM_NAME_V2,files_to_copy)
453
- version=@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]=config_tested_version
454
- save_required=true
456
+ version = @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION] = config_tested_version
457
+ save_required = true
455
458
  end
456
- config_tested_version='1.0'
459
+ config_tested_version = '1.0'
457
460
  if Gem::Version.new(version) <= Gem::Version.new(config_tested_version)
458
461
  convert_preset_plugin_name(AOC_COMMAND_V2,AOC_COMMAND_V3)
459
462
  convert_preset_path(PROGRAM_NAME_V2,@info[:name],files_to_copy)
460
- version=@config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]=config_tested_version
461
- save_required=true
463
+ version = @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION] = config_tested_version
464
+ save_required = true
462
465
  end
463
466
  Log.log.debug("conf version: #{version}")
464
467
  # Place new compatibility code here
465
468
  if save_required
466
469
  Log.log.warn('Saving automatic conversion.')
467
- @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION]=@info[:version]
470
+ @config_presets[CONF_PRESET_CONFIG][CONF_PRESET_VERSION] = @info[:version]
468
471
  save_presets_to_config_file
469
472
  Log.log.warn('Copying referenced files')
470
473
  files_to_copy.each do |file|
@@ -477,7 +480,7 @@ module Aspera
477
480
  raise e
478
481
  rescue StandardError => e
479
482
  Log.log.debug("-> #{e}")
480
- new_name="#{@option_config_file}.pre#{@info[:version]}.manual_conversion_needed"
483
+ new_name = "#{@option_config_file}.pre#{@info[:version]}.manual_conversion_needed"
481
484
  File.rename(@option_config_file,new_name)
482
485
  Log.log.warn("Renamed config file to #{new_name}.")
483
486
  Log.log.warn('Manual Conversion is required. Next time, a new empty file will be created.')
@@ -503,13 +506,13 @@ module Aspera
503
506
 
504
507
  def add_plugin_info(path)
505
508
  raise "ERROR: plugin path must end with #{RUBY_FILE_EXT}" if !path.end_with?(RUBY_FILE_EXT)
506
- plugin_symbol=File.basename(path,RUBY_FILE_EXT).to_sym
507
- req=path.gsub(/#{RUBY_FILE_EXT}$/,'')
509
+ plugin_symbol = File.basename(path,RUBY_FILE_EXT).to_sym
510
+ req = path.gsub(/#{RUBY_FILE_EXT}$/o,'')
508
511
  if @plugins.has_key?(plugin_symbol)
509
512
  Log.log.warn("skipping plugin already registered: #{plugin_symbol}")
510
513
  return
511
514
  end
512
- @plugins[plugin_symbol]={source: path,require_stanza: req}
515
+ @plugins[plugin_symbol] = {source: path,require_stanza: req}
513
516
  end
514
517
 
515
518
  def identify_plugin_for_url(url)
@@ -518,24 +521,27 @@ module Aspera
518
521
  next if plugin_name_sym.eql?(CONF_PLUGIN_SYM)
519
522
  # load plugin class
520
523
  require plugin_info[:require_stanza]
521
- c=self.class.plugin_class(plugin_name_sym)
524
+ c = self.class.plugin_class(plugin_name_sym)
522
525
  next unless c.respond_to?(:detect)
523
- current_url=url
524
- detection_info=nil
526
+ current_url = url
527
+ detection_info = nil
525
528
  # first try : direct
526
529
  begin
527
- detection_info=c.detect(current_url)
530
+ detection_info = c.detect(current_url)
531
+ rescue OpenSSL::SSL::SSLError => e
532
+ Log.log.warn(e.message)
533
+ Log.log.warn('Use option --insecure=yes to ignore certificate') if e.message.include?('cert')
528
534
  rescue StandardError => e
529
- Log.log.debug("Cannot detect #{plugin_name_sym} : #{e.message}")
535
+ Log.log.debug("Cannot detect #{plugin_name_sym} : #{e.class}/#{e.message}")
530
536
  end
531
537
  # second try : is there a redirect ?
532
538
  if detection_info.nil?
533
539
  begin
534
540
  # TODO: check if redirect ?
535
- new_url=Rest.new(base_url: url).call(operation: 'GET',subpath: '',redirect_max: 1)[:http].uri.to_s
541
+ new_url = Rest.new(base_url: url).call(operation: 'GET',subpath: '',redirect_max: 1)[:http].uri.to_s
536
542
  unless url.eql?(new_url)
537
- detection_info=c.detect(new_url)
538
- current_url=new_url
543
+ detection_info = c.detect(new_url)
544
+ current_url = new_url
539
545
  end
540
546
  rescue StandardError => e
541
547
  Log.log.debug("Cannot detect #{plugin_name_sym} : #{e.message}")
@@ -547,35 +553,35 @@ module Aspera
547
553
  end
548
554
 
549
555
  def execute_connect_action
550
- command=options.get_next_command([:list,:info,:version])
551
- if [:info,:version].include?(command)
552
- connect_id=options.get_next_argument('id or title')
553
- one_res=connect_versions.select{|i|i['id'].eql?(connect_id) || i['title'].eql?(connect_id)}.first
556
+ command = options.get_next_command(%i[list info version])
557
+ if %i[info version].include?(command)
558
+ connect_id = options.get_next_argument('id or title')
559
+ one_res = connect_versions.find{|i|i['id'].eql?(connect_id) || i['title'].eql?(connect_id)}
554
560
  raise CliNoSuchId.new(:connect,connect_id) if one_res.nil?
555
561
  end
556
562
  case command
557
563
  when :list
558
- return {type: :object_list, data: connect_versions, fields: ['id','title','version']}
564
+ return {type: :object_list, data: connect_versions, fields: %w[id title version]}
559
565
  when :info # shows files used
560
566
  one_res.delete('links')
561
567
  return {type: :single_object, data: one_res}
562
568
  when :version # shows files used
563
- all_links=one_res['links']
564
- command=options.get_next_command([:list,:download,:open])
565
- if [:download,:open].include?(command)
566
- link_title=options.get_next_argument('title or rel')
567
- one_link=all_links.select {|i| i['title'].eql?(link_title) or i['rel'].eql?(link_title)}.first
569
+ all_links = one_res['links']
570
+ command = options.get_next_command(%i[list download open])
571
+ if %i[download open].include?(command)
572
+ link_title = options.get_next_argument('title or rel')
573
+ one_link = all_links.find {|i| i['title'].eql?(link_title) || i['rel'].eql?(link_title)}
568
574
  raise 'no such value' if one_link.nil?
569
575
  end
570
576
  case command
571
577
  when :list # shows files used
572
578
  return {type: :object_list, data: all_links}
573
579
  when :download
574
- folder_dest=transfer.destination_folder(Fasp::TransferSpec::DIRECTION_RECEIVE)
580
+ folder_dest = transfer.destination_folder(Fasp::TransferSpec::DIRECTION_RECEIVE)
575
581
  #folder_dest=self.options.get_next_argument('destination folder')
576
- api_connect_cdn=Rest.new({base_url: CONNECT_WEB_URL})
582
+ api_connect_cdn = Rest.new({base_url: CONNECT_WEB_URL})
577
583
  fileurl = one_link['href']
578
- filename=fileurl.gsub(%r{.*/},'')
584
+ filename = fileurl.gsub(%r{.*/},'')
579
585
  api_connect_cdn.call({operation: 'GET',subpath: fileurl,save_to_file: File.join(folder_dest,filename)})
580
586
  return Main.result_status("Downloaded: #{filename}")
581
587
  when :open
@@ -586,60 +592,69 @@ module Aspera
586
592
  end
587
593
 
588
594
  def execute_action_ascp
589
- command=options.get_next_command([:connect,:use,:show,:products,:info,:install,:spec,:errors])
595
+ command = options.get_next_command(%i[connect use show products info install spec errors])
590
596
  case command
591
597
  when :connect
592
598
  return execute_connect_action
593
599
  when :use
594
- ascp_path=options.get_next_argument('path to ascp')
595
- ascp_version=Fasp::Installation.instance.get_ascp_version(ascp_path)
600
+ ascp_path = options.get_next_argument('path to ascp')
601
+ ascp_version = Fasp::Installation.instance.get_ascp_version(ascp_path)
596
602
  self.format.display_status("ascp version: #{ascp_version}")
597
- preset_name=set_global_default(:ascp_path,ascp_path)
603
+ preset_name = set_global_default(:ascp_path,ascp_path)
598
604
  return Main.result_status("Saved to default global preset #{preset_name}")
599
605
  when :show # shows files used
600
606
  return {type: :status, data: Fasp::Installation.instance.path(:ascp)}
601
607
  when :info # shows files used
602
- data=Fasp::Installation::FILES.each_with_object({}) do |v,m|
603
- m[v.to_s]=Fasp::Installation.instance.path(v) rescue 'Not Found'
608
+ data = Fasp::Installation::FILES.each_with_object({}) do |v,m|
609
+ m[v.to_s] =
610
+ begin
611
+ Fasp::Installation.instance.path(v)
612
+ rescue => e
613
+ e.message
614
+ end
604
615
  end
605
616
  # read PATHs from ascp directly, and pvcl modules as well
606
617
  Open3.popen3(Fasp::Installation.instance.path(:ascp),'-DDL-') do |_stdin, _stdout, stderr, thread|
607
- last_line=''
608
- while (line=stderr.gets)
618
+ last_line = ''
619
+ while (line = stderr.gets)
609
620
  line.chomp!
610
- last_line=line
621
+ last_line = line
611
622
  case line
612
- when %r{^DBG Path ([^ ]+) (dir|file) +: (.*)$} then data[Regexp.last_match(1)]=Regexp.last_match(3)
613
- when %r{^DBG Added module group:"([^"]+)" name:"([^"]+)", version:"([^"]+)" interface:"([^"]+)"$} then data[Regexp.last_match(2)]=Regexp.last_match(4)
614
- when %r{^DBG License result \(/license/(\S+)\): (.+)$} then data[Regexp.last_match(1)]=Regexp.last_match(2)
615
- when %r{^LOG (.+) version ([0-9.]+)$} then data['product_name']=Regexp.last_match(1);data['product_version']=Regexp.last_match(2)
616
- when %r{^LOG Initializing FASP version ([^,]+),} then data['ascp_version']=Regexp.last_match(1)
623
+ when %r{^DBG Path ([^ ]+) (dir|file) +: (.*)$} then data[Regexp.last_match(1)] = Regexp.last_match(3)
624
+ when %r{^DBG Added module group:"([^"]+)" name:"([^"]+)", version:"([^"]+)" interface:"([^"]+)"$} then data[Regexp.last_match(2)] = Regexp.last_match(4)
625
+ when %r{^DBG License result \(/license/(\S+)\): (.+)$} then data[Regexp.last_match(1)] = Regexp.last_match(2)
626
+ when %r{^LOG (.+) version ([0-9.]+)$} then data['product_name'] = Regexp.last_match(1);data['product_version'] = Regexp.last_match(2)
627
+ when %r{^LOG Initializing FASP version ([^,]+),} then data['ascp_version'] = Regexp.last_match(1)
617
628
  end
618
629
  end
619
630
  if !thread.value.exitstatus.eql?(1) && !data.has_key?('root')
620
631
  raise last_line
621
632
  end
622
633
  end
623
- data['keypass']=Fasp::Installation.instance.bypass_pass
634
+ data['keypass'] = Fasp::Installation.instance.bypass_pass
624
635
  return {type: :single_object, data: data}
625
636
  when :products
626
- command=options.get_next_command([:list,:use])
637
+ command = options.get_next_command(%i[list use])
627
638
  case command
628
639
  when :list
629
- return {type: :object_list, data: Fasp::Installation.instance.installed_products, fields: ['name','app_root']}
640
+ return {type: :object_list, data: Fasp::Installation.instance.installed_products, fields: %w[name app_root]}
630
641
  when :use
631
- default_product=options.get_next_argument('product name')
642
+ default_product = options.get_next_argument('product name')
632
643
  Fasp::Installation.instance.use_ascp_from_product(default_product)
633
- preset_name=set_global_default(:ascp_path,Fasp::Installation.instance.path(:ascp))
644
+ preset_name = set_global_default(:ascp_path,Fasp::Installation.instance.path(:ascp))
634
645
  return Main.result_status("Saved to default global preset #{preset_name}")
635
646
  end
636
647
  when :install
637
- v=Fasp::Installation.instance.install_sdk(options.get_option(:sdk_url,:mandatory))
648
+ v = Fasp::Installation.instance.install_sdk(options.get_option(:sdk_url,is_type: :mandatory))
638
649
  return Main.result_status("Installed version #{v}")
639
650
  when :spec
640
- return {type: :object_list, data: Fasp::Parameters.man_table, fields: ['name','type',Fasp::Parameters::SUPPORTED_AGENTS_SHORT.map(&:to_s),'description'].flatten}
651
+ return {
652
+ type: :object_list,
653
+ data: Fasp::Parameters.man_table,
654
+ fields: ['name','type',Fasp::Parameters::SUPPORTED_AGENTS_SHORT.map(&:to_s),'description'].flatten
655
+ }
641
656
  when :errors
642
- error_data=[]
657
+ error_data = []
643
658
  Fasp::ERROR_INFO.each_pair do |code,prop|
644
659
  error_data.push(code: code, mnemonic: prop[:c], retry: prop[:r], info: prop[:a])
645
660
  end
@@ -649,24 +664,24 @@ module Aspera
649
664
  end
650
665
 
651
666
  # legacy actions available globally
652
- PRESET_GBL_ACTIONS=[:list,:overview].freeze
667
+ PRESET_GBL_ACTIONS = %i[list overview].freeze
653
668
  # require existing preset
654
- PRESET_EXST_ACTIONS=[:show,:delete,:get,:unset].freeze
669
+ PRESET_EXST_ACTIONS = %i[show delete get unset].freeze
655
670
  # require id
656
- PRESET_INSTANCE_ACTIONS=[PRESET_EXST_ACTIONS,:initialize,:update,:ask,:set].flatten.freeze
657
- PRESET_ALL_ACTIONS=[PRESET_GBL_ACTIONS,PRESET_INSTANCE_ACTIONS].flatten.freeze
671
+ PRESET_INSTANCE_ACTIONS = [PRESET_EXST_ACTIONS,%i[initialize update ask set]].flatten.freeze
672
+ PRESET_ALL_ACTIONS = [PRESET_GBL_ACTIONS,PRESET_INSTANCE_ACTIONS].flatten.freeze
658
673
 
659
674
  def execute_file_action(action,config_name)
660
- action=options.get_next_command(PRESET_ALL_ACTIONS) if action.nil?
661
- config_name=instance_identifier() if config_name.nil? && PRESET_INSTANCE_ACTIONS.include?(action)
675
+ action = options.get_next_command(PRESET_ALL_ACTIONS) if action.nil?
676
+ config_name = instance_identifier if config_name.nil? && PRESET_INSTANCE_ACTIONS.include?(action)
662
677
  # those operations require existing option
663
678
  raise "no such preset: #{config_name}" if PRESET_EXST_ACTIONS.include?(action) && !@config_presets.has_key?(config_name)
664
- selected_preset=@config_presets[config_name]
679
+ selected_preset = @config_presets[config_name]
665
680
  case action
666
681
  when :list
667
682
  return {type: :value_list, data: @config_presets.keys, name: 'name'}
668
683
  when :overview
669
- return {type: :object_list, data: self.class.flatten_all_config(@config_presets)}
684
+ return {type: :object_list, data: Formater.flatten_config_overview(@config_presets)}
670
685
  when :show
671
686
  raise "no such config: #{config_name}" if selected_preset.nil?
672
687
  return {type: :single_object, data: selected_preset}
@@ -675,67 +690,67 @@ module Aspera
675
690
  save_presets_to_config_file
676
691
  return Main.result_status("Deleted: #{config_name}")
677
692
  when :get
678
- param_name=options.get_next_argument('parameter name')
679
- value=selected_preset[param_name]
693
+ param_name = options.get_next_argument('parameter name')
694
+ value = selected_preset[param_name]
680
695
  raise "no such option in preset #{config_name} : #{param_name}" if value.nil?
681
696
  case value
682
697
  when Numeric,String then return {type: :text, data: ExtendedValue.instance.evaluate(value.to_s)}
683
698
  end
684
699
  return {type: :single_object, data: value}
685
700
  when :unset
686
- param_name=options.get_next_argument('parameter name')
701
+ param_name = options.get_next_argument('parameter name')
687
702
  selected_preset.delete(param_name)
688
703
  save_presets_to_config_file
689
704
  return Main.result_status("Removed: #{config_name}: #{param_name}")
690
705
  when :set
691
- param_name=options.get_next_argument('parameter name')
692
- param_value=options.get_next_argument('parameter value')
706
+ param_name = options.get_next_argument('parameter name')
707
+ param_value = options.get_next_argument('parameter value')
693
708
  if !@config_presets.has_key?(config_name)
694
709
  Log.log.debug("no such config name: #{config_name}, initializing")
695
- selected_preset=@config_presets[config_name]={}
710
+ selected_preset = @config_presets[config_name] = {}
696
711
  end
697
712
  if selected_preset.has_key?(param_name)
698
713
  Log.log.warn("overwriting value: #{selected_preset[param_name]}")
699
714
  end
700
- selected_preset[param_name]=param_value
715
+ selected_preset[param_name] = param_value
701
716
  save_presets_to_config_file
702
717
  return Main.result_status("Updated: #{config_name}: #{param_name} <- #{param_value}")
703
718
  when :initialize
704
- config_value=options.get_next_argument('extended value (Hash)')
719
+ config_value = options.get_next_argument('extended value (Hash)')
705
720
  if @config_presets.has_key?(config_name)
706
721
  Log.log.warn("configuration already exists: #{config_name}, overwriting")
707
722
  end
708
- @config_presets[config_name]=config_value
723
+ @config_presets[config_name] = config_value
709
724
  save_presets_to_config_file
710
725
  return Main.result_status("Modified: #{@option_config_file}")
711
726
  when :update
712
727
  # get unprocessed options
713
- theopts=options.get_options_table
728
+ theopts = options.get_options_table
714
729
  Log.log.debug("opts=#{theopts}")
715
- @config_presets[config_name]||={}
730
+ @config_presets[config_name] ||= {}
716
731
  @config_presets[config_name].merge!(theopts)
717
732
  # fix bug in 4.4 (creating key "true" in "default" preset)
718
733
  @config_presets[CONF_PRESET_DEFAULT].delete(true) if @config_presets[CONF_PRESET_DEFAULT].is_a?(Hash)
719
734
  save_presets_to_config_file
720
735
  return Main.result_status("Updated: #{config_name}")
721
736
  when :ask
722
- options.ask_missing_mandatory=:yes
723
- @config_presets[config_name]||={}
724
- options.get_next_argument('option names',:multiple).each do |optionname|
725
- option_value=options.get_interactive(:option,optionname)
726
- @config_presets[config_name][optionname]=option_value
737
+ options.ask_missing_mandatory = :yes
738
+ @config_presets[config_name] ||= {}
739
+ options.get_next_argument('option names',expected: :multiple).each do |optionname|
740
+ option_value = options.get_interactive(:option,optionname)
741
+ @config_presets[config_name][optionname] = option_value
727
742
  end
728
743
  save_presets_to_config_file
729
744
  return Main.result_status("Updated: #{config_name}")
730
745
  end
731
746
  end
732
747
 
733
- ACTIONS=[PRESET_GBL_ACTIONS,:id,:preset,:open,:documentation,:genkey,:gem,:plugin,:flush_tokens,:echo,:wizard,:export_to_cli,:detect,:coffee,:ascp,:email_test,
734
- :smtp_settings,:proxy_check,:folder,:file,:check_update,:initdemo,:vault].flatten.freeze
748
+ ACTIONS = [PRESET_GBL_ACTIONS,%i[id preset open documentation genkey gem plugin flush_tokens echo wizard export_to_cli detect coffee
749
+ ascp email_test smtp_settings proxy_check folder file check_update initdemo vault]].flatten.freeze
735
750
 
736
751
  # "config" plugin
737
752
  def execute_action
738
- action=options.get_next_command(ACTIONS)
753
+ action = options.get_next_command(ACTIONS)
739
754
  case action
740
755
  when *PRESET_GBL_ACTIONS # older syntax
741
756
  return execute_file_action(action,nil)
@@ -747,31 +762,33 @@ module Aspera
747
762
  OpenApplication.instance.uri(@option_config_file.to_s) #file://
748
763
  return Main.result_nothing
749
764
  when :documentation
750
- section=options.get_next_argument('private key file path',:single,:optional)
751
- section='#'+section unless section.nil?
765
+ section = options.get_next_argument('private key file path',mandatory: false)
766
+ section = '#' + section unless section.nil?
752
767
  OpenApplication.instance.uri("#{@info[:help]}#{section}")
753
768
  return Main.result_nothing
754
769
  when :genkey # generate new rsa key
755
- private_key_path=options.get_next_argument('private key file path')
756
- generate_rsa_private_key(private_key_path,DEFAULT_PRIVKEY_LENGTH)
757
- return Main.result_status('Generated key: '+private_key_path)
770
+ private_key_path = options.get_next_argument('private key file path')
771
+ private_key_length = options.get_next_argument('size in bits',mandatory: false) || DEFAULT_PRIVKEY_LENGTH
772
+ generate_rsa_private_key(private_key_path,private_key_length)
773
+ return Main.result_status('Generated key: ' + private_key_path)
758
774
  when :echo # display the content of a value given on command line
759
- result={type: :other_struct, data: options.get_next_argument('value')}
775
+ result = {type: :other_struct, data: options.get_next_argument('value')}
760
776
  # special for csv
761
- result[:type]=:object_list if result[:data].is_a?(Array) && result[:data].first.is_a?(Hash)
777
+ result[:type] = :object_list if result[:data].is_a?(Array) && result[:data].first.is_a?(Hash)
778
+ result[:type] = :single_object if result[:data].is_a?(Hash)
762
779
  return result
763
780
  when :flush_tokens
764
- deleted_files=Oauth.flush_tokens
781
+ deleted_files = Oauth.flush_tokens
765
782
  return {type: :value_list, data: deleted_files, name: 'file'}
766
783
  when :plugin
767
- case options.get_next_command([:list,:create])
784
+ case options.get_next_command(%i[list create])
768
785
  when :list
769
- return {type: :object_list, data: @plugins.keys.map { |i| { 'plugin' => i.to_s, 'path' => @plugins[i][:source] } }, fields: ['plugin','path']}
786
+ return {type: :object_list, data: @plugins.keys.map { |i| { 'plugin' => i.to_s, 'path' => @plugins[i][:source] } }, fields: %w[plugin path]}
770
787
  when :create
771
- plugin_name=options.get_next_argument('name',:single,:mandatory).downcase
772
- plugin_folder=options.get_next_argument('folder',:single,:optional) || File.join(@main_folder,ASPERA_PLUGINS_FOLDERNAME)
773
- plugin_file=File.join(plugin_folder,"#{plugin_name}.rb")
774
- content=<<~END_OF_PLUGIN_CODE
788
+ plugin_name = options.get_next_argument('name',expected: :single).downcase
789
+ plugin_folder = options.get_next_argument('folder',expected: :single,mandatory: false) || File.join(@main_folder,ASPERA_PLUGINS_FOLDERNAME)
790
+ plugin_file = File.join(plugin_folder,"#{plugin_name}.rb")
791
+ content = <<~END_OF_PLUGIN_CODE
775
792
  require 'aspera/cli/plugin'
776
793
  module Aspera
777
794
  module Cli
@@ -789,159 +806,62 @@ module Aspera
789
806
  end
790
807
  when :wizard
791
808
  # interactive mode
792
- options.ask_missing_mandatory=true
809
+ options.ask_missing_mandatory = true
793
810
  # register url option
794
- BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
811
+ BasicAuthPlugin.register_options(@agents)
812
+ params={}
795
813
  # get from option, or ask
796
- instance_url=options.get_option(:url,:mandatory)
814
+ params[:instance_url] = options.get_option(:url,is_type: :mandatory)
797
815
  # allow user to tell the preset name
798
- preset_name=options.get_option(:id,:optional)
816
+ params[:preset_name] = options.get_option(:id)
799
817
  # allow user to specify type of application
800
- application=options.get_option(:value,:optional)
801
- application=application.nil? ? identify_plugin_for_url(instance_url)[:product] : application.to_sym
802
- plugin_name='<replace per app>'
803
- test_args='<replace per app>'
804
- case application
818
+ params[:application] = options.get_option(:value)
819
+ params[:application] = params[:application].nil? ? identify_plugin_for_url(params[:instance_url])[:product] : params[:application].to_sym
820
+ params[:plugin_name]=params[:application]
821
+ params[:test_args] = '<replace per app>'
822
+ case params[:application]
823
+ when :faspex5
824
+ wizard_faspex5(params)
805
825
  when :aoc
806
- self.format.display_status('Detected: Aspera on Cloud'.bold)
807
- plugin_name=AOC_COMMAND_CURRENT
808
- organization=AoC.parse_url(instance_url).first
809
- # if not defined by user, generate name
810
- preset_name=[application,organization].join('_') if preset_name.nil?
811
- self.format.display_status("Preparing preset: #{preset_name}")
812
- # init defaults if necessary
813
- @config_presets[CONF_PRESET_DEFAULT]||={}
814
- option_override=options.get_option(:override,:mandatory)
815
- option_default=options.get_option(:default,:mandatory)
816
- Log.log.error("override=#{option_override} -> #{option_override.class}")
817
- raise CliError,"A default configuration already exists for plugin '#{plugin_name}' (use --override=yes or --default=no)" if !option_override && option_default && @config_presets[CONF_PRESET_DEFAULT].has_key?(plugin_name)
818
- raise CliError,"Preset already exists: #{preset_name} (use --override=yes or --id=<name>)" if !option_override && @config_presets.has_key?(preset_name)
819
- # lets see if path to priv key is provided
820
- private_key_path=options.get_option(:pkeypath,:optional)
821
- # give a chance to provide
822
- if private_key_path.nil?
823
- self.format.display_status('Please provide path to your private RSA key, or empty to generate one:')
824
- private_key_path=options.get_option(:pkeypath,:mandatory).to_s
825
- end
826
- # else generate path
827
- if private_key_path.empty?
828
- private_key_path=File.join(@main_folder,DEFAULT_PRIV_KEY_FILENAME)
829
- end
830
- if File.exist?(private_key_path)
831
- self.format.display_status('Using existing key:')
832
- else
833
- self.format.display_status("Generating #{DEFAULT_PRIVKEY_LENGTH} bit RSA key...")
834
- generate_rsa_private_key(private_key_path,DEFAULT_PRIVKEY_LENGTH)
835
- self.format.display_status('Created:')
836
- end
837
- self.format.display_status(private_key_path)
838
- pub_key_pem=OpenSSL::PKey::RSA.new(File.read(private_key_path)).public_key.to_s
839
- # declare command line options for AoC
840
- require 'aspera/cli/plugins/aoc'
841
- # make username mandatory for jwt, this triggers interactive input
842
- options.get_option(:username,:mandatory)
843
- # instanciate AoC plugin, so that command line options are known
844
- aoc_api=self.class.plugin_class(plugin_name).new(@agents.merge({skip_basic_auth_options: true, private_key_path: private_key_path})).aoc_api
845
- auto_set_pub_key=false
846
- auto_set_jwt=false
847
- use_browser_authentication=false
848
- if options.get_option(:use_generic_client)
849
- self.format.display_status('Using global client_id.')
850
- self.format.display_status('Please Login to your Aspera on Cloud instance.'.red)
851
- self.format.display_status('Navigate to your "Account Settings"'.red)
852
- self.format.display_status('Check or update the value of "Public Key" to be:'.red.blink)
853
- self.format.display_status(pub_key_pem.to_s)
854
- if !options.get_option(:test_mode)
855
- self.format.display_status('Once updated or validated, press enter.')
856
- OpenApplication.instance.uri(instance_url)
857
- $stdin.gets
858
- end
859
- else
860
- self.format.display_status('Using organization specific client_id.')
861
- if options.get_option(:client_id,:optional).nil? || options.get_option(:client_secret,:optional).nil?
862
- self.format.display_status('Please login to your Aspera on Cloud instance.'.red)
863
- self.format.display_status('Go to: Apps->Admin->Organization->Integrations')
864
- self.format.display_status('Create or check if there is an existing integration named:')
865
- self.format.display_status("- name: #{@info[:name]}")
866
- self.format.display_status("- redirect uri: #{DEFAULT_REDIRECT}")
867
- self.format.display_status('- origin: localhost')
868
- self.format.display_status('Once created or identified,')
869
- self.format.display_status('Please enter:'.red)
870
- end
871
- OpenApplication.instance.uri("#{instance_url}/#{AOC_PATH_API_CLIENTS}")
872
- options.get_option(:client_id,:mandatory)
873
- options.get_option(:client_secret,:mandatory)
874
- use_browser_authentication=true
875
- end
876
- if use_browser_authentication
877
- self.format.display_status('We will use web authentication to bootstrap.')
878
- auto_set_pub_key=true
879
- auto_set_jwt=true
880
- aoc_api.oauth.params[:crtype]=:web
881
- aoc_api.oauth.params[:web][:redirect_uri]=DEFAULT_REDIRECT
882
- aoc_api.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
883
- end
884
- myself=aoc_api.read('self')[:data]
885
- if auto_set_pub_key
886
- raise CliError,'Public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? || option_override
887
- self.format.display_status('Updating profile with new key')
888
- aoc_api.update("users/#{myself['id']}",{'public_key'=>pub_key_pem})
889
- end
890
- if auto_set_jwt
891
- self.format.display_status('Enabling JWT for client')
892
- aoc_api.update("clients/#{options.get_option(:client_id)}",{'jwt_grant_enabled'=>true,'explicit_authorization_required'=>false})
893
- end
894
- self.format.display_status("Creating new config preset: #{preset_name}")
895
- @config_presets[preset_name]={
896
- :url.to_s =>options.get_option(:url),
897
- :username.to_s =>myself['email'],
898
- :auth.to_s =>:jwt.to_s,
899
- :private_key.to_s =>'@file:'+private_key_path
900
- }
901
- # set only if non nil
902
- [:client_id,:client_secret].each do |s|
903
- o=options.get_option(s)
904
- @config_presets[preset_name][s.to_s] = o unless o.nil?
905
- end
906
- test_args="#{plugin_name} user profile show"
826
+ wizard_aoc(params)
907
827
  else
908
- raise CliBadArgument,"Supports only: aoc. Detected: #{application}"
828
+ raise CliBadArgument,"Supports only: aoc. Detected: #{params[:application]}"
909
829
  end # product
910
- if option_default
911
- self.format.display_status("Setting config preset as default for #{plugin_name}")
912
- @config_presets[CONF_PRESET_DEFAULT][plugin_name]=preset_name
830
+ if params[:option_default]
831
+ self.format.display_status("Setting config preset as default for #{params[:plugin_name]}")
832
+ @config_presets[CONF_PRESET_DEFAULT][params[:plugin_name]] = params[:preset_name]
913
833
  else
914
- test_args="-P#{preset_name} #{test_args}"
834
+ params[:test_args] = "-P#{params[:preset_name]} #{params[:test_args]}"
915
835
  end
916
836
  self.format.display_status('Saving config file.')
917
837
  save_presets_to_config_file
918
- return Main.result_status("Done.\nYou can test with:\n#{@info[:name]} #{test_args}")
919
- when :export_to_cli
838
+ return Main.result_status("Done.\nYou can test with:\n#{@info[:name]} #{params[:test_args]}")
839
+ when :export_to_cli # this method shall be deprecated in the future: it was used to export configuration to "aspera.exe" CLI
920
840
  self.format.display_status('Exporting: Aspera on Cloud')
921
841
  require 'aspera/cli/plugins/aoc'
922
842
  # need url / username
923
843
  add_plugin_default_preset(AOC_COMMAND_V3.to_sym)
924
844
  # instanciate AoC plugin
925
845
  self.class.plugin_class(AOC_COMMAND_CURRENT).new(@agents) # TODO: is this line needed ? get options ?
926
- url=options.get_option(:url,:mandatory)
927
- cli_conf_file=Fasp::Installation.instance.cli_conf_file
928
- data=JSON.parse(File.read(cli_conf_file))
929
- organization,instance_domain=AoC.parse_url(url)
930
- key_basename='org_'+organization+'.pem'
931
- key_file=File.join(File.dirname(File.dirname(cli_conf_file)),'etc',key_basename)
932
- File.write(key_file,options.get_option(:private_key,:mandatory))
933
- new_conf={
846
+ url = options.get_option(:url,is_type: :mandatory)
847
+ cli_conf_file = Fasp::Installation.instance.cli_conf_file
848
+ data = JSON.parse(File.read(cli_conf_file))
849
+ organization,instance_domain = AoC.parse_url(url)
850
+ key_basename = 'org_' + organization + '.pem'
851
+ key_file = File.join(File.dirname(File.dirname(cli_conf_file)),'etc',key_basename)
852
+ File.write(key_file,options.get_option(:private_key,is_type: :mandatory))
853
+ new_conf = {
934
854
  'organization' => organization,
935
855
  'hostname' => [organization,instance_domain].join('.'),
936
856
  'privateKeyFilename' => key_basename,
937
- 'username' => options.get_option(:username,:mandatory)
857
+ 'username' => options.get_option(:username,is_type: :mandatory)
938
858
  }
939
- new_conf['clientId']=options.get_option(:client_id,:optional)
940
- new_conf['clientSecret']=options.get_option(:client_secret,:optional)
859
+ new_conf['clientId'] = options.get_option(:client_id)
860
+ new_conf['clientSecret'] = options.get_option(:client_secret)
941
861
  if new_conf['clientId'].nil?
942
- new_conf['clientId'],new_conf['clientSecret']=AoC.get_client_info()
862
+ new_conf['clientId'],new_conf['clientSecret'] = AoC.get_client_info
943
863
  end
944
- entry=data['AoCAccounts'].select{|i|i['organization'].eql?(organization)}.first
864
+ entry = data['AoCAccounts'].find{|i|i['organization'].eql?(organization)}
945
865
  if entry.nil?
946
866
  data['AoCAccounts'].push(new_conf)
947
867
  self.format.display_status("Creating new aoc entry: #{organization}")
@@ -953,15 +873,15 @@ module Aspera
953
873
  return Main.result_status("Updated: #{cli_conf_file}")
954
874
  when :detect
955
875
  # need url / username
956
- BasicAuthPlugin.new(@agents)
957
- return {type: :single_object, data: identify_plugin_for_url(options.get_option(:url,:mandatory))}
876
+ BasicAuthPlugin.register_options(@agents)
877
+ return {type: :single_object, data: identify_plugin_for_url(options.get_option(:url,is_type: :mandatory))}
958
878
  when :coffee
959
879
  OpenApplication.instance.uri('https://enjoyjava.com/wp-content/uploads/2018/01/How-to-make-strong-coffee.jpg')
960
880
  return Main.result_nothing
961
881
  when :ascp
962
882
  execute_action_ascp
963
883
  when :gem
964
- case options.get_next_command([:path,:version,:name])
884
+ case options.get_next_command(%i[path version name])
965
885
  when :path then return Main.result_status(self.class.gem_src_root)
966
886
  when :version then return Main.result_status(Aspera::Cli::VERSION)
967
887
  when :name then return Main.result_status(@info[:gem])
@@ -977,8 +897,8 @@ module Aspera
977
897
  return {type: :single_object, data: email_settings}
978
898
  when :proxy_check
979
899
  # ensure fpac was provided
980
- options.get_option(:fpac,:mandatory)
981
- server_url=options.get_next_argument('server url')
900
+ options.get_option(:fpac,is_type: :mandatory)
901
+ server_url = options.get_next_argument('server url')
982
902
  return Main.result_status(@pac_exec.find_proxy_for_url(server_url))
983
903
  when :check_update
984
904
  return {type: :single_object, data: check_gem_version}
@@ -987,28 +907,32 @@ module Aspera
987
907
  Log.log.warn("Demo server preset already present: #{DEMO_SERVER_PRESET}")
988
908
  else
989
909
  Log.log.info("Creating Demo server preset: #{DEMO_SERVER_PRESET}")
990
- @config_presets[DEMO_SERVER_PRESET]=
991
- {'url'=>'ssh://'+DEMO+'.asperasoft.com:33001','username'=>AOC_COMMAND_V2,'ssAP'.downcase.reverse+'drow'.reverse=>DEMO+AOC_COMMAND_V2}
910
+ @config_presets[DEMO_SERVER_PRESET] = {
911
+ 'url' => 'ssh://' + DEMO + '.asperasoft.com:33001',
912
+ 'username' => AOC_COMMAND_V2,
913
+ 'ssAP'.downcase.reverse + 'drow'.reverse => DEMO + AOC_COMMAND_V2
914
+ }
992
915
  end
993
- @config_presets[CONF_PRESET_DEFAULT]||={}
916
+ @config_presets[CONF_PRESET_DEFAULT] ||= {}
994
917
  if @config_presets[CONF_PRESET_DEFAULT].has_key?(SERVER_COMMAND)
995
918
  Log.log.warn("Server default preset already set to: #{@config_presets[CONF_PRESET_DEFAULT][SERVER_COMMAND]}")
996
- Log.log.warn("Use #{DEMO_SERVER_PRESET} for demo: -P#{DEMO_SERVER_PRESET}") unless DEMO_SERVER_PRESET.eql?(@config_presets[CONF_PRESET_DEFAULT][SERVER_COMMAND])
919
+ Log.log.warn("Use #{DEMO_SERVER_PRESET} for demo: -P#{DEMO_SERVER_PRESET}") unless
920
+ DEMO_SERVER_PRESET.eql?(@config_presets[CONF_PRESET_DEFAULT][SERVER_COMMAND])
997
921
  else
998
- @config_presets[CONF_PRESET_DEFAULT][SERVER_COMMAND]=DEMO_SERVER_PRESET
922
+ @config_presets[CONF_PRESET_DEFAULT][SERVER_COMMAND] = DEMO_SERVER_PRESET
999
923
  Log.log.info("Setting server default preset to : #{DEMO_SERVER_PRESET}")
1000
924
  end
1001
925
  save_presets_to_config_file
1002
926
  return Main.result_status('Done')
1003
927
  when :vault
1004
- command=options.get_next_command([:init,:list,:get,:set,:delete])
928
+ command = options.get_next_command(%i[init list get set delete])
1005
929
  case command
1006
930
  when :init
1007
- type=options.get_option(:value,:optional)
931
+ type = options.get_option(:value)
1008
932
  case type
1009
933
  when 'config',NilClass
1010
934
  raise 'default secrets already exists' if @config_presets.has_key?(CONF_PRESET_SECRETS)
1011
- @config_presets[CONF_PRESET_SECRETS]={}
935
+ @config_presets[CONF_PRESET_SECRETS] = {}
1012
936
  set_global_default(:secrets,"@preset:#{CONF_PRESET_SECRETS}")
1013
937
  else raise 'no such vault type'
1014
938
  end
@@ -1017,26 +941,26 @@ module Aspera
1017
941
  return {type: :object_list, data: vault.list}
1018
942
  when :set
1019
943
  # register url option
1020
- BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
1021
- username=options.get_option(:username,:mandatory)
1022
- url=options.get_option(:url,:mandatory)
1023
- description=options.get_option(:value,:optional)
1024
- secret=options.get_next_argument('secret')
944
+ BasicAuthPlugin.register_options(@agents)
945
+ username = options.get_option(:username,is_type: :mandatory)
946
+ url = options.get_option(:url,is_type: :mandatory)
947
+ description = options.get_option(:value)
948
+ secret = options.get_next_argument('secret')
1025
949
  vault.set(username: username, url: url, description: description, secret: secret)
1026
950
  save_presets_to_config_file if vault.is_a?(Keychain::EncryptedHash)
1027
951
  return Main.result_status('Done')
1028
952
  when :get
1029
953
  # register url option
1030
- BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
1031
- username=options.get_option(:username,:mandatory)
1032
- url=options.get_option(:url,:optional)
1033
- result=vault.get(username: username, url: url)
954
+ BasicAuthPlugin.register_options(@agents)
955
+ username = options.get_option(:username,is_type: :mandatory)
956
+ url = options.get_option(:url)
957
+ result = vault.get(username: username, url: url)
1034
958
  return {type: :single_object, data: result}
1035
959
  when :delete
1036
960
  # register url option
1037
- BasicAuthPlugin.new(@agents.merge(skip_option_header: true))
1038
- username=options.get_option(:username,:mandatory)
1039
- url=options.get_option(:url,:optional)
961
+ BasicAuthPlugin.register_options(@agents)
962
+ username = options.get_option(:username,is_type: :mandatory)
963
+ url = options.get_option(:url)
1040
964
  vault.delete(username: username, url: url)
1041
965
  return Main.result_status('Done')
1042
966
  end
@@ -1046,17 +970,17 @@ module Aspera
1046
970
 
1047
971
  # @return email server setting with defaults if not defined
1048
972
  def email_settings
1049
- smtp=options.get_option(:smtp,:mandatory)
973
+ smtp = options.get_option(:smtp,is_type: :mandatory)
1050
974
  # change string keys into symbol keys
1051
- smtp=smtp.keys.each_with_object({}){|v,m|m[v.to_sym]=smtp[v];}
975
+ smtp = smtp.keys.each_with_object({}){|v,m|m[v.to_sym] = smtp[v];}
1052
976
  # defaults
1053
- smtp[:tls]||=true
1054
- smtp[:port]||=smtp[:tls]?587:25
1055
- smtp[:from_email]||=smtp[:username] if smtp.has_key?(:username)
1056
- smtp[:from_name]||=smtp[:from_email].gsub(/@.*$/,'').gsub(/[^a-zA-Z]/,' ').capitalize if smtp.has_key?(:username)
1057
- smtp[:domain]||=smtp[:from_email].gsub(/^.*@/,'') if smtp.has_key?(:from_email)
977
+ smtp[:tls] ||= true
978
+ smtp[:port] ||= smtp[:tls] ? 587 : 25
979
+ smtp[:from_email] ||= smtp[:username] if smtp.has_key?(:username)
980
+ smtp[:from_name] ||= smtp[:from_email].gsub(/@.*$/,'').gsub(/[^a-zA-Z]/,' ').capitalize if smtp.has_key?(:username)
981
+ smtp[:domain] ||= smtp[:from_email].gsub(/^.*@/,'') if smtp.has_key?(:from_email)
1058
982
  # check minimum required
1059
- [:server,:port,:domain].each do |n|
983
+ %i[server port domain].each do |n|
1060
984
  raise "Missing smtp parameter: #{n}" unless smtp.has_key?(n)
1061
985
  end
1062
986
  Log.log.debug("smtp=#{smtp}")
@@ -1069,25 +993,25 @@ module Aspera
1069
993
  end
1070
994
 
1071
995
  def send_email_template(vars,email_template_default=nil)
1072
- vars[:to]||=options.get_option(:notif_to,:mandatory)
1073
- notif_template=options.get_option(:notif_template,email_template_default.nil? ? :mandatory : :optional) || email_template_default
1074
- mail_conf=email_settings
1075
- vars[:from_name]||=mail_conf[:from_name]
1076
- vars[:from_email]||=mail_conf[:from_email]
1077
- [:from_name,:from_email].each do |n|
996
+ vars[:to] ||= options.get_option(:notif_to,is_type: :mandatory)
997
+ notif_template = options.get_option(:notif_template,is_type: email_template_default.nil? ? :mandatory : :optional) || email_template_default
998
+ mail_conf = email_settings
999
+ vars[:from_name] ||= mail_conf[:from_name]
1000
+ vars[:from_email] ||= mail_conf[:from_email]
1001
+ %i[from_name from_email].each do |n|
1078
1002
  raise "Missing email parameter: #{n}" unless vars.has_key?(n)
1079
1003
  end
1080
- start_options=[mail_conf[:domain]]
1004
+ start_options = [mail_conf[:domain]]
1081
1005
  start_options.push(mail_conf[:username],mail_conf[:password],:login) if mail_conf.has_key?(:username) && mail_conf.has_key?(:password)
1082
1006
  # create a binding with only variables defined in vars
1083
- template_binding=empty_binding
1007
+ template_binding = empty_binding
1084
1008
  # add variables to binding
1085
1009
  vars.each do |k,v|
1086
1010
  raise "key (#{k.class}) must be Symbol" unless k.is_a?(Symbol)
1087
1011
  template_binding.local_variable_set(k,v)
1088
1012
  end
1089
1013
  # execute template
1090
- msg_with_headers=ERB.new(notif_template).result(template_binding)
1014
+ msg_with_headers = ERB.new(notif_template).result(template_binding)
1091
1015
  Log.dump(:msg_with_headers,msg_with_headers)
1092
1016
  smtp = Net::SMTP.new(mail_conf[:server], mail_conf[:port])
1093
1017
  smtp.enable_starttls if mail_conf[:tls]
@@ -1099,8 +1023,10 @@ module Aspera
1099
1023
  def save_presets_to_config_file
1100
1024
  raise 'no configuration loaded' if @config_presets.nil?
1101
1025
  FileUtils.mkdir_p(@main_folder) unless Dir.exist?(@main_folder)
1026
+ File.chmod(0700,@main_folder)
1102
1027
  Log.log.debug("Writing #{@option_config_file}")
1103
1028
  File.write(@option_config_file,@config_presets.to_yaml)
1029
+ File.chmod(0600,@option_config_file)
1104
1030
  end
1105
1031
 
1106
1032
  # returns [String] name if config_presets has default
@@ -1113,9 +1039,11 @@ module Aspera
1113
1039
  end
1114
1040
  if @config_presets.has_key?(CONF_PRESET_DEFAULT) &&
1115
1041
  @config_presets[CONF_PRESET_DEFAULT].has_key?(plugin_sym.to_s)
1116
- default_config_name=@config_presets[CONF_PRESET_DEFAULT][plugin_sym.to_s]
1042
+ default_config_name = @config_presets[CONF_PRESET_DEFAULT][plugin_sym.to_s]
1117
1043
  if !@config_presets.has_key?(default_config_name)
1118
- Log.log.error("Default config name [#{default_config_name}] specified for plugin [#{plugin_sym}], but it does not exist in config file.\nPlease fix the issue: either create preset with one parameter (#{@info[:name]} config id #{default_config_name} init @json:'{}') or remove default (#{@info[:name]} config id default remove #{plugin_sym}).")
1044
+ Log.log.error("Default config name [#{default_config_name}] specified for plugin [#{plugin_sym}], but it does not exist in config file.\n"\
1045
+ 'Please fix the issue: either create preset with one parameter: '\
1046
+ "(#{@info[:name]} config id #{default_config_name} init @json:'{}') or remove default (#{@info[:name]} config id default remove #{plugin_sym}).")
1119
1047
  end
1120
1048
  raise CliError,"Config name [#{default_config_name}] must be a hash, check config file." if !@config_presets[default_config_name].is_a?(Hash)
1121
1049
  return default_config_name
@@ -1125,15 +1053,15 @@ module Aspera
1125
1053
 
1126
1054
  def vault
1127
1055
  if @vault.nil?
1128
- vault_info=options.get_option(:secrets,:optional)
1056
+ vault_info = options.get_option(:secrets)
1129
1057
  case vault_info
1130
1058
  when Hash
1131
- @vault=Keychain::EncryptedHash.new(vault_info)
1059
+ @vault = Keychain::EncryptedHash.new(vault_info)
1132
1060
  when /^system/
1133
- name=vault_info.start_with?('system:') ? vault_info[7..-1] : nil
1061
+ name = vault_info.start_with?('system:') ? vault_info[7..-1] : nil
1134
1062
  case Environment.os
1135
1063
  when Environment::OS_X
1136
- @vault=Keychain::MacosSecurity.new(name)
1064
+ @vault = Keychain::MacosSecurity.new(name)
1137
1065
  when Environment::OS_WINDOWS,Environment::OS_LINUX,Environment::OS_AIX
1138
1066
  raise 'not implemented'
1139
1067
  else raise 'Error'
@@ -1151,14 +1079,177 @@ module Aspera
1151
1079
  def get_secret(options)
1152
1080
  raise 'options shall be Hash' unless options.is_a?(Hash)
1153
1081
  raise 'options shall have username' unless options.has_key?(:username)
1154
- secret=self.options.get_option(:secret,:optional)
1082
+ secret = self.options.get_option(:secret)
1155
1083
  if secret.nil?
1156
- secret=vault.get(options) rescue nil
1084
+ secret = vault.get(options) rescue nil
1157
1085
  # mandatory by default
1158
1086
  raise "please provide secret for #{options[:username]}" if secret.nil? && (options[:mandatory].nil? || options[:mandatory])
1159
1087
  end
1160
1088
  return secret
1161
1089
  end
1090
+
1091
+ def wizard_aoc(params)
1092
+ self.format.display_status('Detected: Aspera on Cloud'.bold)
1093
+ params[:plugin_name] = AOC_COMMAND_CURRENT
1094
+ organization = AoC.parse_url(params[:instance_url]).first
1095
+ # if not defined by user, generate name
1096
+ params[:preset_name] = [params[:application],organization].join('_') if params[:preset_name].nil?
1097
+ self.format.display_status("Preparing preset: #{params[:preset_name]}")
1098
+ # init defaults if necessary
1099
+ @config_presets[CONF_PRESET_DEFAULT] ||= {}
1100
+ option_override = options.get_option(:override,is_type: :mandatory)
1101
+ params[:option_default] = options.get_option(:default,is_type: :mandatory)
1102
+ Log.log.error("override=#{option_override} -> #{option_override.class}")
1103
+ raise CliError,"A default configuration already exists for plugin '#{params[:plugin_name]}' (use --override=yes or --default=no)" \
1104
+ if !option_override && params[:option_default] && @config_presets[CONF_PRESET_DEFAULT].has_key?(params[:plugin_name])
1105
+ raise CliError,"Preset already exists: #{params[:preset_name]} (use --override=yes or --id=<name>)" \
1106
+ if !option_override && @config_presets.has_key?(params[:preset_name])
1107
+ # lets see if path to priv key is provided
1108
+ private_key_path = options.get_option(:pkeypath)
1109
+ # give a chance to provide
1110
+ if private_key_path.nil?
1111
+ self.format.display_status('Please provide path to your private RSA key, or empty to generate one:')
1112
+ private_key_path = options.get_option(:pkeypath,is_type: :mandatory).to_s
1113
+ end
1114
+ # else generate path
1115
+ if private_key_path.empty?
1116
+ private_key_path = File.join(@main_folder,DEFAULT_PRIV_KEY_FILENAME)
1117
+ end
1118
+ if File.exist?(private_key_path)
1119
+ self.format.display_status('Using existing key:')
1120
+ else
1121
+ self.format.display_status("Generating #{DEFAULT_PRIVKEY_LENGTH} bit RSA key...")
1122
+ generate_rsa_private_key(private_key_path,DEFAULT_PRIVKEY_LENGTH)
1123
+ self.format.display_status('Created:')
1124
+ end
1125
+ self.format.display_status(private_key_path)
1126
+ pub_key_pem = OpenSSL::PKey::RSA.new(File.read(private_key_path)).public_key.to_s
1127
+ # declare command line options for AoC
1128
+ require 'aspera/cli/plugins/aoc'
1129
+ # make username mandatory for jwt, this triggers interactive input
1130
+ options.get_option(:username,is_type: :mandatory)
1131
+ # instanciate AoC plugin, so that command line options are known
1132
+ aoc_api = self.class.plugin_class(params[:plugin_name]).new(@agents.merge({skip_basic_auth_options: true, private_key_path: private_key_path})).aoc_api
1133
+ auto_set_pub_key = false
1134
+ auto_set_jwt = false
1135
+ use_browser_authentication = false
1136
+ if options.get_option(:use_generic_client)
1137
+ self.format.display_status('Using global client_id.')
1138
+ self.format.display_status('Please Login to your Aspera on Cloud instance.'.red)
1139
+ self.format.display_status('Navigate to your "Account Settings"'.red)
1140
+ self.format.display_status('Check or update the value of "Public Key" to be:'.red.blink)
1141
+ self.format.display_status(pub_key_pem.to_s)
1142
+ if !options.get_option(:test_mode)
1143
+ self.format.display_status('Once updated or validated, press enter.')
1144
+ OpenApplication.instance.uri(params[:instance_url])
1145
+ $stdin.gets
1146
+ end
1147
+ else
1148
+ self.format.display_status('Using organization specific client_id.')
1149
+ if options.get_option(:client_id).nil? || options.get_option(:client_secret,is_type: :optional).nil?
1150
+ self.format.display_status('Please login to your Aspera on Cloud instance.'.red)
1151
+ self.format.display_status('Go to: Apps->Admin->Organization->Integrations')
1152
+ self.format.display_status('Create or check if there is an existing integration named:')
1153
+ self.format.display_status("- name: #{@info[:name]}")
1154
+ self.format.display_status("- redirect uri: #{DEFAULT_REDIRECT}")
1155
+ self.format.display_status('- origin: localhost')
1156
+ self.format.display_status('Once created or identified,')
1157
+ self.format.display_status('Please enter:'.red)
1158
+ end
1159
+ OpenApplication.instance.uri("#{params[:instance_url]}/#{AOC_PATH_API_CLIENTS}")
1160
+ options.get_option(:client_id,is_type: :mandatory)
1161
+ options.get_option(:client_secret,is_type: :mandatory)
1162
+ use_browser_authentication = true
1163
+ end
1164
+ if use_browser_authentication
1165
+ self.format.display_status('We will use web authentication to bootstrap.')
1166
+ auto_set_pub_key = true
1167
+ auto_set_jwt = true
1168
+ aoc_api.oauth.gparams[:crtype] = :web
1169
+ aoc_api.oauth.gparams[:scope] = AoC::SCOPE_FILES_ADMIN
1170
+ aoc_api.oauth.sparams[:redirect_uri] = DEFAULT_REDIRECT
1171
+ end
1172
+ myself = aoc_api.read('self')[:data]
1173
+ if auto_set_pub_key
1174
+ raise CliError,'Public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? || option_override
1175
+ self.format.display_status('Updating profile with new key')
1176
+ aoc_api.update("users/#{myself['id']}",{'public_key' => pub_key_pem})
1177
+ end
1178
+ if auto_set_jwt
1179
+ self.format.display_status('Enabling JWT for client')
1180
+ aoc_api.update("clients/#{options.get_option(:client_id)}",{'jwt_grant_enabled' => true,'explicit_authorization_required' => false})
1181
+ end
1182
+ self.format.display_status("Creating new config preset: #{params[:preset_name]}")
1183
+ @config_presets[params[:preset_name]] = {
1184
+ :url.to_s => options.get_option(:url),
1185
+ :username.to_s => myself['email'],
1186
+ :auth.to_s => :jwt.to_s,
1187
+ :private_key.to_s => '@file:' + private_key_path
1188
+ }
1189
+ # set only if non nil
1190
+ %i[client_id client_secret].each do |s|
1191
+ o = options.get_option(s)
1192
+ @config_presets[params[:preset_name]][s.to_s] = o unless o.nil?
1193
+ end
1194
+ params[:test_args] = "#{params[:plugin_name]} user profile show"
1195
+ end
1196
+
1197
+ def wizard_faspex5(params)
1198
+ self.format.display_status('Detected: Faspex v5'.bold)
1199
+ # if not defined by user, generate unique name
1200
+ params[:preset_name] = [params[:application],URI.parse(params[:instance_url]).host.gsub(/[^a-z0-9.]/,'').split('.')].flatten.join('_') \
1201
+ if params[:preset_name].nil?
1202
+ self.format.display_status("Preparing preset: #{params[:preset_name]}")
1203
+ # init defaults if necessary
1204
+ @config_presets[CONF_PRESET_DEFAULT] ||= {}
1205
+ option_override = options.get_option(:override,is_type: :mandatory)
1206
+ params[:option_default] = options.get_option(:default,is_type: :mandatory)
1207
+ Log.log.error("override=#{option_override} -> #{option_override.class}")
1208
+ raise CliError,"A default configuration already exists for plugin '#{params[:plugin_name]}' (use --override=yes or --default=no)" \
1209
+ if !option_override && params[:option_default] && @config_presets[CONF_PRESET_DEFAULT].has_key?(params[:plugin_name])
1210
+ raise CliError,"Preset already exists: #{params[:preset_name]} (use --override=yes or --id=<name>)" \
1211
+ if !option_override && @config_presets.has_key?(params[:preset_name])
1212
+ # lets see if path to priv key is provided
1213
+ private_key_path = options.get_option(:pkeypath)
1214
+ # give a chance to provide
1215
+ if private_key_path.nil?
1216
+ self.format.display_status('Please provide path to your private RSA key, or empty to generate one:')
1217
+ private_key_path = options.get_option(:pkeypath,is_type: :mandatory).to_s
1218
+ end
1219
+ # else generate path
1220
+ if private_key_path.empty?
1221
+ private_key_path = File.join(@main_folder,DEFAULT_PRIV_KEY_FILENAME)
1222
+ end
1223
+ if File.exist?(private_key_path)
1224
+ self.format.display_status('Using existing key:')
1225
+ else
1226
+ self.format.display_status("Generating #{DEFAULT_PRIVKEY_LENGTH} bit RSA key...")
1227
+ generate_rsa_private_key(private_key_path,DEFAULT_PRIVKEY_LENGTH)
1228
+ self.format.display_status('Created:')
1229
+ end
1230
+ self.format.display_status(private_key_path)
1231
+ pub_key_pem = OpenSSL::PKey::RSA.new(File.read(private_key_path)).public_key.to_s
1232
+ # declare command line options for AoC
1233
+ require 'aspera/cli/plugins/faspex5'
1234
+ self.class.plugin_class(params[:plugin_name]).new(@agents.merge({skip_basic_auth_options: true}))
1235
+ self.format.display_status('Please login to Faspex 5.'.red)
1236
+ OpenApplication.instance.uri(params[:instance_url])
1237
+ self.format.display_status('Navigate to: 𓃑 → Admin → Configurations → API clients')
1238
+ self.format.display_status('Create a client with:')
1239
+ self.format.display_status('- JWT enabled')
1240
+ self.format.display_status('- The following public key:')
1241
+ self.format.display_status(pub_key_pem.to_s)
1242
+ self.format.display_status('Once created, copy the following parameters:')
1243
+ @config_presets[params[:preset_name]] = {
1244
+ :url.to_s => options.get_option(:url),
1245
+ :username.to_s => options.get_option(:username),
1246
+ :auth.to_s => :jwt.to_s,
1247
+ :private_key.to_s => '@file:' + private_key_path,
1248
+ :client_id.to_s => options.get_option(:client_id,is_type: :mandatory),
1249
+ :client_secret.to_s => options.get_option(:client_secret,is_type: :mandatory)
1250
+ }
1251
+ params[:test_args] = "#{params[:plugin_name]} user profile show"
1252
+ end
1162
1253
  end
1163
1254
  end
1164
1255
  end