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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +33 -0
  4. data/CONTRIBUTING.md +17 -12
  5. data/README.md +396 -185
  6. data/bin/asession +26 -19
  7. data/examples/build_exec +74 -0
  8. data/examples/{rubyc → build_exec_rubyc} +18 -2
  9. data/examples/get_proto_file.rb +7 -0
  10. data/lib/aspera/agent/alpha.rb +8 -8
  11. data/lib/aspera/agent/base.rb +4 -18
  12. data/lib/aspera/agent/connect.rb +14 -13
  13. data/lib/aspera/agent/direct.rb +123 -120
  14. data/lib/aspera/agent/httpgw.rb +2 -3
  15. data/lib/aspera/agent/node.rb +10 -10
  16. data/lib/aspera/agent/trsdk.rb +17 -20
  17. data/lib/aspera/api/alee.rb +15 -0
  18. data/lib/aspera/api/aoc.rb +128 -99
  19. data/lib/aspera/api/ats.rb +1 -1
  20. data/lib/aspera/api/cos_node.rb +1 -1
  21. data/lib/aspera/api/httpgw.rb +104 -64
  22. data/lib/aspera/api/node.rb +33 -12
  23. data/lib/aspera/ascmd.rb +56 -48
  24. data/lib/aspera/ascp/installation.rb +142 -70
  25. data/lib/aspera/ascp/management.rb +7 -3
  26. data/lib/aspera/ascp/products.rb +13 -7
  27. data/lib/aspera/assert.rb +10 -5
  28. data/lib/aspera/cli/formatter.rb +42 -26
  29. data/lib/aspera/cli/hints.rb +2 -1
  30. data/lib/aspera/cli/info.rb +12 -10
  31. data/lib/aspera/cli/main.rb +16 -13
  32. data/lib/aspera/cli/manager.rb +15 -10
  33. data/lib/aspera/cli/plugin.rb +17 -31
  34. data/lib/aspera/cli/plugin_factory.rb +10 -1
  35. data/lib/aspera/cli/plugins/alee.rb +3 -3
  36. data/lib/aspera/cli/plugins/aoc.rb +222 -194
  37. data/lib/aspera/cli/plugins/ats.rb +16 -14
  38. data/lib/aspera/cli/plugins/config.rb +66 -53
  39. data/lib/aspera/cli/plugins/console.rb +3 -3
  40. data/lib/aspera/cli/plugins/faspex.rb +11 -21
  41. data/lib/aspera/cli/plugins/faspex5.rb +44 -42
  42. data/lib/aspera/cli/plugins/faspio.rb +2 -2
  43. data/lib/aspera/cli/plugins/httpgw.rb +1 -1
  44. data/lib/aspera/cli/plugins/node.rb +155 -96
  45. data/lib/aspera/cli/plugins/orchestrator.rb +14 -13
  46. data/lib/aspera/cli/plugins/preview.rb +8 -9
  47. data/lib/aspera/cli/plugins/server.rb +6 -10
  48. data/lib/aspera/cli/plugins/shares.rb +13 -9
  49. data/lib/aspera/cli/sync_actions.rb +72 -31
  50. data/lib/aspera/cli/transfer_agent.rb +13 -14
  51. data/lib/aspera/cli/transfer_progress.rb +36 -18
  52. data/lib/aspera/cli/version.rb +1 -1
  53. data/lib/aspera/command_line_builder.rb +3 -4
  54. data/lib/aspera/coverage.rb +13 -1
  55. data/lib/aspera/environment.rb +59 -10
  56. data/lib/aspera/faspex_gw.rb +3 -3
  57. data/lib/aspera/json_rpc.rb +1 -1
  58. data/lib/aspera/keychain/encrypted_hash.rb +2 -0
  59. data/lib/aspera/keychain/macos_security.rb +7 -12
  60. data/lib/aspera/log.rb +4 -4
  61. data/lib/aspera/node_simulator.rb +1 -1
  62. data/lib/aspera/oauth/base.rb +39 -45
  63. data/lib/aspera/oauth/factory.rb +11 -4
  64. data/lib/aspera/oauth/generic.rb +4 -8
  65. data/lib/aspera/oauth/jwt.rb +4 -4
  66. data/lib/aspera/oauth/url_json.rb +3 -2
  67. data/lib/aspera/oauth/web.rb +10 -6
  68. data/lib/aspera/persistency_action_once.rb +16 -8
  69. data/lib/aspera/preview/utils.rb +5 -16
  70. data/lib/aspera/rest.rb +100 -76
  71. data/lib/aspera/secret_hider.rb +3 -2
  72. data/lib/aspera/ssh.rb +1 -1
  73. data/lib/aspera/transfer/faux_file.rb +7 -5
  74. data/lib/aspera/transfer/parameters.rb +41 -35
  75. data/lib/aspera/transfer/spec.rb +16 -18
  76. data/lib/aspera/transfer/sync.rb +51 -50
  77. data/lib/aspera/transfer/uri.rb +1 -1
  78. data/lib/aspera/uri_reader.rb +1 -1
  79. data/lib/aspera/web_auth.rb +166 -18
  80. data/lib/aspera/web_server_simple.rb +27 -15
  81. data/lib/transfer_pb.rb +84 -0
  82. data/lib/transfer_services_pb.rb +82 -0
  83. data.tar.gz.sig +0 -0
  84. metadata +25 -6
  85. 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
- result = Rest.new(base_url: base_url, redirect_max: 10).read('')
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 result[:http].uri.host.end_with?(Api::SAAS_DOMAIN_PROD)
72
- Log.log.debug{"AoC Main page: #{result[:http].body.include?(Api::AoC::PRODUCT_NAME)}"}
73
- base_url = result[:http].uri.to_s if result[:http].uri.path.include?('/public')
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]})[:data]
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')[:data]
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')[:data]
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
- # get identifier or name from command line
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.read(resource_class_path, query)
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.context[:workspace_id] unless aoc_api.context[:workspace_id].eql?(:undefined)
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.context[:workspace_id],
311
- workspace_name: aoc_api.context[:workspace_name],
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']}")[:data]['root_file_id'] if file_id.nil?
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 of source files', validation: String)
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)[:data]
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)[:data]
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(:files)
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')[:data]
466
- bss_api = api_from_options('bss/platform')
470
+ org = aoc_api.read('organization')
471
+ bss_graphql = api_from_options('bss/platform/graphql')
467
472
  # cspell:disable
468
- graphql_query = "
469
- query ($organization_id: ID!) {
470
- aoc (organization_id: $organization_id) {
471
- bssSubscription {
472
- endDate
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
- transferVolumeGb
491
- egressVolumeGb
492
- storageVolumeGb
493
- }
494
- paygoRate {
495
- rate
496
- currency
497
- }
498
- aocPlanData {
499
- tier
479
+ startDate
480
+ termMonths
481
+ plan
500
482
  trial
501
- workspaces { max }
502
- users {
503
- planAmount
504
- max
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 = bss_api.create('graphql', {'variables' => {'organization_id' => org['id']}, 'query' => graphql_query})[:data]['data']
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}")[:data][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.context(:files)[:workspace_name],
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))[:data][event_type]
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
- return result_list('usage_reports', base_query: {workspace_id: aoc_api.context(:files)[:workspace_id]})
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
- app_context = aoc_api.context(command)
590
- formatter.display_status("Workspace: #{app_context[:workspace_name].to_s.red}#{default_flag}")
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: app_context[:home_node_id]).read("files/#{app_context[:home_file_id]}")[:data]['name']
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})[:data]
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')[:data]}
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')[:data] }
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')[:data] }
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/')[:data]}
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
- return { type: :single_object, data: aoc_api.read("workspaces/#{aoc_api.context(:files)[:workspace_id]}")[:data] }
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)[:data] }
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.context[:workspace_id] unless aoc_api.context[:workspace_id].eql?(:undefined)
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'), query)[:data]}
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.context[:workspace_id]
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.context[:workspace_id]
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}")[:data]
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.context[:workspace_id],
720
- workspace_name: aoc_api.context[:workspace_name],
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}")[:data]
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.context[:workspace_id].eql?(:undefined)
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}")[:data]
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}")[:data]
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.context[:home_node_id], file_id: aoc_api.context[:home_file_id], scope: Api::Node::SCOPE_USER)
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.context[:home_node_id],
767
- workspace_id: aoc_api.context[:workspace_id],
768
- workspace_name: aoc_api.context[:workspace_name])
769
- shared_apfid = home_node_api.resolve_api_fid(aoc_api.context[:home_file_id], folder_dest)
770
- folder_info = {
771
- node_id: shared_apfid[:api].app_info[:node_info]['id'],
772
- file_id: shared_apfid[:file_id],
773
- workspace_id: aoc_api.context[:workspace_id]
774
- }
775
- purpose = case link_type
776
- when :public then 'token_auth_redirection'
777
- when :private then 'shared_folder_auth_link'
778
- else Aspera.error_unreachable_line
779
- end
780
- case short_link_command
781
- when :delete
782
- one_id = instance_identifier
783
- folder_info.delete(:workspace_id)
784
- delete_params = {
785
- edit_access: true,
786
- json_query: folder_info.to_json
787
- }
788
- aoc_api.delete("short_links/#{one_id}", delete_params)
789
- if link_type.eql?(:public)
790
- # TODO: get permission id..
791
- # shared_apfid[:api].delete('permissions', {ids: })[:data]
792
- end
793
- return Main.result_status('deleted')
794
- when :list
795
- query = if link_type.eql?(:private)
796
- folder_info
797
- else
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", {})[:data]
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})[:data]
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'})[:data]
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}")[:data]
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
- server.mount(uri.path, Faspex4GWServlet, aoc_api, aoc_api.context(:files)[:workspace_id])
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