aspera-cli 4.24.0 → 4.24.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - checksums.yaml.gz.sig +0 -0
 - data/CHANGELOG.md +19 -1
 - data/README.md +1264 -941
 - data/bin/ascli +20 -1
 - data/bin/asession +23 -27
 - data/lib/aspera/agent/base.rb +10 -21
 - data/lib/aspera/agent/connect.rb +2 -3
 - data/lib/aspera/agent/desktop.rb +2 -2
 - data/lib/aspera/agent/direct.rb +49 -32
 - data/lib/aspera/agent/factory.rb +31 -0
 - data/lib/aspera/api/aoc.rb +79 -49
 - data/lib/aspera/api/faspex.rb +212 -0
 - data/lib/aspera/api/node.rb +99 -84
 - data/lib/aspera/ascp/installation.rb +22 -21
 - data/lib/aspera/ascp/management.rb +119 -23
 - data/lib/aspera/assert.rb +14 -8
 - data/lib/aspera/cli/extended_value.rb +15 -15
 - data/lib/aspera/cli/formatter.rb +7 -5
 - data/lib/aspera/cli/hints.rb +8 -0
 - data/lib/aspera/cli/info.rb +4 -4
 - data/lib/aspera/cli/main.rb +56 -71
 - data/lib/aspera/cli/manager.rb +7 -4
 - data/lib/aspera/cli/plugins/alee.rb +2 -1
 - data/lib/aspera/cli/plugins/aoc.rb +110 -186
 - data/lib/aspera/cli/plugins/ats.rb +4 -4
 - data/lib/aspera/cli/plugins/base.rb +335 -0
 - data/lib/aspera/cli/plugins/basic_auth.rb +45 -0
 - data/lib/aspera/cli/plugins/config.rb +263 -221
 - data/lib/aspera/cli/plugins/console.rb +15 -15
 - data/lib/aspera/cli/plugins/cos.rb +2 -2
 - data/lib/aspera/cli/plugins/factory.rb +78 -0
 - data/lib/aspera/cli/plugins/faspex.rb +17 -20
 - data/lib/aspera/cli/plugins/faspex5.rb +79 -193
 - data/lib/aspera/cli/plugins/faspio.rb +14 -13
 - data/lib/aspera/cli/plugins/httpgw.rb +13 -12
 - data/lib/aspera/cli/plugins/node.rb +34 -32
 - data/lib/aspera/cli/plugins/oauth.rb +48 -0
 - data/lib/aspera/cli/plugins/orchestrator.rb +15 -13
 - data/lib/aspera/cli/plugins/preview.rb +4 -4
 - data/lib/aspera/cli/plugins/server.rb +15 -13
 - data/lib/aspera/cli/plugins/shares.rb +18 -15
 - data/lib/aspera/cli/sync_actions.rb +1 -1
 - data/lib/aspera/cli/transfer_agent.rb +24 -20
 - data/lib/aspera/cli/transfer_progress.rb +6 -6
 - data/lib/aspera/cli/version.rb +3 -3
 - data/lib/aspera/cli/wizard.rb +74 -65
 - data/lib/aspera/colors.rb +6 -0
 - data/lib/aspera/command_line_builder.rb +45 -50
 - data/lib/aspera/command_line_converter.rb +2 -1
 - data/lib/aspera/coverage.rb +1 -1
 - data/lib/aspera/data_repository.rb +1 -1
 - data/lib/aspera/environment.rb +13 -9
 - data/lib/aspera/faspex_gw.rb +6 -4
 - data/lib/aspera/faspex_postproc.rb +1 -1
 - data/lib/aspera/keychain/macos_security.rb +1 -1
 - data/lib/aspera/log.rb +88 -37
 - data/lib/aspera/nagios.rb +1 -1
 - data/lib/aspera/oauth/base.rb +17 -10
 - data/lib/aspera/oauth/factory.rb +8 -8
 - data/lib/aspera/oauth/web.rb +2 -2
 - data/lib/aspera/products/connect.rb +4 -3
 - data/lib/aspera/products/desktop.rb +1 -4
 - data/lib/aspera/products/other.rb +9 -1
 - data/lib/aspera/products/transferd.rb +0 -1
 - data/lib/aspera/rest.rb +126 -83
 - data/lib/aspera/ssh.rb +3 -3
 - data/lib/aspera/sync/args.schema.yaml +46 -3
 - data/lib/aspera/sync/conf.schema.yaml +130 -94
 - data/lib/aspera/sync/operations.rb +71 -74
 - data/lib/aspera/temp_file_manager.rb +17 -5
 - data/lib/aspera/transfer/error.rb +16 -7
 - data/lib/aspera/transfer/parameters.rb +34 -20
 - data/lib/aspera/transfer/resumer.rb +74 -0
 - data/lib/aspera/transfer/spec.rb +4 -3
 - data/lib/aspera/transfer/spec.schema.yaml +132 -51
 - data/lib/aspera/transfer/spec_doc.rb +41 -35
 - data/lib/aspera/uri_reader.rb +1 -1
 - data/lib/aspera/web_auth.rb +6 -6
 - data.tar.gz.sig +0 -0
 - metadata +9 -7
 - metadata.gz.sig +2 -2
 - data/lib/aspera/cli/basic_auth_plugin.rb +0 -43
 - data/lib/aspera/cli/plugin.rb +0 -333
 - data/lib/aspera/cli/plugin_factory.rb +0 -81
 - data/lib/aspera/resumer.rb +0 -77
 - data/lib/aspera/transfer/error_info.rb +0 -91
 
    
        data/lib/aspera/cli/wizard.rb
    CHANGED
    
    | 
         @@ -1,9 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'aspera/oauth/jwt'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'aspera/assert'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'aspera/cli/plugins/factory'
         
     | 
| 
       4 
6 
     | 
    
         | 
| 
       5 
7 
     | 
    
         
             
            module Aspera
         
     | 
| 
       6 
8 
     | 
    
         
             
              module Cli
         
     | 
| 
      
 9 
     | 
    
         
            +
                # The wizard detects applications and generates a config
         
     | 
| 
       7 
10 
     | 
    
         
             
                class Wizard
         
     | 
| 
       8 
11 
     | 
    
         
             
                  WIZARD_RESULT_KEYS = %i[preset_value test_args].freeze
         
     | 
| 
       9 
12 
     | 
    
         
             
                  DEFAULT_PRIV_KEY_FILENAME = 'my_private_key.pem' # pragma: allowlist secret
         
     | 
| 
         @@ -13,13 +16,17 @@ module Aspera 
     | 
|
| 
       13 
16 
     | 
    
         
             
                  def initialize(parent, main_folder)
         
     | 
| 
       14 
17 
     | 
    
         
             
                    @parent = parent
         
     | 
| 
       15 
18 
     | 
    
         
             
                    @main_folder = main_folder
         
     | 
| 
       16 
     | 
    
         
            -
                    #  
     | 
| 
      
 19 
     | 
    
         
            +
                    # Wizard options
         
     | 
| 
       17 
20 
     | 
    
         
             
                    options.declare(:override, 'Wizard: override existing value', values: :bool, default: :no)
         
     | 
| 
       18 
21 
     | 
    
         
             
                    options.declare(:default, 'Wizard: set as default configuration for specified plugin (also: update)', values: :bool, default: true)
         
     | 
| 
       19 
     | 
    
         
            -
                    options.declare(:test_mode, 'Wizard: skip private key check step', values: :bool, default: false)
         
     | 
| 
       20 
22 
     | 
    
         
             
                    options.declare(:key_path, 'Wizard: path to private key for JWT')
         
     | 
| 
       21 
23 
     | 
    
         
             
                  end
         
     | 
| 
       22 
24 
     | 
    
         | 
| 
      
 25 
     | 
    
         
            +
                  # @return false if in test mode to avoid interactive input
         
     | 
| 
      
 26 
     | 
    
         
            +
                  def required
         
     | 
| 
      
 27 
     | 
    
         
            +
                    !ENV['ASCLI_WIZ_TEST']
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
       23 
30 
     | 
    
         
             
                  def options
         
     | 
| 
       24 
31 
     | 
    
         
             
                    @parent.options
         
     | 
| 
       25 
32 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -28,6 +35,14 @@ module Aspera 
     | 
|
| 
       28 
35 
     | 
    
         
             
                    @parent.formatter
         
     | 
| 
       29 
36 
     | 
    
         
             
                  end
         
     | 
| 
       30 
37 
     | 
    
         | 
| 
      
 38 
     | 
    
         
            +
                  def config
         
     | 
| 
      
 39 
     | 
    
         
            +
                    @parent.config
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                  def check_email(email)
         
     | 
| 
      
 43 
     | 
    
         
            +
                    Aspera.assert(email =~ /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i, type: ParameterError){"Username shall be an email: #{email}"}
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
       31 
46 
     | 
    
         
             
                  # Find a plugin, and issue the "require"
         
     | 
| 
       32 
47 
     | 
    
         
             
                  # @return [Hash] plugin info: { product:, name:, url:, version: }
         
     | 
| 
       33 
48 
     | 
    
         
             
                  def identify_plugins_for_url
         
     | 
| 
         @@ -36,19 +51,19 @@ module Aspera 
     | 
|
| 
       36 
51 
     | 
    
         
             
                    check_only = check_only.to_sym unless check_only.nil?
         
     | 
| 
       37 
52 
     | 
    
         
             
                    found_apps = []
         
     | 
| 
       38 
53 
     | 
    
         
             
                    my_self_plugin_sym = self.class.name.split('::').last.downcase.to_sym
         
     | 
| 
       39 
     | 
    
         
            -
                     
     | 
| 
       40 
     | 
    
         
            -
                      #  
     | 
| 
      
 54 
     | 
    
         
            +
                    Plugins::Factory.instance.plugin_list.each do |plugin_name_sym|
         
     | 
| 
      
 55 
     | 
    
         
            +
                      # No detection for internal plugin
         
     | 
| 
       41 
56 
     | 
    
         
             
                      next if plugin_name_sym.eql?(my_self_plugin_sym)
         
     | 
| 
       42 
57 
     | 
    
         
             
                      next if check_only && !check_only.eql?(plugin_name_sym)
         
     | 
| 
       43 
     | 
    
         
            -
                      #  
     | 
| 
       44 
     | 
    
         
            -
                       
     | 
| 
       45 
     | 
    
         
            -
                      #  
     | 
| 
       46 
     | 
    
         
            -
                      next unless  
     | 
| 
      
 58 
     | 
    
         
            +
                      # Load plugin class
         
     | 
| 
      
 59 
     | 
    
         
            +
                      plugin_klass = Plugins::Factory.instance.plugin_class(plugin_name_sym)
         
     | 
| 
      
 60 
     | 
    
         
            +
                      # Requires detection method
         
     | 
| 
      
 61 
     | 
    
         
            +
                      next unless plugin_klass.respond_to?(:detect)
         
     | 
| 
       47 
62 
     | 
    
         
             
                      detection_info = nil
         
     | 
| 
       48 
63 
     | 
    
         
             
                      begin
         
     | 
| 
       49 
64 
     | 
    
         
             
                        Log.log.debug{"detecting #{plugin_name_sym} at #{app_url}"}
         
     | 
| 
       50 
65 
     | 
    
         
             
                        formatter.long_operation_running("#{plugin_name_sym}\r")
         
     | 
| 
       51 
     | 
    
         
            -
                        detection_info =  
     | 
| 
      
 66 
     | 
    
         
            +
                        detection_info = plugin_klass.detect(app_url)
         
     | 
| 
       52 
67 
     | 
    
         
             
                      rescue OpenSSL::SSL::SSLError => e
         
     | 
| 
       53 
68 
     | 
    
         
             
                        Log.log.warn(e.message)
         
     | 
| 
       54 
69 
     | 
    
         
             
                        Log.log.warn('Use option --insecure=yes to allow unchecked certificate') if e.message.include?('cert')
         
     | 
| 
         @@ -59,8 +74,8 @@ module Aspera 
     | 
|
| 
       59 
74 
     | 
    
         
             
                      next if detection_info.nil?
         
     | 
| 
       60 
75 
     | 
    
         
             
                      Aspera.assert_type(detection_info, Hash)
         
     | 
| 
       61 
76 
     | 
    
         
             
                      Aspera.assert_type(detection_info[:url], String) if detection_info.key?(:url)
         
     | 
| 
       62 
     | 
    
         
            -
                      app_name =  
     | 
| 
       63 
     | 
    
         
            -
                      #  
     | 
| 
      
 77 
     | 
    
         
            +
                      app_name = plugin_klass.respond_to?(:application_name) ? plugin_klass.application_name : plugin_klass.name.split('::').last
         
     | 
| 
      
 78 
     | 
    
         
            +
                      # If there is a redirect, then the detector can override the url.
         
     | 
| 
       64 
79 
     | 
    
         
             
                      found_apps.push({product: plugin_name_sym, name: app_name, url: app_url, version: 'unknown'}.merge(detection_info))
         
     | 
| 
       65 
80 
     | 
    
         
             
                    end
         
     | 
| 
       66 
81 
     | 
    
         
             
                    raise "No known application found at #{app_url}" if found_apps.empty?
         
     | 
| 
         @@ -68,6 +83,41 @@ module Aspera 
     | 
|
| 
       68 
83 
     | 
    
         
             
                    return found_apps
         
     | 
| 
       69 
84 
     | 
    
         
             
                  end
         
     | 
| 
       70 
85 
     | 
    
         | 
| 
      
 86 
     | 
    
         
            +
                  # To be called in public wizard method to get private key
         
     | 
| 
      
 87 
     | 
    
         
            +
                  # @return [Array] Private key path, pub key PEM
         
     | 
| 
      
 88 
     | 
    
         
            +
                  def ask_private_key(user:, url:, page:)
         
     | 
| 
      
 89 
     | 
    
         
            +
                    # Lets see if path to priv key is provided
         
     | 
| 
      
 90 
     | 
    
         
            +
                    private_key_path = options.get_option(:key_path)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    # Give a chance to provide
         
     | 
| 
      
 92 
     | 
    
         
            +
                    if private_key_path.nil?
         
     | 
| 
      
 93 
     | 
    
         
            +
                      formatter.display_status('Path to private RSA key (leave empty to generate):')
         
     | 
| 
      
 94 
     | 
    
         
            +
                      private_key_path = options.get_option(:key_path, mandatory: true).to_s
         
     | 
| 
      
 95 
     | 
    
         
            +
                    end
         
     | 
| 
      
 96 
     | 
    
         
            +
                    # Else generate path
         
     | 
| 
      
 97 
     | 
    
         
            +
                    private_key_path = File.join(@main_folder, DEFAULT_PRIV_KEY_FILENAME) if private_key_path.empty?
         
     | 
| 
      
 98 
     | 
    
         
            +
                    if File.exist?(private_key_path)
         
     | 
| 
      
 99 
     | 
    
         
            +
                      formatter.display_status('Using existing key:')
         
     | 
| 
      
 100 
     | 
    
         
            +
                    else
         
     | 
| 
      
 101 
     | 
    
         
            +
                      formatter.display_status("Generating #{OAuth::Jwt::DEFAULT_PRIV_KEY_LENGTH} bit RSA key...")
         
     | 
| 
      
 102 
     | 
    
         
            +
                      OAuth::Jwt.generate_rsa_private_key(path: private_key_path)
         
     | 
| 
      
 103 
     | 
    
         
            +
                      formatter.display_status('Created key:')
         
     | 
| 
      
 104 
     | 
    
         
            +
                    end
         
     | 
| 
      
 105 
     | 
    
         
            +
                    formatter.display_status(private_key_path)
         
     | 
| 
      
 106 
     | 
    
         
            +
                    private_key_pem = File.read(private_key_path)
         
     | 
| 
      
 107 
     | 
    
         
            +
                    pub_key_pem = OpenSSL::PKey::RSA.new(private_key_pem).public_key.to_s
         
     | 
| 
      
 108 
     | 
    
         
            +
                    options.set_option(:private_key, private_key_pem)
         
     | 
| 
      
 109 
     | 
    
         
            +
                    formatter.display_status("Please Log in as user #{user.red} at: #{url.red}")
         
     | 
| 
      
 110 
     | 
    
         
            +
                    formatter.display_status("Navigate to: #{page}")
         
     | 
| 
      
 111 
     | 
    
         
            +
                    formatter.display_status("Check or update the value to (#{'including BEGIN/END lines'.red}):".blink)
         
     | 
| 
      
 112 
     | 
    
         
            +
                    formatter.display_status(pub_key_pem, hide_secrets: false)
         
     | 
| 
      
 113 
     | 
    
         
            +
                    formatter.display_status('Once updated or validated, press [Enter].')
         
     | 
| 
      
 114 
     | 
    
         
            +
                    Environment.instance.open_uri(url)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    $stdin.gets if required
         
     | 
| 
      
 116 
     | 
    
         
            +
                    private_key_path
         
     | 
| 
      
 117 
     | 
    
         
            +
                  end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                  # Wizard function, creates configuration
         
     | 
| 
      
 120 
     | 
    
         
            +
                  # @param apps [Array] list of detected apps
         
     | 
| 
       71 
121 
     | 
    
         
             
                  def find(apps)
         
     | 
| 
       72 
122 
     | 
    
         
             
                    identification = if apps.length.eql?(1)
         
     | 
| 
       73 
123 
     | 
    
         
             
                      Log.log.debug{"Detected: #{identification}"}
         
     | 
| 
         @@ -82,49 +132,18 @@ module Aspera 
     | 
|
| 
       82 
132 
     | 
    
         
             
                    Log.dump(:identification, identification)
         
     | 
| 
       83 
133 
     | 
    
         
             
                    wiz_url = identification[:url]
         
     | 
| 
       84 
134 
     | 
    
         
             
                    formatter.display_status("Using: #{identification[:name]} at #{wiz_url}".bold)
         
     | 
| 
       85 
     | 
    
         
            -
                    #  
     | 
| 
      
 135 
     | 
    
         
            +
                    # Set url for instantiation of plugin
         
     | 
| 
       86 
136 
     | 
    
         
             
                    options.add_option_preset({url: wiz_url}, 'wizard')
         
     | 
| 
       87 
     | 
    
         
            -
                    #  
     | 
| 
       88 
     | 
    
         
            -
                     
     | 
| 
       89 
     | 
    
         
            -
                    Aspera.assert( 
     | 
| 
      
 137 
     | 
    
         
            +
                    # Instantiate plugin: command line options will be known, e.g. private_key, and wizard can be called
         
     | 
| 
      
 138 
     | 
    
         
            +
                    plugin_instance = Plugins::Factory.instance.plugin_class(identification[:product]).new(context: @parent.context)
         
     | 
| 
      
 139 
     | 
    
         
            +
                    Aspera.assert(plugin_instance.respond_to?(:wizard), type: Cli::BadArgument) do
         
     | 
| 
       90 
140 
     | 
    
         
             
                      "Detected: #{identification[:product]}, but this application has no wizard"
         
     | 
| 
       91 
141 
     | 
    
         
             
                    end
         
     | 
| 
       92 
     | 
    
         
            -
                    #  
     | 
| 
       93 
     | 
    
         
            -
                     
     | 
| 
       94 
     | 
    
         
            -
                    wiz_params = {
         
     | 
| 
       95 
     | 
    
         
            -
                      object: plugin_instance
         
     | 
| 
       96 
     | 
    
         
            -
                    }
         
     | 
| 
       97 
     | 
    
         
            -
                    # is private key needed ?
         
     | 
| 
       98 
     | 
    
         
            -
                    if options.known_options.key?(:private_key) &&
         
     | 
| 
       99 
     | 
    
         
            -
                        (!wiz_plugin_class.respond_to?(:private_key_required?) || wiz_plugin_class.private_key_required?(wiz_url))
         
     | 
| 
       100 
     | 
    
         
            -
                      # lets see if path to priv key is provided
         
     | 
| 
       101 
     | 
    
         
            -
                      private_key_path = options.get_option(:key_path)
         
     | 
| 
       102 
     | 
    
         
            -
                      # give a chance to provide
         
     | 
| 
       103 
     | 
    
         
            -
                      if private_key_path.nil?
         
     | 
| 
       104 
     | 
    
         
            -
                        formatter.display_status('Please provide the path to your private RSA key, or nothing to generate one:')
         
     | 
| 
       105 
     | 
    
         
            -
                        private_key_path = options.get_option(:key_path, mandatory: true).to_s
         
     | 
| 
       106 
     | 
    
         
            -
                      end
         
     | 
| 
       107 
     | 
    
         
            -
                      # else generate path
         
     | 
| 
       108 
     | 
    
         
            -
                      private_key_path = File.join(@main_folder, DEFAULT_PRIV_KEY_FILENAME) if private_key_path.empty?
         
     | 
| 
       109 
     | 
    
         
            -
                      if File.exist?(private_key_path)
         
     | 
| 
       110 
     | 
    
         
            -
                        formatter.display_status('Using existing key:')
         
     | 
| 
       111 
     | 
    
         
            -
                      else
         
     | 
| 
       112 
     | 
    
         
            -
                        formatter.display_status("Generating #{OAuth::Jwt::DEFAULT_PRIV_KEY_LENGTH} bit RSA key...")
         
     | 
| 
       113 
     | 
    
         
            -
                        OAuth::Jwt.generate_rsa_private_key(path: private_key_path)
         
     | 
| 
       114 
     | 
    
         
            -
                        formatter.display_status('Created key:')
         
     | 
| 
       115 
     | 
    
         
            -
                      end
         
     | 
| 
       116 
     | 
    
         
            -
                      formatter.display_status(private_key_path)
         
     | 
| 
       117 
     | 
    
         
            -
                      private_key_pem = File.read(private_key_path)
         
     | 
| 
       118 
     | 
    
         
            -
                      options.set_option(:private_key, private_key_pem)
         
     | 
| 
       119 
     | 
    
         
            -
                      wiz_params[:private_key_path] = private_key_path
         
     | 
| 
       120 
     | 
    
         
            -
                      wiz_params[:pub_key_pem] = OpenSSL::PKey::RSA.new(private_key_pem).public_key.to_s
         
     | 
| 
       121 
     | 
    
         
            -
                    end
         
     | 
| 
       122 
     | 
    
         
            -
                    Log.dump(:wiz_params, wiz_params)
         
     | 
| 
       123 
     | 
    
         
            -
                    # finally, call the wizard
         
     | 
| 
       124 
     | 
    
         
            -
                    wizard_result = wiz_plugin_class.wizard(**wiz_params)
         
     | 
| 
      
 142 
     | 
    
         
            +
                    # Call the wizard
         
     | 
| 
      
 143 
     | 
    
         
            +
                    wizard_result = plugin_instance.wizard(self, wiz_url)
         
     | 
| 
       125 
144 
     | 
    
         
             
                    Log.log.debug{"wizard result: #{wizard_result}"}
         
     | 
| 
       126 
145 
     | 
    
         
             
                    Aspera.assert(WIZARD_RESULT_KEYS.eql?(wizard_result.keys.sort)){"missing or extra keys in wizard result: #{wizard_result.keys}"}
         
     | 
| 
       127 
     | 
    
         
            -
                    #  
     | 
| 
      
 146 
     | 
    
         
            +
                    # Get preset name from user or default
         
     | 
| 
       128 
147 
     | 
    
         
             
                    if wiz_preset_name.empty?
         
     | 
| 
       129 
148 
     | 
    
         
             
                      elements = [
         
     | 
| 
       130 
149 
     | 
    
         
             
                        identification[:product],
         
     | 
| 
         @@ -133,27 +152,17 @@ module Aspera 
     | 
|
| 
       133 
152 
     | 
    
         
             
                      elements.push(options.get_option(:username, mandatory: true)) unless wizard_result[:preset_value].key?(:link) rescue nil
         
     | 
| 
       134 
153 
     | 
    
         
             
                      wiz_preset_name = elements.join('_').strip.downcase.gsub(/[^a-z0-9]/, '_').squeeze('_')
         
     | 
| 
       135 
154 
     | 
    
         
             
                    end
         
     | 
| 
       136 
     | 
    
         
            -
                    # test mode does not change conf file
         
     | 
| 
       137 
     | 
    
         
            -
                    return Main.result_single_object(wizard_result) if options.get_option(:test_mode)
         
     | 
| 
       138 
155 
     | 
    
         
             
                    # Write configuration file
         
     | 
| 
       139 
156 
     | 
    
         
             
                    formatter.display_status("Preparing preset: #{wiz_preset_name}")
         
     | 
| 
       140 
     | 
    
         
            -
                    #  
     | 
| 
       141 
     | 
    
         
            -
                    @config_presets[CONF_PRESET_DEFAULTS] ||= {}
         
     | 
| 
      
 157 
     | 
    
         
            +
                    # Init defaults if necessary
         
     | 
| 
       142 
158 
     | 
    
         
             
                    option_override = options.get_option(:override, mandatory: true)
         
     | 
| 
       143 
     | 
    
         
            -
                     
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
       145 
     | 
    
         
            -
                    raise Cli::Error, "Preset already exists: #{wiz_preset_name}  (use --override=yes or --id=<name>)" \
         
     | 
| 
       146 
     | 
    
         
            -
                      if !option_override && @config_presets.key?(wiz_preset_name)
         
     | 
| 
       147 
     | 
    
         
            -
                    @config_presets[wiz_preset_name] = wizard_result[:preset_value].stringify_keys
         
     | 
| 
      
 159 
     | 
    
         
            +
                    option_default = options.get_option(:default, mandatory: true)
         
     | 
| 
      
 160 
     | 
    
         
            +
                    config.defaults_set(identification[:product], wiz_preset_name, wizard_result[:preset_value].stringify_keys, option_default, option_override)
         
     | 
| 
       148 
161 
     | 
    
         
             
                    test_args = wizard_result[:test_args]
         
     | 
| 
       149 
     | 
    
         
            -
                     
     | 
| 
       150 
     | 
    
         
            -
                      formatter.display_status("Setting config preset as default for #{identification[:product]}")
         
     | 
| 
       151 
     | 
    
         
            -
                      @config_presets[CONF_PRESET_DEFAULTS][identification[:product].to_s] = wiz_preset_name
         
     | 
| 
       152 
     | 
    
         
            -
                    else
         
     | 
| 
       153 
     | 
    
         
            -
                      test_args = "-P#{wiz_preset_name} #{test_args}"
         
     | 
| 
       154 
     | 
    
         
            -
                    end
         
     | 
| 
      
 162 
     | 
    
         
            +
                    test_args = "-P#{wiz_preset_name} #{test_args}" unless option_default
         
     | 
| 
       155 
163 
     | 
    
         
             
                    # TODO: actually test the command
         
     | 
| 
       156 
     | 
    
         
            -
                     
     | 
| 
      
 164 
     | 
    
         
            +
                    test_cmd = "#{Info::CMD_NAME} #{identification[:product]} #{test_args}"
         
     | 
| 
      
 165 
     | 
    
         
            +
                    return Main.result_status("You can test with:\n#{test_cmd.red}")
         
     | 
| 
       157 
166 
     | 
    
         
             
                  end
         
     | 
| 
       158 
167 
     | 
    
         
             
                end
         
     | 
| 
       159 
168 
     | 
    
         
             
              end
         
     | 
    
        data/lib/aspera/colors.rb
    CHANGED
    
    | 
         @@ -57,10 +57,16 @@ class String 
     | 
|
| 
       57 
57 
     | 
    
         
             
                  define_method(name){self}
         
     | 
| 
       58 
58 
     | 
    
         
             
                end
         
     | 
| 
       59 
59 
     | 
    
         
             
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
       60 
61 
     | 
    
         
             
              # Transform capitalized to snake case
         
     | 
| 
       61 
62 
     | 
    
         
             
              def capital_to_snake
         
     | 
| 
       62 
63 
     | 
    
         
             
                return gsub(/([a-z\d])([A-Z])/, '\1_\2')
         
     | 
| 
       63 
64 
     | 
    
         
             
                    .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
         
     | 
| 
       64 
65 
     | 
    
         
             
                    .downcase
         
     | 
| 
       65 
66 
     | 
    
         
             
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              # Transform snake case to capitalized
         
     | 
| 
      
 69 
     | 
    
         
            +
              def snake_to_capital
         
     | 
| 
      
 70 
     | 
    
         
            +
                split('_').map(&:capitalize).join
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
       66 
72 
     | 
    
         
             
            end
         
     | 
| 
         @@ -4,43 +4,31 @@ require 'aspera/log' 
     | 
|
| 
       4 
4 
     | 
    
         
             
            require 'aspera/assert'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require 'yaml'
         
     | 
| 
       6 
6 
     | 
    
         
             
            module Aspera
         
     | 
| 
       7 
     | 
    
         
            -
              #  
     | 
| 
       8 
     | 
    
         
            -
              #  
     | 
| 
       9 
     | 
    
         
            -
              # process_param is called repeatedly with all known parameters
         
     | 
| 
       10 
     | 
    
         
            -
              # add_env_args is called to get resulting param list and env var (also checks that all params were used)
         
     | 
| 
      
 7 
     | 
    
         
            +
              # Helper class to build command line from a parameter list (key-value hash)
         
     | 
| 
      
 8 
     | 
    
         
            +
              # Constructor takes hash: `{ 'param1':'value1', ...}`
         
     | 
| 
      
 9 
     | 
    
         
            +
              # `process_param` is called repeatedly with all known parameters
         
     | 
| 
      
 10 
     | 
    
         
            +
              # `add_env_args` is called to get resulting param list and env var (also checks that all params were used)
         
     | 
| 
       11 
11 
     | 
    
         
             
              class CommandLineBuilder
         
     | 
| 
       12 
     | 
    
         
            -
                #  
     | 
| 
       13 
     | 
    
         
            -
                 
     | 
| 
       14 
     | 
    
         
            -
                #  
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                #  
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                   
     | 
| 
       29 
     | 
    
         
            -
                   
     | 
| 
       30 
     | 
    
         
            -
                   
     | 
| 
       31 
     | 
    
         
            -
                   
     | 
| 
       32 
     | 
    
         
            -
                  items
         
     | 
| 
       33 
     | 
    
         
            -
                  properties
         
     | 
| 
       34 
     | 
    
         
            -
                  required
         
     | 
| 
       35 
     | 
    
         
            -
                  $comment
         
     | 
| 
       36 
     | 
    
         
            -
                  x-cli-envvar
         
     | 
| 
       37 
     | 
    
         
            -
                  x-cli-option
         
     | 
| 
       38 
     | 
    
         
            -
                  x-cli-switch
         
     | 
| 
       39 
     | 
    
         
            -
                  x-cli-special
         
     | 
| 
       40 
     | 
    
         
            -
                  x-cli-convert
         
     | 
| 
       41 
     | 
    
         
            -
                  x-agents
         
     | 
| 
       42 
     | 
    
         
            -
                  x-ts-name
         
     | 
| 
       43 
     | 
    
         
            -
                  x-deprecation
         
     | 
| 
      
 12 
     | 
    
         
            +
                # Supported keys in JSON schema
         
     | 
| 
      
 13 
     | 
    
         
            +
                PROPERTY_KEYS = [
         
     | 
| 
      
 14 
     | 
    
         
            +
                  'description',    # [String]       Description
         
     | 
| 
      
 15 
     | 
    
         
            +
                  'type',           # [String,Array] Accepted type(s) for non-enum
         
     | 
| 
      
 16 
     | 
    
         
            +
                  'default',        # [String]       Default value if not specified
         
     | 
| 
      
 17 
     | 
    
         
            +
                  'enum',           # [Array]        Set with list of values for enum types accepted in transfer spec
         
     | 
| 
      
 18 
     | 
    
         
            +
                  'items',          # [Array]
         
     | 
| 
      
 19 
     | 
    
         
            +
                  'properties',     # [Array]
         
     | 
| 
      
 20 
     | 
    
         
            +
                  'required',       # [Array]
         
     | 
| 
      
 21 
     | 
    
         
            +
                  '$comment',       # [String]
         
     | 
| 
      
 22 
     | 
    
         
            +
                  'x-cli-envvar',   # [String]       Name of env var
         
     | 
| 
      
 23 
     | 
    
         
            +
                  'x-cli-option',   # [String]       Command line option (starts with "-")
         
     | 
| 
      
 24 
     | 
    
         
            +
                  'x-cli-short',    # [String]       Command line option (starts with "-")
         
     | 
| 
      
 25 
     | 
    
         
            +
                  'x-cli-switch',   # [Bool]         `true` if option has no arg, else by default option has a value
         
     | 
| 
      
 26 
     | 
    
         
            +
                  'x-cli-special',  # [Bool]         `true` if special handling (deferred)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  'x-cli-convert',  # [String,Hash]  Method name for Convert object or Conversion for enum ts to arg
         
     | 
| 
      
 28 
     | 
    
         
            +
                  'x-agents',       # [Array]        Supported agents (for doc only), if not specified: all
         
     | 
| 
      
 29 
     | 
    
         
            +
                  'x-ts-name',      # [Bool,String]  (async) true if same name in transfer spec, else real name in transfer spec, else ignored
         
     | 
| 
      
 30 
     | 
    
         
            +
                  'x-ts-convert',   # [String]       (async) Name of methods to convert value from transfer spec to `conf` API.
         
     | 
| 
      
 31 
     | 
    
         
            +
                  'x-deprecation'   # [String]       Deprecation message for doc
         
     | 
| 
       44 
32 
     | 
    
         
             
                ].freeze
         
     | 
| 
       45 
33 
     | 
    
         | 
| 
       46 
34 
     | 
    
         
             
                CLI_AGENT = 'direct'
         
     | 
| 
         @@ -53,17 +41,23 @@ module Aspera 
     | 
|
| 
       53 
41 
     | 
    
         
             
                    !properties.key?('x-agents') || properties['x-agents'].include?(agent)
         
     | 
| 
       54 
42 
     | 
    
         
             
                  end
         
     | 
| 
       55 
43 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
                  #  
     | 
| 
       57 
     | 
    
         
            -
                   
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
      
 44 
     | 
    
         
            +
                  # Fill default values for some fields in the schema
         
     | 
| 
      
 45 
     | 
    
         
            +
                  # @param schema [Hash] The JSON schema
         
     | 
| 
      
 46 
     | 
    
         
            +
                  def validate_schema(schema, ascp: false)
         
     | 
| 
      
 47 
     | 
    
         
            +
                    schema['properties'].each do |name, info|
         
     | 
| 
       59 
48 
     | 
    
         
             
                      Aspera.assert_type(info, Hash){"#{info.class} for #{name}"}
         
     | 
| 
       60 
49 
     | 
    
         
             
                      unsupported_keys = info.keys - PROPERTY_KEYS
         
     | 
| 
       61 
50 
     | 
    
         
             
                      Aspera.assert(unsupported_keys.empty?){"Unsupported definition keys: #{unsupported_keys}"}
         
     | 
| 
       62 
     | 
    
         
            -
                      #  
     | 
| 
       63 
     | 
    
         
            -
                      info['type'] ||= info['x-cli-switch'] ? 'boolean' : 'string'
         
     | 
| 
       64 
     | 
    
         
            -
                       
     | 
| 
       65 
     | 
    
         
            -
                      info[' 
     | 
| 
      
 51 
     | 
    
         
            +
                      # By default : string, unless it's without arg (switch)
         
     | 
| 
      
 52 
     | 
    
         
            +
                      # info['type'] ||= info['x-cli-switch'] ? 'boolean' : 'string'
         
     | 
| 
      
 53 
     | 
    
         
            +
                      Aspera.assert(info.key?('type') || info.key?('enum')){"Missing type for #{name} in #{schema['description']}"}
         
     | 
| 
      
 54 
     | 
    
         
            +
                      Aspera.assert(info['type'].eql?('boolean')){"switch must be bool: #{name}"} if info['x-cli-switch']
         
     | 
| 
      
 55 
     | 
    
         
            +
                      # Add default cli option name if not present, and if supported in "direct".
         
     | 
| 
      
 56 
     | 
    
         
            +
                      info['x-cli-option'] = "--#{name.to_s.tr('_', '-')}" if info['x-cli-option'].eql?(true) || (info['x-cli-switch'].eql?(true) && !info.key?('x-cli-option'))
         
     | 
| 
      
 57 
     | 
    
         
            +
                      Aspera.assert(%w[x-cli-option x-cli-envvar x-cli-special].any?{ |i| info.key?(i)}, type: :warn){name} if ascp && supported_by_agent(CLI_AGENT, info)
         
     | 
| 
      
 58 
     | 
    
         
            +
                      # info['x-cli-option'] = "--#{name.to_s.tr('_', '-')}" if ascp && !info.key?('x-cli-option') && !info['x-cli-envvar'] && (info.key?('x-cli-switch') || supported_by_agent(CLI_AGENT, info))
         
     | 
| 
       66 
59 
     | 
    
         
             
                      info.freeze
         
     | 
| 
      
 60 
     | 
    
         
            +
                      validate_schema(info, ascp: ascp) if info['type'].eql?('object') && info['properties']
         
     | 
| 
       67 
61 
     | 
    
         
             
                    end
         
     | 
| 
       68 
62 
     | 
    
         
             
                  end
         
     | 
| 
       69 
63 
     | 
    
         | 
| 
         @@ -98,10 +92,10 @@ module Aspera 
     | 
|
| 
       98 
92 
     | 
    
         
             
                # Add processed parameters to env and args, warns about unused parameters
         
     | 
| 
       99 
93 
     | 
    
         
             
                # @param [Hash] env_args with :env and :args
         
     | 
| 
       100 
94 
     | 
    
         
             
                def add_env_args(env_args)
         
     | 
| 
       101 
     | 
    
         
            -
                  Log. 
     | 
| 
      
 95 
     | 
    
         
            +
                  Log.dump(:env_args, @result)
         
     | 
| 
       102 
96 
     | 
    
         
             
                  # warn about non translated arguments
         
     | 
| 
       103 
97 
     | 
    
         
             
                  @object.each_pair do |name, value|
         
     | 
| 
       104 
     | 
    
         
            -
                    Log.log.warn{ 
     | 
| 
      
 98 
     | 
    
         
            +
                    Log.log.warn{"Unknown transfer spec parameter: #{name} = \"#{value}\""} unless @processed_parameters.include?(name)
         
     | 
| 
       105 
99 
     | 
    
         
             
                  end
         
     | 
| 
       106 
100 
     | 
    
         
             
                  # set result
         
     | 
| 
       107 
101 
     | 
    
         
             
                  env_args[:env].merge!(@result[:env])
         
     | 
| 
         @@ -109,9 +103,10 @@ module Aspera 
     | 
|
| 
       109 
103 
     | 
    
         
             
                  return
         
     | 
| 
       110 
104 
     | 
    
         
             
                end
         
     | 
| 
       111 
105 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                #  
     | 
| 
       113 
     | 
    
         
            -
                def add_command_line_options(options)
         
     | 
| 
       114 
     | 
    
         
            -
                   
     | 
| 
      
 106 
     | 
    
         
            +
                # Add options directly to command line
         
     | 
| 
      
 107 
     | 
    
         
            +
                def add_command_line_options(*options)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  options = options.first if options.first.is_a?(Array) && options.length.eql?(1)
         
     | 
| 
      
 109 
     | 
    
         
            +
                  Aspera.assert_type(options, Array)
         
     | 
| 
       115 
110 
     | 
    
         
             
                  options.each{ |o| @result[:args].push(o.to_s)}
         
     | 
| 
       116 
111 
     | 
    
         
             
                end
         
     | 
| 
       117 
112 
     | 
    
         | 
| 
         @@ -198,13 +193,13 @@ module Aspera 
     | 
|
| 
       198 
193 
     | 
    
         
             
                    else Aspera.error_unexpected_value(parameter_value){name}
         
     | 
| 
       199 
194 
     | 
    
         
             
                    end
         
     | 
| 
       200 
195 
     | 
    
         
             
                    # add_param = !add_param if properties[:add_on_false]
         
     | 
| 
       201 
     | 
    
         
            -
                    add_command_line_options( 
     | 
| 
      
 196 
     | 
    
         
            +
                    add_command_line_options(properties['x-cli-option']) if add_param
         
     | 
| 
       202 
197 
     | 
    
         
             
                  else
         
     | 
| 
       203 
198 
     | 
    
         
             
                    # transform into command line option with value
         
     | 
| 
       204 
199 
     | 
    
         
             
                    # parameter_value=parameter_value.to_s if parameter_value.is_a?(Integer)
         
     | 
| 
       205 
200 
     | 
    
         
             
                    parameter_value = [parameter_value] unless parameter_value.is_a?(Array)
         
     | 
| 
       206 
201 
     | 
    
         
             
                    # if transfer_spec value is an array, applies option many times
         
     | 
| 
       207 
     | 
    
         
            -
                    parameter_value.each{ |v| add_command_line_options( 
     | 
| 
      
 202 
     | 
    
         
            +
                    parameter_value.each{ |v| add_command_line_options(properties['x-cli-option'], v)}
         
     | 
| 
       208 
203 
     | 
    
         
             
                  end
         
     | 
| 
       209 
204 
     | 
    
         
             
                end
         
     | 
| 
       210 
205 
     | 
    
         
             
              end
         
     | 
    
        data/lib/aspera/coverage.rb
    CHANGED
    
    | 
         @@ -5,7 +5,7 @@ if ENV.key?('ENABLE_COVERAGE') 
     | 
|
| 
       5 
5 
     | 
    
         
             
              require 'simplecov'
         
     | 
| 
       6 
6 
     | 
    
         
             
              require 'securerandom'
         
     | 
| 
       7 
7 
     | 
    
         
             
              # compute development top folder based on this source location
         
     | 
| 
       8 
     | 
    
         
            -
              development_root =  
     | 
| 
      
 8 
     | 
    
         
            +
              development_root = File.dirname(File.realpath(__FILE__), 3)
         
     | 
| 
       9 
9 
     | 
    
         
             
              SimpleCov.root(development_root)
         
     | 
| 
       10 
10 
     | 
    
         
             
              SimpleCov.enable_for_subprocesses if SimpleCov.respond_to?(:enable_for_subprocesses)
         
     | 
| 
       11 
11 
     | 
    
         
             
              # keep cache data for 1 day (must be longer that time to run the whole test suite)
         
     | 
| 
         @@ -19,7 +19,7 @@ module Aspera 
     | 
|
| 
       19 
19 
     | 
    
         
             
                # @return [String] decoded data
         
     | 
| 
       20 
20 
     | 
    
         
             
                def item(name)
         
     | 
| 
       21 
21 
     | 
    
         
             
                  index = ELEMENTS.index(name)
         
     | 
| 
       22 
     | 
    
         
            -
                  raise  
     | 
| 
      
 22 
     | 
    
         
            +
                  raise ParameterError, "Unknown data item #{name} (#{name.class})" unless index
         
     | 
| 
       23 
23 
     | 
    
         
             
                  raw_data = data(START_INDEX + index)
         
     | 
| 
       24 
24 
     | 
    
         
             
                  case name
         
     | 
| 
       25 
25 
     | 
    
         
             
                  when :dsa, :rsa
         
     | 
    
        data/lib/aspera/environment.rb
    CHANGED
    
    | 
         @@ -38,6 +38,8 @@ module Aspera 
     | 
|
| 
       38 
38 
     | 
    
         
             
                WINDOWS_FILENAME_INVALID_CHARACTERS = '<>:"/\\|?*'
         
     | 
| 
       39 
39 
     | 
    
         
             
                REPLACE_CHARACTER = '_'
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
      
 41 
     | 
    
         
            +
                RB_EXT = '.rb'
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
       41 
43 
     | 
    
         
             
                class << self
         
     | 
| 
       42 
44 
     | 
    
         
             
                  def ruby_version
         
     | 
| 
       43 
45 
     | 
    
         
             
                    return RbConfig::CONFIG['RUBY_PROGRAM_VERSION']
         
     | 
| 
         @@ -186,7 +188,7 @@ module Aspera 
     | 
|
| 
       186 
188 
     | 
    
         
             
                  end
         
     | 
| 
       187 
189 
     | 
    
         
             
                end
         
     | 
| 
       188 
190 
     | 
    
         
             
                attr_accessor :url_method, :file_illegal_characters
         
     | 
| 
       189 
     | 
    
         
            -
                attr_reader :os, :cpu, : 
     | 
| 
      
 191 
     | 
    
         
            +
                attr_reader :os, :cpu, :default_gui_mode
         
     | 
| 
       190 
192 
     | 
    
         | 
| 
       191 
193 
     | 
    
         
             
                def initialize
         
     | 
| 
       192 
194 
     | 
    
         
             
                  initialize_fields
         
     | 
| 
         @@ -218,7 +220,7 @@ module Aspera 
     | 
|
| 
       218 
220 
     | 
    
         
             
                      CPU_ARM64
         
     | 
| 
       219 
221 
     | 
    
         
             
                    else Aspera.error_unexpected_value(RbConfig::CONFIG['host_cpu']){'host_cpu'}
         
     | 
| 
       220 
222 
     | 
    
         
             
                    end
         
     | 
| 
       221 
     | 
    
         
            -
                  @executable_extension = @os.eql?(OS_WINDOWS) ? 'exe' : nil
         
     | 
| 
      
 223 
     | 
    
         
            +
                  @executable_extension = @os.eql?(OS_WINDOWS) ? '.exe' : nil
         
     | 
| 
       222 
224 
     | 
    
         
             
                  # :text or :graphical depending on the environment
         
     | 
| 
       223 
225 
     | 
    
         
             
                  @default_gui_mode =
         
     | 
| 
       224 
226 
     | 
    
         
             
                    if [Environment::OS_WINDOWS, Environment::OS_MACOS].include?(os) ||
         
     | 
| 
         @@ -239,8 +241,10 @@ module Aspera 
     | 
|
| 
       239 
241 
     | 
    
         
             
                  "#{@os}-#{@cpu}"
         
     | 
| 
       240 
242 
     | 
    
         
             
                end
         
     | 
| 
       241 
243 
     | 
    
         | 
| 
       242 
     | 
    
         
            -
                # executable file extension for current OS
         
     | 
| 
       243 
     | 
    
         
            -
                 
     | 
| 
      
 244 
     | 
    
         
            +
                # Add executable file extension (e.g. ".exe") for current OS
         
     | 
| 
      
 245 
     | 
    
         
            +
                # @param name [String,nil] Path or file name
         
     | 
| 
      
 246 
     | 
    
         
            +
                # @return [String] Executable name with extension
         
     | 
| 
      
 247 
     | 
    
         
            +
                def exe_file(name = nil)
         
     | 
| 
       244 
248 
     | 
    
         
             
                  return name unless @executable_extension
         
     | 
| 
       245 
249 
     | 
    
         
             
                  return "#{name}#{@executable_extension}"
         
     | 
| 
       246 
250 
     | 
    
         
             
                end
         
     | 
| 
         @@ -311,11 +315,11 @@ module Aspera 
     | 
|
| 
       311 
315 
     | 
    
         
             
                # @return [String] A file name safe to use on file system
         
     | 
| 
       312 
316 
     | 
    
         
             
                def sanitized_filename(filename)
         
     | 
| 
       313 
317 
     | 
    
         
             
                  safe_char = safe_filename_character
         
     | 
| 
       314 
     | 
    
         
            -
                  # Windows does not allow file name 
     | 
| 
       315 
     | 
    
         
            -
                  #  
     | 
| 
       316 
     | 
    
         
            -
                   
     | 
| 
       317 
     | 
    
         
            -
             
     | 
| 
       318 
     | 
    
         
            -
             
     | 
| 
      
 318 
     | 
    
         
            +
                  # Windows does not allow file name:
         
     | 
| 
      
 319 
     | 
    
         
            +
                  # - with control characters anywhere
         
     | 
| 
      
 320 
     | 
    
         
            +
                  # - ending with space or dot
         
     | 
| 
      
 321 
     | 
    
         
            +
                  filename = filename.gsub(/[\x00-\x1F\x7F]/, safe_char)
         
     | 
| 
      
 322 
     | 
    
         
            +
                  filename = filename.chop while filename.end_with?(' ', '.')
         
     | 
| 
       319 
323 
     | 
    
         
             
                  if @file_illegal_characters&.size.to_i >= 2
         
     | 
| 
       320 
324 
     | 
    
         
             
                    # replace all illegal characters with safe_char
         
     | 
| 
       321 
325 
     | 
    
         
             
                    filename = filename.tr(@file_illegal_characters[1..-1], safe_char)
         
     | 
    
        data/lib/aspera/faspex_gw.rb
    CHANGED
    
    | 
         @@ -8,10 +8,12 @@ require 'json' 
     | 
|
| 
       8 
8 
     | 
    
         
             
            module Aspera
         
     | 
| 
       9 
9 
     | 
    
         
             
              # Simulate the Faspex 4 /send API and creates a package on Aspera on Cloud or Faspex 5
         
     | 
| 
       10 
10 
     | 
    
         
             
              class Faspex4GWServlet < WEBrick::HTTPServlet::AbstractServlet
         
     | 
| 
      
 11 
     | 
    
         
            +
                AOC_API = 'Aspera::Api::AoC'
         
     | 
| 
      
 12 
     | 
    
         
            +
                FX_API = 'Aspera::Api::Faspex'
         
     | 
| 
       11 
13 
     | 
    
         
             
                # @param app_api     [Rest]   API object
         
     | 
| 
       12 
14 
     | 
    
         
             
                # @param app_context [String] workspace id (aoc only)
         
     | 
| 
       13 
15 
     | 
    
         
             
                def initialize(server, app_api, app_context)
         
     | 
| 
       14 
     | 
    
         
            -
                  Aspera.assert_values(app_api.class.name, [ 
     | 
| 
      
 16 
     | 
    
         
            +
                  Aspera.assert_values(app_api.class.name, [AOC_API, FX_API])
         
     | 
| 
       15 
17 
     | 
    
         
             
                  super(server)
         
     | 
| 
       16 
18 
     | 
    
         
             
                  @app_api = app_api
         
     | 
| 
       17 
19 
     | 
    
         
             
                  @app_context = app_context
         
     | 
| 
         @@ -49,7 +51,7 @@ module Aspera 
     | 
|
| 
       49 
51 
     | 
    
         
             
                  transfer_spec = @app_api.call(
         
     | 
| 
       50 
52 
     | 
    
         
             
                    operation:    'POST',
         
     | 
| 
       51 
53 
     | 
    
         
             
                    subpath:      "packages/#{package['id']}/transfer_spec/upload",
         
     | 
| 
       52 
     | 
    
         
            -
                    query:        {transfer_type:  
     | 
| 
      
 54 
     | 
    
         
            +
                    query:        {transfer_type: Api::Faspex::TRANSFER_CONNECT},
         
     | 
| 
       53 
55 
     | 
    
         
             
                    content_type: Rest::MIME_JSON,
         
     | 
| 
       54 
56 
     | 
    
         
             
                    body:         {paths: [{'destination'=>'/'}]},
         
     | 
| 
       55 
57 
     | 
    
         
             
                    headers:      {'Accept' => Rest::MIME_JSON}
         
     | 
| 
         @@ -72,9 +74,9 @@ module Aspera 
     | 
|
| 
       72 
74 
     | 
    
         
             
                      # compare string, as class is not yet known here
         
     | 
| 
       73 
75 
     | 
    
         
             
                      faspex_package_create_result =
         
     | 
| 
       74 
76 
     | 
    
         
             
                        case @app_api.class.name
         
     | 
| 
       75 
     | 
    
         
            -
                        when  
     | 
| 
      
 77 
     | 
    
         
            +
                        when AOC_API
         
     | 
| 
       76 
78 
     | 
    
         
             
                          faspex4_send_to_aoc(faspex_pkg_parameters)
         
     | 
| 
       77 
     | 
    
         
            -
                        when  
     | 
| 
      
 79 
     | 
    
         
            +
                        when FX_API
         
     | 
| 
       78 
80 
     | 
    
         
             
                          faspex4_send_to_faspex5(faspex_pkg_parameters)
         
     | 
| 
       79 
81 
     | 
    
         
             
                        else Aspera.error_unexpected_value(@app_api.class.name)
         
     | 
| 
       80 
82 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -8,7 +8,7 @@ require 'aspera/log' 
     | 
|
| 
       8 
8 
     | 
    
         
             
            require 'aspera/assert'
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
            module Aspera
         
     | 
| 
       11 
     | 
    
         
            -
              #  
     | 
| 
      
 11 
     | 
    
         
            +
              # Start a Faspex-4 style post-processing script using Faspex-5 webhook
         
     | 
| 
       12 
12 
     | 
    
         
             
              class Faspex4PostProcServlet < WEBrick::HTTPServlet::AbstractServlet
         
     | 
| 
       13 
13 
     | 
    
         
             
                ALLOWED_PARAMETERS = %i[root script_folder fail_on_error timeout_seconds].freeze
         
     | 
| 
       14 
14 
     | 
    
         
             
                def initialize(server, parameters)
         
     | 
| 
         @@ -73,7 +73,7 @@ module Aspera 
     | 
|
| 
       73 
73 
     | 
    
         
             
                      end
         
     | 
| 
       74 
74 
     | 
    
         | 
| 
       75 
75 
     | 
    
         
             
                      def list(options = {})
         
     | 
| 
       76 
     | 
    
         
            -
                        Aspera.assert_values(options[:domain], DOMAINS, type:  
     | 
| 
      
 76 
     | 
    
         
            +
                        Aspera.assert_values(options[:domain], DOMAINS, type: ParameterError){'domain'} unless options[:domain].nil?
         
     | 
| 
       77 
77 
     | 
    
         
             
                        key_chains(execute('list-keychains', options, LIST_OPTIONS))
         
     | 
| 
       78 
78 
     | 
    
         
             
                      end
         
     | 
| 
       79 
79 
     | 
    
         |