aspera-cli 4.18.1 → 4.20.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.
- checksums.yaml +4 -4
 - checksums.yaml.gz.sig +0 -0
 - data/CHANGELOG.md +33 -0
 - data/CONTRIBUTING.md +17 -12
 - data/README.md +396 -185
 - data/bin/asession +26 -19
 - data/examples/build_exec +74 -0
 - data/examples/{rubyc → build_exec_rubyc} +18 -2
 - data/examples/get_proto_file.rb +7 -0
 - data/lib/aspera/agent/alpha.rb +8 -8
 - data/lib/aspera/agent/base.rb +4 -18
 - data/lib/aspera/agent/connect.rb +14 -13
 - data/lib/aspera/agent/direct.rb +123 -120
 - data/lib/aspera/agent/httpgw.rb +2 -3
 - data/lib/aspera/agent/node.rb +10 -10
 - data/lib/aspera/agent/trsdk.rb +17 -20
 - data/lib/aspera/api/alee.rb +15 -0
 - data/lib/aspera/api/aoc.rb +128 -99
 - data/lib/aspera/api/ats.rb +1 -1
 - data/lib/aspera/api/cos_node.rb +1 -1
 - data/lib/aspera/api/httpgw.rb +104 -64
 - data/lib/aspera/api/node.rb +33 -12
 - data/lib/aspera/ascmd.rb +56 -48
 - data/lib/aspera/ascp/installation.rb +142 -70
 - data/lib/aspera/ascp/management.rb +7 -3
 - data/lib/aspera/ascp/products.rb +13 -7
 - data/lib/aspera/assert.rb +10 -5
 - data/lib/aspera/cli/formatter.rb +42 -26
 - data/lib/aspera/cli/hints.rb +2 -1
 - data/lib/aspera/cli/info.rb +12 -10
 - data/lib/aspera/cli/main.rb +16 -13
 - data/lib/aspera/cli/manager.rb +15 -10
 - data/lib/aspera/cli/plugin.rb +17 -31
 - data/lib/aspera/cli/plugin_factory.rb +10 -1
 - data/lib/aspera/cli/plugins/alee.rb +3 -3
 - data/lib/aspera/cli/plugins/aoc.rb +222 -194
 - data/lib/aspera/cli/plugins/ats.rb +16 -14
 - data/lib/aspera/cli/plugins/config.rb +66 -53
 - data/lib/aspera/cli/plugins/console.rb +3 -3
 - data/lib/aspera/cli/plugins/faspex.rb +11 -21
 - data/lib/aspera/cli/plugins/faspex5.rb +44 -42
 - data/lib/aspera/cli/plugins/faspio.rb +2 -2
 - data/lib/aspera/cli/plugins/httpgw.rb +1 -1
 - data/lib/aspera/cli/plugins/node.rb +155 -96
 - data/lib/aspera/cli/plugins/orchestrator.rb +14 -13
 - data/lib/aspera/cli/plugins/preview.rb +8 -9
 - data/lib/aspera/cli/plugins/server.rb +6 -10
 - data/lib/aspera/cli/plugins/shares.rb +13 -9
 - data/lib/aspera/cli/sync_actions.rb +72 -31
 - data/lib/aspera/cli/transfer_agent.rb +13 -14
 - data/lib/aspera/cli/transfer_progress.rb +36 -18
 - data/lib/aspera/cli/version.rb +1 -1
 - data/lib/aspera/command_line_builder.rb +3 -4
 - data/lib/aspera/coverage.rb +13 -1
 - data/lib/aspera/environment.rb +59 -10
 - data/lib/aspera/faspex_gw.rb +3 -3
 - data/lib/aspera/json_rpc.rb +1 -1
 - data/lib/aspera/keychain/encrypted_hash.rb +2 -0
 - data/lib/aspera/keychain/macos_security.rb +7 -12
 - data/lib/aspera/log.rb +4 -4
 - data/lib/aspera/node_simulator.rb +1 -1
 - data/lib/aspera/oauth/base.rb +39 -45
 - data/lib/aspera/oauth/factory.rb +11 -4
 - data/lib/aspera/oauth/generic.rb +4 -8
 - data/lib/aspera/oauth/jwt.rb +4 -4
 - data/lib/aspera/oauth/url_json.rb +3 -2
 - data/lib/aspera/oauth/web.rb +10 -6
 - data/lib/aspera/persistency_action_once.rb +16 -8
 - data/lib/aspera/preview/utils.rb +5 -16
 - data/lib/aspera/rest.rb +100 -76
 - data/lib/aspera/secret_hider.rb +3 -2
 - data/lib/aspera/ssh.rb +1 -1
 - data/lib/aspera/transfer/faux_file.rb +7 -5
 - data/lib/aspera/transfer/parameters.rb +41 -35
 - data/lib/aspera/transfer/spec.rb +16 -18
 - data/lib/aspera/transfer/sync.rb +51 -50
 - data/lib/aspera/transfer/uri.rb +1 -1
 - data/lib/aspera/uri_reader.rb +1 -1
 - data/lib/aspera/web_auth.rb +166 -18
 - data/lib/aspera/web_server_simple.rb +27 -15
 - data/lib/transfer_pb.rb +84 -0
 - data/lib/transfer_services_pb.rb +82 -0
 - data.tar.gz.sig +0 -0
 - metadata +25 -6
 - metadata.gz.sig +0 -0
 
| 
         @@ -63,14 +63,14 @@ module Aspera 
     | 
|
| 
       63 
63 
     | 
    
         
             
                        # no protocol ?
         
     | 
| 
       64 
64 
     | 
    
         
             
                        base_url = "https://#{base_url}" unless base_url.match?(%r{^[a-z]{1,6}://})
         
     | 
| 
       65 
65 
     | 
    
         
             
                        # only org provided ?
         
     | 
| 
       66 
     | 
    
         
            -
                        base_url = "#{base_url}.#{Api::SAAS_DOMAIN_PROD}" unless base_url.include?('.')
         
     | 
| 
      
 66 
     | 
    
         
            +
                        base_url = "#{base_url}.#{Api::AoC::SAAS_DOMAIN_PROD}" unless base_url.include?('.')
         
     | 
| 
       67 
67 
     | 
    
         
             
                        # AoC is only https
         
     | 
| 
       68 
68 
     | 
    
         
             
                        return nil unless base_url.start_with?('https://')
         
     | 
| 
       69 
     | 
    
         
            -
                         
     | 
| 
      
 69 
     | 
    
         
            +
                        res_http = Rest.new(base_url: base_url, redirect_max: 10).call(operation: 'GET')[:http]
         
     | 
| 
       70 
70 
     | 
    
         
             
                        # Any AoC is on this domain
         
     | 
| 
       71 
     | 
    
         
            -
                        return nil unless  
     | 
| 
       72 
     | 
    
         
            -
                        Log.log.debug{"AoC Main page: #{ 
     | 
| 
       73 
     | 
    
         
            -
                        base_url =  
     | 
| 
      
 71 
     | 
    
         
            +
                        return nil unless res_http.uri.host.end_with?(Api::AoC::SAAS_DOMAIN_PROD)
         
     | 
| 
      
 72 
     | 
    
         
            +
                        Log.log.debug{"AoC Main page: #{res_http.body.include?(Api::AoC::PRODUCT_NAME)}"}
         
     | 
| 
      
 73 
     | 
    
         
            +
                        base_url = res_http.uri.to_s if res_http.uri.path.include?('/public')
         
     | 
| 
       74 
74 
     | 
    
         
             
                        # either in standard domain, or product name in page
         
     | 
| 
       75 
75 
     | 
    
         
             
                        return {
         
     | 
| 
       76 
76 
     | 
    
         
             
                          version: 'SaaS',
         
     | 
| 
         @@ -98,7 +98,7 @@ module Aspera 
     | 
|
| 
       98 
98 
     | 
    
         
             
                        pub_link_info = Api::AoC.link_info(instance_url)
         
     | 
| 
       99 
99 
     | 
    
         
             
                        if !pub_link_info[:token].nil?
         
     | 
| 
       100 
100 
     | 
    
         
             
                          pub_api = Rest.new(base_url: "https://#{URI.parse(pub_link_info[:url]).host}/api/v1")
         
     | 
| 
       101 
     | 
    
         
            -
                          pub_info = pub_api.read('env/url_token_check', {token: pub_link_info[:token]}) 
     | 
| 
      
 101 
     | 
    
         
            +
                          pub_info = pub_api.read('env/url_token_check', {token: pub_link_info[:token]})
         
     | 
| 
       102 
102 
     | 
    
         
             
                          preset_value = {
         
     | 
| 
       103 
103 
     | 
    
         
             
                            link: instance_url
         
     | 
| 
       104 
104 
     | 
    
         
             
                          }
         
     | 
| 
         @@ -152,7 +152,7 @@ module Aspera 
     | 
|
| 
       152 
152 
     | 
    
         
             
                          # aoc_api.oauth.scope = Api::AoC::SCOPE_FILES_ADMIN
         
     | 
| 
       153 
153 
     | 
    
         
             
                          # aoc_api.oauth.specific_parameters[:redirect_uri] = REDIRECT_LOCALHOST
         
     | 
| 
       154 
154 
     | 
    
         
             
                        end
         
     | 
| 
       155 
     | 
    
         
            -
                        myself = object.aoc_api.read('self') 
     | 
| 
      
 155 
     | 
    
         
            +
                        myself = object.aoc_api.read('self')
         
     | 
| 
       156 
156 
     | 
    
         
             
                        if auto_set_pub_key
         
     | 
| 
       157 
157 
     | 
    
         
             
                          Aspera.assert(myself['public_key'].empty?, exception_class: Cli::Error){'Public key is already set in profile (use --override=yes)'} unless option_override
         
     | 
| 
       158 
158 
     | 
    
         
             
                          formatter.display_status('Updating profile with the public key.')
         
     | 
| 
         @@ -214,7 +214,7 @@ module Aspera 
     | 
|
| 
       214 
214 
     | 
    
         
             
                    def aoc_api
         
     | 
| 
       215 
215 
     | 
    
         
             
                      if @cache_api_aoc.nil?
         
     | 
| 
       216 
216 
     | 
    
         
             
                        @cache_api_aoc = api_from_options(Api::AoC::API_V1)
         
     | 
| 
       217 
     | 
    
         
            -
                        organization = @cache_api_aoc.read('organization') 
     | 
| 
      
 217 
     | 
    
         
            +
                        organization = @cache_api_aoc.read('organization')
         
     | 
| 
       218 
218 
     | 
    
         
             
                        if organization['http_gateway_enabled'] && organization['http_gateway_server_url']
         
     | 
| 
       219 
219 
     | 
    
         
             
                          transfer.httpgw_url_cb = lambda { organization['http_gateway_server_url'] }
         
     | 
| 
       220 
220 
     | 
    
         
             
                          # @cache_api_aoc.current_user_info['connect_disabled']
         
     | 
| 
         @@ -223,7 +223,8 @@ module Aspera 
     | 
|
| 
       223 
223 
     | 
    
         
             
                      return @cache_api_aoc
         
     | 
| 
       224 
224 
     | 
    
         
             
                    end
         
     | 
| 
       225 
225 
     | 
    
         | 
| 
       226 
     | 
    
         
            -
                    #  
     | 
| 
      
 226 
     | 
    
         
            +
                    # Get resource identifier from command line, either directly or from name.
         
     | 
| 
      
 227 
     | 
    
         
            +
                    # @param resource_class_path url path for resource
         
     | 
| 
       227 
228 
     | 
    
         
             
                    # @return identifier
         
     | 
| 
       228 
229 
     | 
    
         
             
                    def get_resource_id_from_args(resource_class_path)
         
     | 
| 
       229 
230 
     | 
    
         
             
                      return instance_identifier do |field, value|
         
     | 
| 
         @@ -232,11 +233,13 @@ module Aspera 
     | 
|
| 
       232 
233 
     | 
    
         
             
                      end
         
     | 
| 
       233 
234 
     | 
    
         
             
                    end
         
     | 
| 
       234 
235 
     | 
    
         | 
| 
      
 236 
     | 
    
         
            +
                    # Get resource path from command line
         
     | 
| 
       235 
237 
     | 
    
         
             
                    def get_resource_path_from_args(resource_class_path)
         
     | 
| 
       236 
238 
     | 
    
         
             
                      return "#{resource_class_path}/#{get_resource_id_from_args(resource_class_path)}"
         
     | 
| 
       237 
239 
     | 
    
         
             
                    end
         
     | 
| 
       238 
240 
     | 
    
         | 
| 
       239 
241 
     | 
    
         
             
                    # Call block with same query using paging and response information
         
     | 
| 
      
 242 
     | 
    
         
            +
                    # block must return a hash with :data and :http keys
         
     | 
| 
       240 
243 
     | 
    
         
             
                    # @return [Hash] {data: , total: }
         
     | 
| 
       241 
244 
     | 
    
         
             
                    def api_call_paging(base_query={})
         
     | 
| 
       242 
245 
     | 
    
         
             
                      Aspera.assert_type(base_query, Hash){'query'}
         
     | 
| 
         @@ -254,6 +257,8 @@ module Aspera 
     | 
|
| 
       254 
257 
     | 
    
         
             
                        query = base_query.clone
         
     | 
| 
       255 
258 
     | 
    
         
             
                        query['page'] = current_page
         
     | 
| 
       256 
259 
     | 
    
         
             
                        result = yield(query)
         
     | 
| 
      
 260 
     | 
    
         
            +
                        Aspera.assert(result[:data])
         
     | 
| 
      
 261 
     | 
    
         
            +
                        Aspera.assert(result[:http])
         
     | 
| 
       257 
262 
     | 
    
         
             
                        total_count = result[:http]['X-Total-Count']
         
     | 
| 
       258 
263 
     | 
    
         
             
                        page_count += 1
         
     | 
| 
       259 
264 
     | 
    
         
             
                        current_page += 1
         
     | 
| 
         @@ -272,7 +277,7 @@ module Aspera 
     | 
|
| 
       272 
277 
     | 
    
         
             
                    # @return [Hash] {data: , total: }
         
     | 
| 
       273 
278 
     | 
    
         
             
                    def api_read_all(resource_class_path, base_query={})
         
     | 
| 
       274 
279 
     | 
    
         
             
                      return api_call_paging(base_query) do |query|
         
     | 
| 
       275 
     | 
    
         
            -
                        aoc_api. 
     | 
| 
      
 280 
     | 
    
         
            +
                        aoc_api.call(operation: 'GET', subpath: resource_class_path, headers: {'Accept' => 'application/json'}, query: query)
         
     | 
| 
       276 
281 
     | 
    
         
             
                      end
         
     | 
| 
       277 
282 
     | 
    
         
             
                    end
         
     | 
| 
       278 
283 
     | 
    
         | 
| 
         @@ -294,7 +299,7 @@ module Aspera 
     | 
|
| 
       294 
299 
     | 
    
         
             
                        query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query['dropbox_name'])['id']
         
     | 
| 
       295 
300 
     | 
    
         
             
                        query.delete('dropbox_name')
         
     | 
| 
       296 
301 
     | 
    
         
             
                      end
         
     | 
| 
       297 
     | 
    
         
            -
                      query['workspace_id'] ||= aoc_api. 
     | 
| 
      
 302 
     | 
    
         
            +
                      query['workspace_id'] ||= aoc_api.workspace[:id] unless aoc_api.workspace[:id].eql?(:undefined)
         
     | 
| 
       298 
303 
     | 
    
         
             
                      # by default show dropbox packages only for dropboxes
         
     | 
| 
       299 
304 
     | 
    
         
             
                      query['exclude_dropbox_packages'] = !query.key?('dropbox_id') unless query.key?('exclude_dropbox_packages')
         
     | 
| 
       300 
305 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -307,11 +312,11 @@ module Aspera 
     | 
|
| 
       307 
312 
     | 
    
         
             
                    def execute_nodegen4_command(command_repo, node_id, file_id: nil, scope: nil)
         
     | 
| 
       308 
313 
     | 
    
         
             
                      top_node_api = aoc_api.node_api_from(
         
     | 
| 
       309 
314 
     | 
    
         
             
                        node_id:        node_id,
         
     | 
| 
       310 
     | 
    
         
            -
                        workspace_id:   aoc_api. 
     | 
| 
       311 
     | 
    
         
            -
                        workspace_name: aoc_api. 
     | 
| 
      
 315 
     | 
    
         
            +
                        workspace_id:   aoc_api.workspace[:id],
         
     | 
| 
      
 316 
     | 
    
         
            +
                        workspace_name: aoc_api.workspace[:name],
         
     | 
| 
       312 
317 
     | 
    
         
             
                        scope:          scope
         
     | 
| 
       313 
318 
     | 
    
         
             
                      )
         
     | 
| 
       314 
     | 
    
         
            -
                      file_id = top_node_api.read("access_keys/#{top_node_api.app_info[:node_info]['access_key']}")[ 
     | 
| 
      
 319 
     | 
    
         
            +
                      file_id = top_node_api.read("access_keys/#{top_node_api.app_info[:node_info]['access_key']}")['root_file_id'] if file_id.nil?
         
     | 
| 
       315 
320 
     | 
    
         
             
                      node_plugin = Node.new(**init_params, api: top_node_api)
         
     | 
| 
       316 
321 
     | 
    
         
             
                      case command_repo
         
     | 
| 
       317 
322 
     | 
    
         
             
                      when *Node::COMMANDS_GEN4
         
     | 
| 
         @@ -321,7 +326,7 @@ module Aspera 
     | 
|
| 
       321 
326 
     | 
    
         
             
                        # server side is transfer server
         
     | 
| 
       322 
327 
     | 
    
         
             
                        # in same workspace
         
     | 
| 
       323 
328 
     | 
    
         
             
                        push_pull = options.get_next_argument('direction', accept_list: %i[push pull])
         
     | 
| 
       324 
     | 
    
         
            -
                        source_folder = options.get_next_argument('folder  
     | 
| 
      
 329 
     | 
    
         
            +
                        source_folder = options.get_next_argument('folder or source files', validation: String)
         
     | 
| 
       325 
330 
     | 
    
         
             
                        case push_pull
         
     | 
| 
       326 
331 
     | 
    
         
             
                        when :push
         
     | 
| 
       327 
332 
     | 
    
         
             
                          client_direction = Transfer::Spec::DIRECTION_SEND
         
     | 
| 
         @@ -390,7 +395,7 @@ module Aspera 
     | 
|
| 
       390 
395 
     | 
    
         
             
                        # TODO: report inconsistency: creation url is !=, and does not return id.
         
     | 
| 
       391 
396 
     | 
    
         
             
                        resource_class_path = 'admin/client_registration/token' if resource_class_path.eql?('admin/client_registration_tokens')
         
     | 
| 
       392 
397 
     | 
    
         
             
                        return do_bulk_operation(command: command, descr: 'creation data', id_result: id_result) do |params|
         
     | 
| 
       393 
     | 
    
         
            -
                          aoc_api.create(resource_class_path, params) 
     | 
| 
      
 398 
     | 
    
         
            +
                          aoc_api.create(resource_class_path, params)
         
     | 
| 
       394 
399 
     | 
    
         
             
                        end
         
     | 
| 
       395 
400 
     | 
    
         
             
                      when :list
         
     | 
| 
       396 
401 
     | 
    
         
             
                        default_fields = ['id']
         
     | 
| 
         @@ -411,7 +416,7 @@ module Aspera 
     | 
|
| 
       411 
416 
     | 
    
         
             
                        end
         
     | 
| 
       412 
417 
     | 
    
         
             
                        return result_list(resource_class_path, fields: default_fields, default_query: default_query)
         
     | 
| 
       413 
418 
     | 
    
         
             
                      when :show
         
     | 
| 
       414 
     | 
    
         
            -
                        object = aoc_api.read(resource_instance_path) 
     | 
| 
      
 419 
     | 
    
         
            +
                        object = aoc_api.read(resource_instance_path)
         
     | 
| 
       415 
420 
     | 
    
         
             
                        # default: show all, but certificate
         
     | 
| 
       416 
421 
     | 
    
         
             
                        fields = object.keys.reject{|k|k.eql?('certificate')}
         
     | 
| 
       417 
422 
     | 
    
         
             
                        return { type: :single_object, data: object, fields: fields }
         
     | 
| 
         @@ -435,7 +440,7 @@ module Aspera 
     | 
|
| 
       435 
440 
     | 
    
         
             
                      when :do
         
     | 
| 
       436 
441 
     | 
    
         
             
                        command_repo = options.get_next_command(NODE4_EXT_COMMANDS)
         
     | 
| 
       437 
442 
     | 
    
         
             
                        # init context
         
     | 
| 
       438 
     | 
    
         
            -
                        aoc_api.context 
     | 
| 
      
 443 
     | 
    
         
            +
                        aoc_api.context = :files
         
     | 
| 
       439 
444 
     | 
    
         
             
                        return execute_nodegen4_command(command_repo, res_id)
         
     | 
| 
       440 
445 
     | 
    
         
             
                      else Aspera.error_unexpected_value(command)
         
     | 
| 
       441 
446 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -462,59 +467,61 @@ module Aspera 
     | 
|
| 
       462 
467 
     | 
    
         
             
                          raise 'not implemented'
         
     | 
| 
       463 
468 
     | 
    
         
             
                        end
         
     | 
| 
       464 
469 
     | 
    
         
             
                      when :subscription
         
     | 
| 
       465 
     | 
    
         
            -
                        org = aoc_api.read('organization') 
     | 
| 
       466 
     | 
    
         
            -
                         
     | 
| 
      
 470 
     | 
    
         
            +
                        org = aoc_api.read('organization')
         
     | 
| 
      
 471 
     | 
    
         
            +
                        bss_graphql = api_from_options('bss/platform/graphql')
         
     | 
| 
       467 
472 
     | 
    
         
             
                        # cspell:disable
         
     | 
| 
       468 
     | 
    
         
            -
                        graphql_query =  
     | 
| 
       469 
     | 
    
         
            -
             
     | 
| 
       470 
     | 
    
         
            -
             
     | 
| 
       471 
     | 
    
         
            -
             
     | 
| 
       472 
     | 
    
         
            -
             
     | 
| 
       473 
     | 
    
         
            -
                      startDate
         
     | 
| 
       474 
     | 
    
         
            -
                      termMonths
         
     | 
| 
       475 
     | 
    
         
            -
                      plan
         
     | 
| 
       476 
     | 
    
         
            -
                      trial
         
     | 
| 
       477 
     | 
    
         
            -
                      termType
         
     | 
| 
       478 
     | 
    
         
            -
                      instances {
         
     | 
| 
       479 
     | 
    
         
            -
                        id
         
     | 
| 
       480 
     | 
    
         
            -
                        entitlements {
         
     | 
| 
       481 
     | 
    
         
            -
                          maxUsageMb
         
     | 
| 
       482 
     | 
    
         
            -
                        }
         
     | 
| 
       483 
     | 
    
         
            -
                      }
         
     | 
| 
       484 
     | 
    
         
            -
                      additionalStorageVolumeGb
         
     | 
| 
       485 
     | 
    
         
            -
                      additionalEgressVolumeGb
         
     | 
| 
       486 
     | 
    
         
            -
                      additionalUsers
         
     | 
| 
       487 
     | 
    
         
            -
                      term {
         
     | 
| 
       488 
     | 
    
         
            -
                        startDate
         
     | 
| 
      
 473 
     | 
    
         
            +
                        graphql_query = <<-GRAPHQL
         
     | 
| 
      
 474 
     | 
    
         
            +
                  query ($organization_id: ID!) {
         
     | 
| 
      
 475 
     | 
    
         
            +
                    aoc (organization_id: $organization_id) {
         
     | 
| 
      
 476 
     | 
    
         
            +
                      bssSubscription {
         
     | 
| 
      
 477 
     | 
    
         
            +
                        aocVersion
         
     | 
| 
       489 
478 
     | 
    
         
             
                        endDate
         
     | 
| 
       490 
     | 
    
         
            -
                         
     | 
| 
       491 
     | 
    
         
            -
                         
     | 
| 
       492 
     | 
    
         
            -
                         
     | 
| 
       493 
     | 
    
         
            -
                      }
         
     | 
| 
       494 
     | 
    
         
            -
                      paygoRate {
         
     | 
| 
       495 
     | 
    
         
            -
                        rate
         
     | 
| 
       496 
     | 
    
         
            -
                        currency
         
     | 
| 
       497 
     | 
    
         
            -
                      }
         
     | 
| 
       498 
     | 
    
         
            -
                      aocPlanData {
         
     | 
| 
       499 
     | 
    
         
            -
                        tier
         
     | 
| 
      
 479 
     | 
    
         
            +
                        startDate
         
     | 
| 
      
 480 
     | 
    
         
            +
                        termMonths
         
     | 
| 
      
 481 
     | 
    
         
            +
                        plan
         
     | 
| 
       500 
482 
     | 
    
         
             
                        trial
         
     | 
| 
       501 
     | 
    
         
            -
                         
     | 
| 
       502 
     | 
    
         
            -
                         
     | 
| 
       503 
     | 
    
         
            -
                           
     | 
| 
       504 
     | 
    
         
            -
             
     | 
| 
      
 483 
     | 
    
         
            +
                        termType
         
     | 
| 
      
 484 
     | 
    
         
            +
                        aocOrganizations {
         
     | 
| 
      
 485 
     | 
    
         
            +
                          id
         
     | 
| 
      
 486 
     | 
    
         
            +
                        }
         
     | 
| 
      
 487 
     | 
    
         
            +
                        additionalStorageVolumeGb
         
     | 
| 
      
 488 
     | 
    
         
            +
                        additionalEgressVolumeGb
         
     | 
| 
      
 489 
     | 
    
         
            +
                        term {
         
     | 
| 
      
 490 
     | 
    
         
            +
                          startDate
         
     | 
| 
      
 491 
     | 
    
         
            +
                          endDate
         
     | 
| 
      
 492 
     | 
    
         
            +
                          transferVolumeGb
         
     | 
| 
      
 493 
     | 
    
         
            +
                          egressVolumeGb
         
     | 
| 
      
 494 
     | 
    
         
            +
                          storageVolumeGb
         
     | 
| 
      
 495 
     | 
    
         
            +
                          transferVolumeOffsetGb
         
     | 
| 
      
 496 
     | 
    
         
            +
                        }
         
     | 
| 
      
 497 
     | 
    
         
            +
                        paygoRate {
         
     | 
| 
      
 498 
     | 
    
         
            +
                          transferRate
         
     | 
| 
      
 499 
     | 
    
         
            +
                          storageRate
         
     | 
| 
      
 500 
     | 
    
         
            +
                          currency
         
     | 
| 
      
 501 
     | 
    
         
            +
                        }
         
     | 
| 
      
 502 
     | 
    
         
            +
                        aocPlanData {
         
     | 
| 
      
 503 
     | 
    
         
            +
                          tier
         
     | 
| 
      
 504 
     | 
    
         
            +
                          trial
         
     | 
| 
      
 505 
     | 
    
         
            +
                          workspaces { max }
         
     | 
| 
      
 506 
     | 
    
         
            +
                          users {
         
     | 
| 
      
 507 
     | 
    
         
            +
                            planAmount
         
     | 
| 
      
 508 
     | 
    
         
            +
                            max
         
     | 
| 
      
 509 
     | 
    
         
            +
                          }
         
     | 
| 
      
 510 
     | 
    
         
            +
                          samlIntegration
         
     | 
| 
      
 511 
     | 
    
         
            +
                          activity
         
     | 
| 
      
 512 
     | 
    
         
            +
                          sharedInboxes
         
     | 
| 
      
 513 
     | 
    
         
            +
                          uniqueUrls
         
     | 
| 
      
 514 
     | 
    
         
            +
                          support
         
     | 
| 
      
 515 
     | 
    
         
            +
                          watermarking
         
     | 
| 
      
 516 
     | 
    
         
            +
                          byok
         
     | 
| 
      
 517 
     | 
    
         
            +
                          automation { planAmount, max }
         
     | 
| 
       505 
518 
     | 
    
         
             
                        }
         
     | 
| 
       506 
     | 
    
         
            -
                        samlIntegration
         
     | 
| 
       507 
     | 
    
         
            -
                        activity
         
     | 
| 
       508 
     | 
    
         
            -
                        sharedInboxes
         
     | 
| 
       509 
     | 
    
         
            -
                        uniqueUrls
         
     | 
| 
       510 
     | 
    
         
            -
                        support
         
     | 
| 
       511 
519 
     | 
    
         
             
                      }
         
     | 
| 
       512 
520 
     | 
    
         
             
                    }
         
     | 
| 
       513 
521 
     | 
    
         
             
                  }
         
     | 
| 
       514 
     | 
    
         
            -
             
     | 
| 
       515 
     | 
    
         
            -
              "
         
     | 
| 
      
 522 
     | 
    
         
            +
                        GRAPHQL
         
     | 
| 
       516 
523 
     | 
    
         
             
                        # cspell:enable
         
     | 
| 
       517 
     | 
    
         
            -
                        result =  
     | 
| 
      
 524 
     | 
    
         
            +
                        result = bss_graphql.create(nil, {query: graphql_query, variables: {organization_id: org['id']}})['data']
         
     | 
| 
       518 
525 
     | 
    
         
             
                        return {type: :single_object, data: result['aoc']['bssSubscription']}
         
     | 
| 
       519 
526 
     | 
    
         
             
                      when :ats
         
     | 
| 
       520 
527 
     | 
    
         
             
                        ats_api = Rest.new(**aoc_api.params.deep_merge({
         
     | 
| 
         @@ -531,7 +538,7 @@ module Aspera 
     | 
|
| 
       531 
538 
     | 
    
         
             
                        case command_analytics
         
     | 
| 
       532 
539 
     | 
    
         
             
                        when :application_events
         
     | 
| 
       533 
540 
     | 
    
         
             
                          event_type = command_analytics.to_s
         
     | 
| 
       534 
     | 
    
         
            -
                          events = analytics_api.read("organizations/#{aoc_api.current_user_info['organization_id']}/#{event_type}")[ 
     | 
| 
      
 541 
     | 
    
         
            +
                          events = analytics_api.read("organizations/#{aoc_api.current_user_info['organization_id']}/#{event_type}")[event_type]
         
     | 
| 
       535 
542 
     | 
    
         
             
                          return {type: :object_list, data: events}
         
     | 
| 
       536 
543 
     | 
    
         
             
                        when :transfers
         
     | 
| 
       537 
544 
     | 
    
         
             
                          event_type = command_analytics.to_s
         
     | 
| 
         @@ -546,6 +553,7 @@ module Aspera 
     | 
|
| 
       546 
553 
     | 
    
         
             
                          filter = options.get_option(:query) || {}
         
     | 
| 
       547 
554 
     | 
    
         
             
                          filter['limit'] ||= 100
         
     | 
| 
       548 
555 
     | 
    
         
             
                          if options.get_option(:once_only, mandatory: true)
         
     | 
| 
      
 556 
     | 
    
         
            +
                            aoc_api.context = :files
         
     | 
| 
       549 
557 
     | 
    
         
             
                            saved_date = []
         
     | 
| 
       550 
558 
     | 
    
         
             
                            start_date_persistency = PersistencyActionOnce.new(
         
     | 
| 
       551 
559 
     | 
    
         
             
                              manager: persistency,
         
     | 
| 
         @@ -553,7 +561,7 @@ module Aspera 
     | 
|
| 
       553 
561 
     | 
    
         
             
                              id: IdGenerator.from_list([
         
     | 
| 
       554 
562 
     | 
    
         
             
                                'aoc_ana_date',
         
     | 
| 
       555 
563 
     | 
    
         
             
                                options.get_option(:url, mandatory: true),
         
     | 
| 
       556 
     | 
    
         
            -
                                aoc_api. 
     | 
| 
      
 564 
     | 
    
         
            +
                                aoc_api.workspace[:name],
         
     | 
| 
       557 
565 
     | 
    
         
             
                                filter_resource.to_s,
         
     | 
| 
       558 
566 
     | 
    
         
             
                                filter_id
         
     | 
| 
       559 
567 
     | 
    
         
             
                              ]))
         
     | 
| 
         @@ -565,7 +573,7 @@ module Aspera 
     | 
|
| 
       565 
573 
     | 
    
         
             
                            filter['start_time'] = start_date_time unless start_date_time.nil?
         
     | 
| 
       566 
574 
     | 
    
         
             
                            filter['stop_time'] = stop_date_time
         
     | 
| 
       567 
575 
     | 
    
         
             
                          end
         
     | 
| 
       568 
     | 
    
         
            -
                          events = analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}", query_read_delete(default: filter))[ 
     | 
| 
      
 576 
     | 
    
         
            +
                          events = analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}", query_read_delete(default: filter))[event_type]
         
     | 
| 
       569 
577 
     | 
    
         
             
                          start_date_persistency&.save
         
     | 
| 
       570 
578 
     | 
    
         
             
                          if !options.get_option(:notify_to).nil?
         
     | 
| 
       571 
579 
     | 
    
         
             
                            events.each do |tr_event|
         
     | 
| 
         @@ -575,7 +583,83 @@ module Aspera 
     | 
|
| 
       575 
583 
     | 
    
         
             
                          return {type: :object_list, data: events}
         
     | 
| 
       576 
584 
     | 
    
         
             
                        end
         
     | 
| 
       577 
585 
     | 
    
         
             
                      when :usage_reports
         
     | 
| 
       578 
     | 
    
         
            -
                         
     | 
| 
      
 586 
     | 
    
         
            +
                        aoc_api.context = :files
         
     | 
| 
      
 587 
     | 
    
         
            +
                        return result_list('usage_reports', base_query: {workspace_id: aoc_api.workspace[:id]})
         
     | 
| 
      
 588 
     | 
    
         
            +
                      end
         
     | 
| 
      
 589 
     | 
    
         
            +
                    end
         
     | 
| 
      
 590 
     | 
    
         
            +
             
     | 
| 
      
 591 
     | 
    
         
            +
                    # Create a shared link for the given entity
         
     | 
| 
      
 592 
     | 
    
         
            +
                    # @param shared_data [Hash] information for shared data
         
     | 
| 
      
 593 
     | 
    
         
            +
                    # @param block [Proc] Optional: called on creation
         
     | 
| 
      
 594 
     | 
    
         
            +
                    def short_link_command(shared_data, purpose_public:)
         
     | 
| 
      
 595 
     | 
    
         
            +
                      link_type = options.get_next_argument('link type', accept_list: %i[public private])
         
     | 
| 
      
 596 
     | 
    
         
            +
                      purpose_local = case link_type
         
     | 
| 
      
 597 
     | 
    
         
            +
                      when :public
         
     | 
| 
      
 598 
     | 
    
         
            +
                        case purpose_public
         
     | 
| 
      
 599 
     | 
    
         
            +
                        when /package/ then 'send_package_to_dropbox'
         
     | 
| 
      
 600 
     | 
    
         
            +
                        when /shared/ then 'token_auth_redirection'
         
     | 
| 
      
 601 
     | 
    
         
            +
                        else raise 'error'
         
     | 
| 
      
 602 
     | 
    
         
            +
                        end
         
     | 
| 
      
 603 
     | 
    
         
            +
                      when :private then 'shared_folder_auth_link'
         
     | 
| 
      
 604 
     | 
    
         
            +
                      else Aspera.error_unreachable_line
         
     | 
| 
      
 605 
     | 
    
         
            +
                      end
         
     | 
| 
      
 606 
     | 
    
         
            +
                      case options.get_next_command(%i[create delete list])
         
     | 
| 
      
 607 
     | 
    
         
            +
                      when :create
         
     | 
| 
      
 608 
     | 
    
         
            +
                        creation_params = {
         
     | 
| 
      
 609 
     | 
    
         
            +
                          purpose:            purpose_local,
         
     | 
| 
      
 610 
     | 
    
         
            +
                          user_selected_name: nil
         
     | 
| 
      
 611 
     | 
    
         
            +
                        }
         
     | 
| 
      
 612 
     | 
    
         
            +
                        case link_type
         
     | 
| 
      
 613 
     | 
    
         
            +
                        when :private
         
     | 
| 
      
 614 
     | 
    
         
            +
                          creation_params[:data] = shared_data
         
     | 
| 
      
 615 
     | 
    
         
            +
                        when :public
         
     | 
| 
      
 616 
     | 
    
         
            +
                          creation_params[:expires_at]       = nil
         
     | 
| 
      
 617 
     | 
    
         
            +
                          creation_params[:password_enabled] = false
         
     | 
| 
      
 618 
     | 
    
         
            +
                          shared_data[:name] = ''
         
     | 
| 
      
 619 
     | 
    
         
            +
                          creation_params[:data] = {
         
     | 
| 
      
 620 
     | 
    
         
            +
                            aoc:            true,
         
     | 
| 
      
 621 
     | 
    
         
            +
                            url_token_data: {
         
     | 
| 
      
 622 
     | 
    
         
            +
                              data:    shared_data,
         
     | 
| 
      
 623 
     | 
    
         
            +
                              purpose: purpose_public
         
     | 
| 
      
 624 
     | 
    
         
            +
                            }
         
     | 
| 
      
 625 
     | 
    
         
            +
                          }
         
     | 
| 
      
 626 
     | 
    
         
            +
                        end
         
     | 
| 
      
 627 
     | 
    
         
            +
                        result_create_short_link = aoc_api.create('short_links', creation_params)
         
     | 
| 
      
 628 
     | 
    
         
            +
                        # public: Creation: permission on node
         
     | 
| 
      
 629 
     | 
    
         
            +
                        yield(result_create_short_link['resource_id']) if block_given? && link_type.eql?(:public)
         
     | 
| 
      
 630 
     | 
    
         
            +
                        return {type: :single_object, data: result_create_short_link}
         
     | 
| 
      
 631 
     | 
    
         
            +
                      when :list
         
     | 
| 
      
 632 
     | 
    
         
            +
                        query = if link_type.eql?(:private)
         
     | 
| 
      
 633 
     | 
    
         
            +
                          shared_data
         
     | 
| 
      
 634 
     | 
    
         
            +
                        else
         
     | 
| 
      
 635 
     | 
    
         
            +
                          {
         
     | 
| 
      
 636 
     | 
    
         
            +
                            url_token_data: {
         
     | 
| 
      
 637 
     | 
    
         
            +
                              data:    shared_data,
         
     | 
| 
      
 638 
     | 
    
         
            +
                              purpose: purpose_public
         
     | 
| 
      
 639 
     | 
    
         
            +
                            }
         
     | 
| 
      
 640 
     | 
    
         
            +
                          }
         
     | 
| 
      
 641 
     | 
    
         
            +
                        end
         
     | 
| 
      
 642 
     | 
    
         
            +
                        list_params = {
         
     | 
| 
      
 643 
     | 
    
         
            +
                          json_query:  query.to_json,
         
     | 
| 
      
 644 
     | 
    
         
            +
                          purpose:     purpose_local,
         
     | 
| 
      
 645 
     | 
    
         
            +
                          edit_access: true,
         
     | 
| 
      
 646 
     | 
    
         
            +
                          # embed: 'updated_by_user',
         
     | 
| 
      
 647 
     | 
    
         
            +
                          sort:        '-created_at'
         
     | 
| 
      
 648 
     | 
    
         
            +
                        }
         
     | 
| 
      
 649 
     | 
    
         
            +
                        return result_list('short_links', fields: Formatter.all_but('data'), base_query: list_params)
         
     | 
| 
      
 650 
     | 
    
         
            +
                      when :delete
         
     | 
| 
      
 651 
     | 
    
         
            +
                        one_id = instance_identifier
         
     | 
| 
      
 652 
     | 
    
         
            +
                        shared_data.delete(:workspace_id)
         
     | 
| 
      
 653 
     | 
    
         
            +
                        delete_params = {
         
     | 
| 
      
 654 
     | 
    
         
            +
                          edit_access: true,
         
     | 
| 
      
 655 
     | 
    
         
            +
                          json_query:  shared_data.to_json
         
     | 
| 
      
 656 
     | 
    
         
            +
                        }
         
     | 
| 
      
 657 
     | 
    
         
            +
                        aoc_api.delete("short_links/#{one_id}", delete_params)
         
     | 
| 
      
 658 
     | 
    
         
            +
                        if link_type.eql?(:public)
         
     | 
| 
      
 659 
     | 
    
         
            +
                          # TODO: get permission id..
         
     | 
| 
      
 660 
     | 
    
         
            +
                          # shared_apfid[:api].delete('permissions', {ids: })
         
     | 
| 
      
 661 
     | 
    
         
            +
                        end
         
     | 
| 
      
 662 
     | 
    
         
            +
                        return Main.result_status('deleted')
         
     | 
| 
       579 
663 
     | 
    
         
             
                      end
         
     | 
| 
       580 
664 
     | 
    
         
             
                    end
         
     | 
| 
       581 
665 
     | 
    
         | 
| 
         @@ -586,10 +670,10 @@ module Aspera 
     | 
|
| 
       586 
670 
     | 
    
         
             
                      command = options.get_next_command(ACTIONS)
         
     | 
| 
       587 
671 
     | 
    
         
             
                      if %i[files packages].include?(command)
         
     | 
| 
       588 
672 
     | 
    
         
             
                        default_flag = ' (default)' if options.get_option(:workspace).eql?(:default)
         
     | 
| 
       589 
     | 
    
         
            -
                         
     | 
| 
       590 
     | 
    
         
            -
                        formatter.display_status("Workspace: #{ 
     | 
| 
      
 673 
     | 
    
         
            +
                        aoc_api.context = command
         
     | 
| 
      
 674 
     | 
    
         
            +
                        formatter.display_status("Workspace: #{aoc_api.workspace[:name].to_s.red}#{default_flag}")
         
     | 
| 
       591 
675 
     | 
    
         
             
                        if !aoc_api.private_link.nil?
         
     | 
| 
       592 
     | 
    
         
            -
                          folder_name = aoc_api.node_api_from(node_id:  
     | 
| 
      
 676 
     | 
    
         
            +
                          folder_name = aoc_api.node_api_from(node_id: aoc_api.home[:node_id]).read("files/#{aoc_api.home[:file_id]}")['name']
         
     | 
| 
       593 
677 
     | 
    
         
             
                          formatter.display_status("Private Folder: #{folder_name}")
         
     | 
| 
       594 
678 
     | 
    
         
             
                        end
         
     | 
| 
       595 
679 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -597,26 +681,27 @@ module Aspera 
     | 
|
| 
       597 
681 
     | 
    
         
             
                      when :reminder
         
     | 
| 
       598 
682 
     | 
    
         
             
                        # send an email reminder with list of orgs
         
     | 
| 
       599 
683 
     | 
    
         
             
                        user_email = options.get_option(:username, mandatory: true)
         
     | 
| 
       600 
     | 
    
         
            -
                        Rest.new(base_url: "#{Api::AoC.api_base_url}/#{Api::AoC::API_V1}").create('organization_reminders', {email: user_email}) 
     | 
| 
      
 684 
     | 
    
         
            +
                        Rest.new(base_url: "#{Api::AoC.api_base_url}/#{Api::AoC::API_V1}").create('organization_reminders', {email: user_email})
         
     | 
| 
       601 
685 
     | 
    
         
             
                        return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
         
     | 
| 
       602 
686 
     | 
    
         
             
                      when :servers
         
     | 
| 
       603 
     | 
    
         
            -
                        return {type: :object_list, data: Rest.new(base_url: "#{Api::AoC.api_base_url}/#{Api::AoC::API_V1}").read('servers') 
     | 
| 
      
 687 
     | 
    
         
            +
                        return {type: :object_list, data: Rest.new(base_url: "#{Api::AoC.api_base_url}/#{Api::AoC::API_V1}").read('servers')}
         
     | 
| 
       604 
688 
     | 
    
         
             
                      when :bearer_token
         
     | 
| 
       605 
689 
     | 
    
         
             
                        return {type: :text, data: aoc_api.oauth.token}
         
     | 
| 
       606 
690 
     | 
    
         
             
                      when :organization
         
     | 
| 
       607 
     | 
    
         
            -
                        return { type: :single_object, data: aoc_api.read('organization') 
     | 
| 
      
 691 
     | 
    
         
            +
                        return { type: :single_object, data: aoc_api.read('organization') }
         
     | 
| 
       608 
692 
     | 
    
         
             
                      when :tier_restrictions
         
     | 
| 
       609 
     | 
    
         
            -
                        return { type: :single_object, data: aoc_api.read('tier_restrictions') 
     | 
| 
      
 693 
     | 
    
         
            +
                        return { type: :single_object, data: aoc_api.read('tier_restrictions') }
         
     | 
| 
       610 
694 
     | 
    
         
             
                      when :user
         
     | 
| 
       611 
695 
     | 
    
         
             
                        case options.get_next_command(%i[workspaces profile preferences])
         
     | 
| 
       612 
696 
     | 
    
         
             
                        # when :settings
         
     | 
| 
       613 
     | 
    
         
            -
                        # return {type: :object_list,data: aoc_api.read('client_settings/') 
     | 
| 
      
 697 
     | 
    
         
            +
                        # return {type: :object_list,data: aoc_api.read('client_settings/')}
         
     | 
| 
       614 
698 
     | 
    
         
             
                        when :workspaces
         
     | 
| 
       615 
699 
     | 
    
         
             
                          case options.get_next_command(%i[list current])
         
     | 
| 
       616 
700 
     | 
    
         
             
                          when :list
         
     | 
| 
       617 
701 
     | 
    
         
             
                            return result_list('workspaces', fields: %w[id name])
         
     | 
| 
       618 
702 
     | 
    
         
             
                          when :current
         
     | 
| 
       619 
     | 
    
         
            -
                             
     | 
| 
      
 703 
     | 
    
         
            +
                            aoc_api.context = :files
         
     | 
| 
      
 704 
     | 
    
         
            +
                            return { type: :single_object, data: aoc_api.read("workspaces/#{aoc_api.workspace[:id]}") }
         
     | 
| 
       620 
705 
     | 
    
         
             
                          end
         
     | 
| 
       621 
706 
     | 
    
         
             
                        when :profile
         
     | 
| 
       622 
707 
     | 
    
         
             
                          case options.get_next_command(%i[show modify])
         
     | 
| 
         @@ -630,7 +715,7 @@ module Aspera 
     | 
|
| 
       630 
715 
     | 
    
         
             
                          user_preferences_res = "users/#{aoc_api.current_user_info(exception: true)['id']}/user_interaction_preferences"
         
     | 
| 
       631 
716 
     | 
    
         
             
                          case options.get_next_command(%i[show modify])
         
     | 
| 
       632 
717 
     | 
    
         
             
                          when :show
         
     | 
| 
       633 
     | 
    
         
            -
                            return { type: :single_object, data: aoc_api.read(user_preferences_res) 
     | 
| 
      
 718 
     | 
    
         
            +
                            return { type: :single_object, data: aoc_api.read(user_preferences_res) }
         
     | 
| 
       634 
719 
     | 
    
         
             
                          when :modify
         
     | 
| 
       635 
720 
     | 
    
         
             
                            aoc_api.update(user_preferences_res, options.get_next_argument('properties', validation: Hash))
         
     | 
| 
       636 
721 
     | 
    
         
             
                            return Main.result_status('modified')
         
     | 
| 
         @@ -640,20 +725,28 @@ module Aspera 
     | 
|
| 
       640 
725 
     | 
    
         
             
                        package_command = options.get_next_command(%i[shared_inboxes send receive list show delete].concat(Node::NODE4_READ_ACTIONS), aliases: {recv: :receive})
         
     | 
| 
       641 
726 
     | 
    
         
             
                        case package_command
         
     | 
| 
       642 
727 
     | 
    
         
             
                        when :shared_inboxes
         
     | 
| 
       643 
     | 
    
         
            -
                          case options.get_next_command(%i[list show])
         
     | 
| 
      
 728 
     | 
    
         
            +
                          case options.get_next_command(%i[list show short_link])
         
     | 
| 
       644 
729 
     | 
    
         
             
                          when :list
         
     | 
| 
       645 
730 
     | 
    
         
             
                            default_query = {'embed[]' => 'dropbox', 'aggregate_permissions_by_dropbox' => true, 'sort' => 'dropbox_name'}
         
     | 
| 
       646 
     | 
    
         
            -
                            default_query['workspace_id'] = aoc_api. 
     | 
| 
      
 731 
     | 
    
         
            +
                            default_query['workspace_id'] = aoc_api.workspace[:id] unless aoc_api.workspace[:id].eql?(:undefined)
         
     | 
| 
       647 
732 
     | 
    
         
             
                            return result_list('dropbox_memberships', fields: %w[dropbox_id dropbox.name], default_query: default_query)
         
     | 
| 
       648 
733 
     | 
    
         
             
                          when :show
         
     | 
| 
       649 
     | 
    
         
            -
                            return {type: :single_object, data: aoc_api.read(get_resource_path_from_args('dropboxes') 
     | 
| 
      
 734 
     | 
    
         
            +
                            return {type: :single_object, data: aoc_api.read(get_resource_path_from_args('dropboxes'))}
         
     | 
| 
      
 735 
     | 
    
         
            +
                          when :short_link
         
     | 
| 
      
 736 
     | 
    
         
            +
                            return short_link_command(
         
     | 
| 
      
 737 
     | 
    
         
            +
                              {
         
     | 
| 
      
 738 
     | 
    
         
            +
                                workspace_id: aoc_api.workspace[:id],
         
     | 
| 
      
 739 
     | 
    
         
            +
                                dropbox_id:   get_resource_id_from_args('dropboxes'),
         
     | 
| 
      
 740 
     | 
    
         
            +
                                name:         ''
         
     | 
| 
      
 741 
     | 
    
         
            +
                              },
         
     | 
| 
      
 742 
     | 
    
         
            +
                              purpose_public: 'send_package_to_dropbox')
         
     | 
| 
       650 
743 
     | 
    
         
             
                          end
         
     | 
| 
       651 
744 
     | 
    
         
             
                        when :send
         
     | 
| 
       652 
745 
     | 
    
         
             
                          package_data = value_create_modify(command: package_command)
         
     | 
| 
       653 
746 
     | 
    
         
             
                          new_user_option = options.get_option(:new_user_option)
         
     | 
| 
       654 
747 
     | 
    
         
             
                          option_validate = options.get_option(:validate_metadata)
         
     | 
| 
       655 
748 
     | 
    
         
             
                          # works for both normal usr auth and link auth
         
     | 
| 
       656 
     | 
    
         
            -
                          package_data['workspace_id'] ||= aoc_api. 
     | 
| 
      
 749 
     | 
    
         
            +
                          package_data['workspace_id'] ||= aoc_api.workspace[:id]
         
     | 
| 
       657 
750 
     | 
    
         | 
| 
       658 
751 
     | 
    
         
             
                          if !aoc_api.public_link.nil?
         
     | 
| 
       659 
752 
     | 
    
         
             
                            aoc_api.assert_public_link_types(%w[send_package_to_user send_package_to_dropbox])
         
     | 
| 
         @@ -687,7 +780,7 @@ module Aspera 
     | 
|
| 
       687 
780 
     | 
    
         
             
                              id: IdGenerator.from_list(
         
     | 
| 
       688 
781 
     | 
    
         
             
                                ['aoc_recv',
         
     | 
| 
       689 
782 
     | 
    
         
             
                                 options.get_option(:url, mandatory: true),
         
     | 
| 
       690 
     | 
    
         
            -
                                 aoc_api. 
     | 
| 
      
 783 
     | 
    
         
            +
                                 aoc_api.workspace[:id]
         
     | 
| 
       691 
784 
     | 
    
         
             
                                ].concat(aoc_api.additional_persistence_ids)))
         
     | 
| 
       692 
785 
     | 
    
         
             
                          end
         
     | 
| 
       693 
786 
     | 
    
         
             
                          case ids_to_download
         
     | 
| 
         @@ -712,12 +805,12 @@ module Aspera 
     | 
|
| 
       712 
805 
     | 
    
         
             
                          result_transfer = []
         
     | 
| 
       713 
806 
     | 
    
         
             
                          formatter.display_status("found #{ids_to_download.length} package(s).")
         
     | 
| 
       714 
807 
     | 
    
         
             
                          ids_to_download.each do |package_id|
         
     | 
| 
       715 
     | 
    
         
            -
                            package_info = aoc_api.read("packages/#{package_id}") 
     | 
| 
      
 808 
     | 
    
         
            +
                            package_info = aoc_api.read("packages/#{package_id}")
         
     | 
| 
       716 
809 
     | 
    
         
             
                            formatter.display_status("downloading package: [#{package_info['id']}] #{package_info['name']}")
         
     | 
| 
       717 
810 
     | 
    
         
             
                            package_node_api = aoc_api.node_api_from(
         
     | 
| 
       718 
811 
     | 
    
         
             
                              node_id: package_info['node_id'],
         
     | 
| 
       719 
     | 
    
         
            -
                              workspace_id: aoc_api. 
     | 
| 
       720 
     | 
    
         
            -
                              workspace_name: aoc_api. 
     | 
| 
      
 812 
     | 
    
         
            +
                              workspace_id: aoc_api.workspace[:id],
         
     | 
| 
      
 813 
     | 
    
         
            +
                              workspace_name: aoc_api.workspace[:name],
         
     | 
| 
       721 
814 
     | 
    
         
             
                              package_info: package_info)
         
     | 
| 
       722 
815 
     | 
    
         
             
                            statuses = transfer.start(
         
     | 
| 
       723 
816 
     | 
    
         
             
                              package_node_api.transfer_spec_gen4(
         
     | 
| 
         @@ -735,132 +828,66 @@ module Aspera 
     | 
|
| 
       735 
828 
     | 
    
         
             
                          return Main.result_transfer_multiple(result_transfer)
         
     | 
| 
       736 
829 
     | 
    
         
             
                        when :show
         
     | 
| 
       737 
830 
     | 
    
         
             
                          package_id = instance_identifier
         
     | 
| 
       738 
     | 
    
         
            -
                          package_info = aoc_api.read("packages/#{package_id}") 
     | 
| 
      
 831 
     | 
    
         
            +
                          package_info = aoc_api.read("packages/#{package_id}")
         
     | 
| 
       739 
832 
     | 
    
         
             
                          return { type: :single_object, data: package_info }
         
     | 
| 
       740 
833 
     | 
    
         
             
                        when :list
         
     | 
| 
       741 
834 
     | 
    
         
             
                          display_fields = %w[id name bytes_transferred]
         
     | 
| 
       742 
     | 
    
         
            -
                          display_fields.push('workspace_id') if aoc_api. 
     | 
| 
      
 835 
     | 
    
         
            +
                          display_fields.push('workspace_id') if aoc_api.workspace[:id].eql?(:undefined)
         
     | 
| 
       743 
836 
     | 
    
         
             
                          return result_list('packages', fields: display_fields, base_query: PACKAGE_RECEIVED_BASE_QUERY) do |query|
         
     | 
| 
       744 
837 
     | 
    
         
             
                                   resolve_dropbox_name_default_ws_id(query)
         
     | 
| 
       745 
838 
     | 
    
         
             
                                 end
         
     | 
| 
       746 
839 
     | 
    
         
             
                        when :delete
         
     | 
| 
       747 
840 
     | 
    
         
             
                          return do_bulk_operation(command: package_command, descr: 'identifier', values: identifier) do |id|
         
     | 
| 
       748 
841 
     | 
    
         
             
                            Aspera.assert_values(id.class, [String, Integer]){'identifier'}
         
     | 
| 
       749 
     | 
    
         
            -
                            aoc_api.delete("packages/#{id}") 
     | 
| 
      
 842 
     | 
    
         
            +
                            aoc_api.delete("packages/#{id}")
         
     | 
| 
       750 
843 
     | 
    
         
             
                          end
         
     | 
| 
       751 
844 
     | 
    
         
             
                        when *Node::NODE4_READ_ACTIONS
         
     | 
| 
       752 
845 
     | 
    
         
             
                          package_id = instance_identifier
         
     | 
| 
       753 
     | 
    
         
            -
                          package_info = aoc_api.read("packages/#{package_id}") 
     | 
| 
      
 846 
     | 
    
         
            +
                          package_info = aoc_api.read("packages/#{package_id}")
         
     | 
| 
       754 
847 
     | 
    
         
             
                          return execute_nodegen4_command(package_command, package_info['node_id'], file_id: package_info['file_id'], scope: Api::Node::SCOPE_USER)
         
     | 
| 
       755 
848 
     | 
    
         
             
                        end
         
     | 
| 
       756 
849 
     | 
    
         
             
                      when :files
         
     | 
| 
       757 
850 
     | 
    
         
             
                        command_repo = options.get_next_command([:short_link].concat(NODE4_EXT_COMMANDS))
         
     | 
| 
       758 
851 
     | 
    
         
             
                        case command_repo
         
     | 
| 
       759 
852 
     | 
    
         
             
                        when *NODE4_EXT_COMMANDS
         
     | 
| 
       760 
     | 
    
         
            -
                          return execute_nodegen4_command(command_repo, aoc_api. 
     | 
| 
      
 853 
     | 
    
         
            +
                          return execute_nodegen4_command(command_repo, aoc_api.home[:node_id], file_id: aoc_api.home[:file_id], scope: Api::Node::SCOPE_USER)
         
     | 
| 
       761 
854 
     | 
    
         
             
                        when :short_link
         
     | 
| 
       762 
     | 
    
         
            -
                          link_type = options.get_next_argument('link type', accept_list: %i[public private])
         
     | 
| 
       763 
     | 
    
         
            -
                          short_link_command = options.get_next_command(%i[create delete list])
         
     | 
| 
       764 
855 
     | 
    
         
             
                          folder_dest = options.get_next_argument('path', validation: String)
         
     | 
| 
       765 
856 
     | 
    
         
             
                          home_node_api = aoc_api.node_api_from(
         
     | 
| 
       766 
     | 
    
         
            -
                            node_id:        aoc_api. 
     | 
| 
       767 
     | 
    
         
            -
                            workspace_id:   aoc_api. 
     | 
| 
       768 
     | 
    
         
            -
                            workspace_name: aoc_api. 
     | 
| 
       769 
     | 
    
         
            -
                          shared_apfid = home_node_api.resolve_api_fid(aoc_api. 
     | 
| 
       770 
     | 
    
         
            -
                           
     | 
| 
       771 
     | 
    
         
            -
                             
     | 
| 
       772 
     | 
    
         
            -
             
     | 
| 
       773 
     | 
    
         
            -
             
     | 
| 
       774 
     | 
    
         
            -
             
     | 
| 
       775 
     | 
    
         
            -
             
     | 
| 
       776 
     | 
    
         
            -
             
     | 
| 
       777 
     | 
    
         
            -
             
     | 
| 
       778 
     | 
    
         
            -
             
     | 
| 
       779 
     | 
    
         
            -
             
     | 
| 
       780 
     | 
    
         
            -
             
     | 
| 
       781 
     | 
    
         
            -
             
     | 
| 
       782 
     | 
    
         
            -
             
     | 
| 
       783 
     | 
    
         
            -
             
     | 
| 
       784 
     | 
    
         
            -
             
     | 
| 
       785 
     | 
    
         
            -
             
     | 
| 
       786 
     | 
    
         
            -
             
     | 
| 
       787 
     | 
    
         
            -
             
     | 
| 
       788 
     | 
    
         
            -
             
     | 
| 
       789 
     | 
    
         
            -
             
     | 
| 
       790 
     | 
    
         
            -
             
     | 
| 
       791 
     | 
    
         
            -
             
     | 
| 
       792 
     | 
    
         
            -
             
     | 
| 
       793 
     | 
    
         
            -
             
     | 
| 
       794 
     | 
    
         
            -
             
     | 
| 
       795 
     | 
    
         
            -
             
     | 
| 
       796 
     | 
    
         
            -
             
     | 
| 
       797 
     | 
    
         
            -
             
     | 
| 
       798 
     | 
    
         
            -
             
     | 
| 
       799 
     | 
    
         
            -
                                url_token_data: {
         
     | 
| 
       800 
     | 
    
         
            -
                                  data:    folder_info,
         
     | 
| 
       801 
     | 
    
         
            -
                                  purpose: 'view_shared_file'
         
     | 
| 
       802 
     | 
    
         
            -
                                }
         
     | 
| 
       803 
     | 
    
         
            -
                              }
         
     | 
| 
       804 
     | 
    
         
            -
                            end
         
     | 
| 
       805 
     | 
    
         
            -
                            list_params = {
         
     | 
| 
       806 
     | 
    
         
            -
                              json_query:  query.to_json,
         
     | 
| 
       807 
     | 
    
         
            -
                              purpose:     purpose,
         
     | 
| 
       808 
     | 
    
         
            -
                              edit_access: true,
         
     | 
| 
       809 
     | 
    
         
            -
                              # embed: 'updated_by_user',
         
     | 
| 
       810 
     | 
    
         
            -
                              sort:        '-created_at'
         
     | 
| 
       811 
     | 
    
         
            -
                            }
         
     | 
| 
       812 
     | 
    
         
            -
                            return result_list('short_links', fields: Formatter.all_but('data'), base_query: list_params)
         
     | 
| 
       813 
     | 
    
         
            -
                          when :create
         
     | 
| 
       814 
     | 
    
         
            -
                            creation_params = {
         
     | 
| 
       815 
     | 
    
         
            -
                              purpose:            purpose,
         
     | 
| 
       816 
     | 
    
         
            -
                              user_selected_name: nil
         
     | 
| 
       817 
     | 
    
         
            -
                            }
         
     | 
| 
       818 
     | 
    
         
            -
                            case link_type
         
     | 
| 
       819 
     | 
    
         
            -
                            when :private
         
     | 
| 
       820 
     | 
    
         
            -
                              creation_params[:data] = folder_info
         
     | 
| 
       821 
     | 
    
         
            -
                            when :public
         
     | 
| 
       822 
     | 
    
         
            -
                              creation_params[:expires_at]       = nil
         
     | 
| 
       823 
     | 
    
         
            -
                              creation_params[:password_enabled] = false
         
     | 
| 
       824 
     | 
    
         
            -
                              folder_info[:name] = ''
         
     | 
| 
       825 
     | 
    
         
            -
                              creation_params[:data] = {
         
     | 
| 
       826 
     | 
    
         
            -
                                aoc:            true,
         
     | 
| 
       827 
     | 
    
         
            -
                                url_token_data: {
         
     | 
| 
       828 
     | 
    
         
            -
                                  data:    folder_info,
         
     | 
| 
       829 
     | 
    
         
            -
                                  purpose: 'view_shared_file'
         
     | 
| 
       830 
     | 
    
         
            -
                                }
         
     | 
| 
       831 
     | 
    
         
            -
                              }
         
     | 
| 
       832 
     | 
    
         
            -
                            end
         
     | 
| 
       833 
     | 
    
         
            -
                            result_create_short_link = aoc_api.create('short_links', creation_params)[:data]
         
     | 
| 
       834 
     | 
    
         
            -
                            # public: Creation: permission on node
         
     | 
| 
       835 
     | 
    
         
            -
                            if link_type.eql?(:public)
         
     | 
| 
       836 
     | 
    
         
            -
                              # TODO: merge with node permissions ?
         
     | 
| 
       837 
     | 
    
         
            -
                              # TODO: access level as arg
         
     | 
| 
       838 
     | 
    
         
            -
                              access_levels = Api::Node::ACCESS_LEVELS # ['delete','list','mkdir','preview','read','rename','write']
         
     | 
| 
       839 
     | 
    
         
            -
                              folder_name = File.basename(folder_dest)
         
     | 
| 
       840 
     | 
    
         
            -
                              perm_data = {
         
     | 
| 
       841 
     | 
    
         
            -
                                'file_id'       => shared_apfid[:file_id],
         
     | 
| 
       842 
     | 
    
         
            -
                                'access_id'     => result_create_short_link['resource_id'],
         
     | 
| 
       843 
     | 
    
         
            -
                                'access_type'   => 'user',
         
     | 
| 
       844 
     | 
    
         
            -
                                'access_levels' => access_levels,
         
     | 
| 
       845 
     | 
    
         
            -
                                'tags'          => {
         
     | 
| 
       846 
     | 
    
         
            -
                                  'url_token'        => true,
         
     | 
| 
       847 
     | 
    
         
            -
                                  'workspace_id'     => aoc_api.context[:workspace_id],
         
     | 
| 
       848 
     | 
    
         
            -
                                  'workspace_name'   => aoc_api.context[:workspace_name],
         
     | 
| 
       849 
     | 
    
         
            -
                                  'folder_name'      => folder_name,
         
     | 
| 
       850 
     | 
    
         
            -
                                  'created_by_name'  => aoc_api.current_user_info['name'],
         
     | 
| 
       851 
     | 
    
         
            -
                                  'created_by_email' => aoc_api.current_user_info['email'],
         
     | 
| 
       852 
     | 
    
         
            -
                                  'access_key'       => shared_apfid[:api].app_info[:node_info]['access_key'],
         
     | 
| 
       853 
     | 
    
         
            -
                                  'node'             => shared_apfid[:api].app_info[:node_info]['host']
         
     | 
| 
       854 
     | 
    
         
            -
                                }
         
     | 
| 
       855 
     | 
    
         
            -
                              }
         
     | 
| 
       856 
     | 
    
         
            -
                              created_data = shared_apfid[:api].create('permissions', perm_data)[:data]
         
     | 
| 
       857 
     | 
    
         
            -
                              aoc_api.permissions_send_event(created_data: created_data, app_info: shared_apfid[:api].app_info)
         
     | 
| 
       858 
     | 
    
         
            -
                              # TODO: event ?
         
     | 
| 
       859 
     | 
    
         
            -
                            end
         
     | 
| 
       860 
     | 
    
         
            -
                            return {type: :single_object, data: result_create_short_link}
         
     | 
| 
       861 
     | 
    
         
            -
                          end
         
     | 
| 
      
 857 
     | 
    
         
            +
                            node_id:        aoc_api.home[:node_id],
         
     | 
| 
      
 858 
     | 
    
         
            +
                            workspace_id:   aoc_api.workspace[:id],
         
     | 
| 
      
 859 
     | 
    
         
            +
                            workspace_name: aoc_api.workspace[:name])
         
     | 
| 
      
 860 
     | 
    
         
            +
                          shared_apfid = home_node_api.resolve_api_fid(aoc_api.home[:file_id], folder_dest)
         
     | 
| 
      
 861 
     | 
    
         
            +
                          return short_link_command(
         
     | 
| 
      
 862 
     | 
    
         
            +
                            {
         
     | 
| 
      
 863 
     | 
    
         
            +
                              workspace_id: aoc_api.workspace[:id],
         
     | 
| 
      
 864 
     | 
    
         
            +
                              node_id:      shared_apfid[:api].app_info[:node_info]['id'],
         
     | 
| 
      
 865 
     | 
    
         
            +
                              file_id:      shared_apfid[:file_id]
         
     | 
| 
      
 866 
     | 
    
         
            +
                            }, purpose_public: 'view_shared_file') do |resource_id|
         
     | 
| 
      
 867 
     | 
    
         
            +
                                   # TODO: merge with node permissions ?
         
     | 
| 
      
 868 
     | 
    
         
            +
                                   # TODO: access level as arg
         
     | 
| 
      
 869 
     | 
    
         
            +
                                   access_levels = Api::Node::ACCESS_LEVELS # ['delete','list','mkdir','preview','read','rename','write']
         
     | 
| 
      
 870 
     | 
    
         
            +
                                   perm_data = {
         
     | 
| 
      
 871 
     | 
    
         
            +
                                     'file_id'       => shared_apfid[:file_id],
         
     | 
| 
      
 872 
     | 
    
         
            +
                                     'access_id'     => resource_id,
         
     | 
| 
      
 873 
     | 
    
         
            +
                                     'access_type'   => 'user',
         
     | 
| 
      
 874 
     | 
    
         
            +
                                     'access_levels' => access_levels,
         
     | 
| 
      
 875 
     | 
    
         
            +
                                     'tags'          => {
         
     | 
| 
      
 876 
     | 
    
         
            +
                                       # TODO: really just here ? not in tags.aspera.files.workspace ?
         
     | 
| 
      
 877 
     | 
    
         
            +
                                       'url_token'        => true,
         
     | 
| 
      
 878 
     | 
    
         
            +
                                       'workspace_id'     => aoc_api.workspace[:id],
         
     | 
| 
      
 879 
     | 
    
         
            +
                                       'workspace_name'   => aoc_api.workspace[:name],
         
     | 
| 
      
 880 
     | 
    
         
            +
                                       'folder_name'      => File.basename(folder_dest),
         
     | 
| 
      
 881 
     | 
    
         
            +
                                       'created_by_name'  => aoc_api.current_user_info['name'],
         
     | 
| 
      
 882 
     | 
    
         
            +
                                       'created_by_email' => aoc_api.current_user_info['email'],
         
     | 
| 
      
 883 
     | 
    
         
            +
                                       'access_key'       => shared_apfid[:api].app_info[:node_info]['access_key'],
         
     | 
| 
      
 884 
     | 
    
         
            +
                                       'node'             => shared_apfid[:api].app_info[:node_info]['host']
         
     | 
| 
      
 885 
     | 
    
         
            +
                                     }
         
     | 
| 
      
 886 
     | 
    
         
            +
                                   }
         
     | 
| 
      
 887 
     | 
    
         
            +
                                   created_data = shared_apfid[:api].create('permissions', perm_data)
         
     | 
| 
      
 888 
     | 
    
         
            +
                                   aoc_api.permissions_send_event(event_data: created_data, app_info: shared_apfid[:api].app_info)
         
     | 
| 
      
 889 
     | 
    
         
            +
                                 end
         
     | 
| 
       862 
890 
     | 
    
         
             
                        end
         
     | 
| 
       863 
     | 
    
         
            -
                        raise 'Error: shall not reach this line'
         
     | 
| 
       864 
891 
     | 
    
         
             
                      when :automation
         
     | 
| 
       865 
892 
     | 
    
         
             
                        Log.log.warn('BETA: work under progress')
         
     | 
| 
       866 
893 
     | 
    
         
             
                        # automation api is not in the same place
         
     | 
| 
         @@ -876,18 +903,18 @@ module Aspera 
     | 
|
| 
       876 
903 
     | 
    
         
             
                            return entity_command(wf_command, automation_api, 'workflows')
         
     | 
| 
       877 
904 
     | 
    
         
             
                          when :launch
         
     | 
| 
       878 
905 
     | 
    
         
             
                            wf_id = instance_identifier
         
     | 
| 
       879 
     | 
    
         
            -
                            data = automation_api.create("workflows/#{wf_id}/launch", {}) 
     | 
| 
      
 906 
     | 
    
         
            +
                            data = automation_api.create("workflows/#{wf_id}/launch", {})
         
     | 
| 
       880 
907 
     | 
    
         
             
                            return {type: :single_object, data: data}
         
     | 
| 
       881 
908 
     | 
    
         
             
                          when :action
         
     | 
| 
       882 
909 
     | 
    
         
             
                            # TODO: not complete
         
     | 
| 
       883 
910 
     | 
    
         
             
                            wf_id = instance_identifier
         
     | 
| 
       884 
911 
     | 
    
         
             
                            wf_action_cmd = options.get_next_command(%i[list create show])
         
     | 
| 
       885 
912 
     | 
    
         
             
                            Log.log.warn{"Not implemented: #{wf_action_cmd}"}
         
     | 
| 
       886 
     | 
    
         
            -
                            step = automation_api.create('steps', {'workflow_id' => wf_id}) 
     | 
| 
      
 913 
     | 
    
         
            +
                            step = automation_api.create('steps', {'workflow_id' => wf_id})
         
     | 
| 
       887 
914 
     | 
    
         
             
                            automation_api.update("workflows/#{wf_id}", {'step_order' => [step['id']]})
         
     | 
| 
       888 
     | 
    
         
            -
                            action = automation_api.create('actions', {'step_id' => step['id'], 'type' => 'manual'}) 
     | 
| 
      
 915 
     | 
    
         
            +
                            action = automation_api.create('actions', {'step_id' => step['id'], 'type' => 'manual'})
         
     | 
| 
       889 
916 
     | 
    
         
             
                            automation_api.update("steps/#{step['id']}", {'action_order' => [action['id']]})
         
     | 
| 
       890 
     | 
    
         
            -
                            wf = automation_api.read("workflows/#{wf_id}") 
     | 
| 
      
 917 
     | 
    
         
            +
                            wf = automation_api.read("workflows/#{wf_id}")
         
     | 
| 
       891 
918 
     | 
    
         
             
                            return {type: :single_object, data: wf}
         
     | 
| 
       892 
919 
     | 
    
         
             
                          end
         
     | 
| 
       893 
920 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -898,7 +925,8 @@ module Aspera 
     | 
|
| 
       898 
925 
     | 
    
         
             
                        url = value_create_modify(command: command, type: String)
         
     | 
| 
       899 
926 
     | 
    
         
             
                        uri = URI.parse(url)
         
     | 
| 
       900 
927 
     | 
    
         
             
                        server = WebServerSimple.new(uri)
         
     | 
| 
       901 
     | 
    
         
            -
                         
     | 
| 
      
 928 
     | 
    
         
            +
                        aoc_api.context = :files
         
     | 
| 
      
 929 
     | 
    
         
            +
                        server.mount(uri.path, Faspex4GWServlet, aoc_api, aoc_api.workspace[:id])
         
     | 
| 
       902 
930 
     | 
    
         
             
                        server.start
         
     | 
| 
       903 
931 
     | 
    
         
             
                        return Main.result_status('Gateway terminated')
         
     | 
| 
       904 
932 
     | 
    
         
             
                      else Aspera.error_unreachable_line
         
     |