aspera-cli 4.4.0 → 4.7.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 (97) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2095 -1503
  3. data/bin/ascli +2 -1
  4. data/bin/asession +4 -5
  5. data/docs/test_env.conf +3 -0
  6. data/examples/aoc.rb +4 -3
  7. data/examples/faspex4.rb +25 -25
  8. data/examples/proxy.pac +1 -1
  9. data/examples/transfer.rb +17 -17
  10. data/lib/aspera/aoc.rb +238 -185
  11. data/lib/aspera/ascmd.rb +93 -83
  12. data/lib/aspera/ats_api.rb +11 -10
  13. data/lib/aspera/cli/basic_auth_plugin.rb +13 -14
  14. data/lib/aspera/cli/extended_value.rb +42 -33
  15. data/lib/aspera/cli/formater.rb +142 -108
  16. data/lib/aspera/cli/info.rb +17 -0
  17. data/lib/aspera/cli/listener/line_dump.rb +3 -2
  18. data/lib/aspera/cli/listener/logger.rb +2 -1
  19. data/lib/aspera/cli/listener/progress.rb +16 -18
  20. data/lib/aspera/cli/listener/progress_multi.rb +18 -21
  21. data/lib/aspera/cli/main.rb +173 -149
  22. data/lib/aspera/cli/manager.rb +163 -168
  23. data/lib/aspera/cli/plugin.rb +43 -31
  24. data/lib/aspera/cli/plugins/alee.rb +6 -6
  25. data/lib/aspera/cli/plugins/aoc.rb +405 -370
  26. data/lib/aspera/cli/plugins/ats.rb +86 -79
  27. data/lib/aspera/cli/plugins/bss.rb +14 -16
  28. data/lib/aspera/cli/plugins/config.rb +580 -362
  29. data/lib/aspera/cli/plugins/console.rb +23 -19
  30. data/lib/aspera/cli/plugins/cos.rb +18 -18
  31. data/lib/aspera/cli/plugins/faspex.rb +201 -158
  32. data/lib/aspera/cli/plugins/faspex5.rb +80 -57
  33. data/lib/aspera/cli/plugins/node.rb +183 -166
  34. data/lib/aspera/cli/plugins/orchestrator.rb +71 -67
  35. data/lib/aspera/cli/plugins/preview.rb +92 -96
  36. data/lib/aspera/cli/plugins/server.rb +79 -75
  37. data/lib/aspera/cli/plugins/shares.rb +35 -19
  38. data/lib/aspera/cli/plugins/sync.rb +20 -22
  39. data/lib/aspera/cli/transfer_agent.rb +76 -113
  40. data/lib/aspera/cli/version.rb +2 -1
  41. data/lib/aspera/colors.rb +35 -27
  42. data/lib/aspera/command_line_builder.rb +48 -34
  43. data/lib/aspera/cos_node.rb +29 -21
  44. data/lib/aspera/data_repository.rb +3 -2
  45. data/lib/aspera/environment.rb +50 -45
  46. data/lib/aspera/fasp/{manager.rb → agent_base.rb} +28 -25
  47. data/lib/aspera/fasp/{connect.rb → agent_connect.rb} +52 -43
  48. data/lib/aspera/fasp/{local.rb → agent_direct.rb} +58 -72
  49. data/lib/aspera/fasp/{http_gw.rb → agent_httpgw.rb} +37 -43
  50. data/lib/aspera/fasp/{node.rb → agent_node.rb} +35 -16
  51. data/lib/aspera/fasp/agent_trsdk.rb +104 -0
  52. data/lib/aspera/fasp/error.rb +2 -1
  53. data/lib/aspera/fasp/error_info.rb +68 -52
  54. data/lib/aspera/fasp/installation.rb +152 -124
  55. data/lib/aspera/fasp/listener.rb +1 -0
  56. data/lib/aspera/fasp/parameters.rb +87 -92
  57. data/lib/aspera/fasp/parameters.yaml +305 -249
  58. data/lib/aspera/fasp/resume_policy.rb +11 -14
  59. data/lib/aspera/fasp/transfer_spec.rb +26 -0
  60. data/lib/aspera/fasp/uri.rb +22 -21
  61. data/lib/aspera/faspex_gw.rb +55 -89
  62. data/lib/aspera/hash_ext.rb +4 -3
  63. data/lib/aspera/id_generator.rb +8 -7
  64. data/lib/aspera/keychain/encrypted_hash.rb +121 -0
  65. data/lib/aspera/keychain/macos_security.rb +90 -0
  66. data/lib/aspera/log.rb +55 -37
  67. data/lib/aspera/nagios.rb +13 -12
  68. data/lib/aspera/node.rb +30 -25
  69. data/lib/aspera/oauth.rb +175 -226
  70. data/lib/aspera/open_application.rb +4 -3
  71. data/lib/aspera/persistency_action_once.rb +6 -6
  72. data/lib/aspera/persistency_folder.rb +5 -9
  73. data/lib/aspera/preview/file_types.rb +6 -5
  74. data/lib/aspera/preview/generator.rb +25 -24
  75. data/lib/aspera/preview/options.rb +16 -14
  76. data/lib/aspera/preview/utils.rb +98 -98
  77. data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
  78. data/lib/aspera/proxy_auto_config.rb +111 -20
  79. data/lib/aspera/rest.rb +154 -135
  80. data/lib/aspera/rest_call_error.rb +2 -2
  81. data/lib/aspera/rest_error_analyzer.rb +23 -25
  82. data/lib/aspera/rest_errors_aspera.rb +15 -14
  83. data/lib/aspera/ssh.rb +12 -10
  84. data/lib/aspera/sync.rb +42 -41
  85. data/lib/aspera/temp_file_manager.rb +18 -14
  86. data/lib/aspera/timer_limiter.rb +2 -1
  87. data/lib/aspera/uri_reader.rb +7 -5
  88. data/lib/aspera/web_auth.rb +79 -76
  89. metadata +116 -29
  90. data/docs/Makefile +0 -66
  91. data/docs/README.erb.md +0 -3973
  92. data/docs/README.md +0 -13
  93. data/docs/diagrams.txt +0 -49
  94. data/docs/doc_tools.rb +0 -58
  95. data/lib/aspera/api_detector.rb +0 -60
  96. data/lib/aspera/cli/plugins/shares2.rb +0 -114
  97. data/lib/aspera/secrets.rb +0 -20
@@ -1,21 +1,36 @@
1
+ # frozen_string_literal: true
1
2
  require 'aspera/cli/plugins/node'
2
3
  require 'aspera/cli/plugins/ats'
3
4
  require 'aspera/cli/basic_auth_plugin'
4
5
  require 'aspera/cli/transfer_agent'
6
+ require 'aspera/fasp/agent_node'
7
+ require 'aspera/fasp/transfer_spec'
5
8
  require 'aspera/aoc'
6
9
  require 'aspera/node'
7
10
  require 'aspera/persistency_action_once'
8
11
  require 'aspera/id_generator'
9
12
  require 'securerandom'
10
- require 'resolv'
11
13
  require 'date'
12
14
 
13
15
  module Aspera
14
16
  module Cli
15
17
  module Plugins
16
18
  class Aoc < BasicAuthPlugin
19
+ class << self
20
+ def detect(base_url)
21
+ api=Rest.new({base_url: base_url})
22
+ # either in standard domain, or product name in page
23
+ if URI.parse(base_url).host.end_with?(Aspera::AoC::PROD_DOMAIN) ||
24
+ api.call({operation: 'GET', redirect_max: 1, headers: {'Accept'=>'text/html'}})[:http].body.include?(Aspera::AoC::PRODUCT_NAME)
25
+ return {product: :aoc,version: 'SaaS' }
26
+ end
27
+ return nil
28
+ end
29
+ end
17
30
  # special value for package id
18
31
  VAL_ALL='ALL'
32
+ ID_AK_ADMIN='ASPERA_ACCESS_KEY_ADMIN'
33
+
19
34
  def initialize(env)
20
35
  super(env)
21
36
  @default_workspace_id=nil
@@ -25,122 +40,108 @@ module Aspera
25
40
  @home_node_file=nil
26
41
  @api_aoc=nil
27
42
  @url_token_data=nil
28
- @user_info=nil
29
43
  @api_aoc=nil
30
- self.options.add_opt_list(:auth,Oauth.auth_types,'OAuth type of authentication')
31
- self.options.add_opt_list(:operation,[:push,:pull],'client operation for transfers')
32
- self.options.add_opt_simple(:client_id,'OAuth API client identifier in application')
33
- self.options.add_opt_simple(:client_secret,'OAuth API client passcode')
34
- self.options.add_opt_simple(:redirect_uri,'OAuth API client redirect URI')
35
- self.options.add_opt_simple(:private_key,'OAuth JWT RSA private key PEM value (prefix file path with @val:@file:)')
36
- self.options.add_opt_simple(:workspace,'name of workspace')
37
- self.options.add_opt_simple(:name,'resource name')
38
- self.options.add_opt_simple(:path,'file or folder path')
39
- self.options.add_opt_simple(:link,'public link to shared resource')
40
- self.options.add_opt_simple(:new_user_option,'new user creation option')
41
- self.options.add_opt_simple(:from_folder,'share to share source folder')
42
- self.options.add_opt_simple(:scope,'OAuth scope for AoC API calls')
43
- self.options.add_opt_boolean(:bulk,'bulk operation')
44
- self.options.add_opt_boolean(:default_ports,'use standard FASP ports or get from node api')
45
- self.options.set_option(:bulk,:no)
46
- self.options.set_option(:default_ports,:yes)
47
- self.options.set_option(:new_user_option,{'package_contact'=>true})
48
- self.options.set_option(:operation,:push)
49
- self.options.set_option(:auth,:jwt)
50
- self.options.set_option(:scope,AoC::SCOPE_FILES_USER)
51
- self.options.set_option(:private_key,'@file:'+env[:private_key_path]) if env[:private_key_path].is_a?(String)
52
- self.options.parse_options!
53
- AoC.set_use_default_ports(self.options.get_option(:default_ports))
44
+ options.add_opt_list(:auth,Oauth::STD_AUTH_TYPES,'OAuth type of authentication')
45
+ options.add_opt_list(:operation,[:push,:pull],'client operation for transfers')
46
+ options.add_opt_simple(:client_id,'OAuth API client identifier in application')
47
+ options.add_opt_simple(:client_secret,'OAuth API client passcode')
48
+ options.add_opt_simple(:redirect_uri,'OAuth API client redirect URI')
49
+ options.add_opt_simple(:private_key,'OAuth JWT RSA private key PEM value (prefix file path with @val:@file:)')
50
+ options.add_opt_simple(:workspace,'name of workspace')
51
+ options.add_opt_simple(:name,'resource name')
52
+ options.add_opt_simple(:path,'file or folder path')
53
+ options.add_opt_simple(:link,'public link to shared resource')
54
+ options.add_opt_simple(:new_user_option,'new user creation option')
55
+ options.add_opt_simple(:from_folder,'share to share source folder')
56
+ options.add_opt_simple(:scope,'OAuth scope for AoC API calls')
57
+ options.add_opt_boolean(:bulk,'bulk operation')
58
+ options.add_opt_boolean(:default_ports,'use standard FASP ports or get from node api')
59
+ options.set_option(:bulk,:no)
60
+ options.set_option(:default_ports,:yes)
61
+ options.set_option(:new_user_option,{'package_contact'=>true})
62
+ options.set_option(:operation,:push)
63
+ options.set_option(:auth,:jwt)
64
+ options.set_option(:scope,AoC::SCOPE_FILES_USER)
65
+ options.set_option(:private_key,'@file:'+env[:private_key_path]) if env[:private_key_path].is_a?(String)
66
+ options.parse_options!
67
+ AoC.use_standard_ports=options.get_option(:default_ports)
54
68
  return if env[:man_only]
55
69
  end
56
70
 
57
- def get_api
71
+ def aoc_api
58
72
  if @api_aoc.nil?
59
73
  @api_aoc=AoC.new(aoc_params(AoC::API_V1))
60
74
  # add keychain for access key secrets
61
- @api_aoc.key_chain=@agents[:secret]
75
+ @api_aoc.key_chain=@agents[:config]
62
76
  end
63
77
  return @api_aoc
64
78
  end
65
79
 
66
- # cached user information
67
- def c_user_info
68
- if @user_info.nil?
69
- # get our user's default information
70
- # self?embed[]=default_workspace&embed[]=organization
71
- @user_info=@api_aoc.read('self')[:data] rescue {
72
- 'name' => 'unknown',
73
- 'email' => 'unknown',
74
- }
75
- end
76
- return @user_info
77
- end
78
-
79
80
  # starts transfer using transfer agent
80
81
  def transfer_start(app,direction,node_file,ts_add)
81
82
  ts_add.deep_merge!(AoC.analytics_ts(app,direction,@workspace_id,@workspace_name))
82
- ts_add.deep_merge!(AoC.console_ts(app,c_user_info['name'],c_user_info['email']))
83
- return self.transfer.start(*@api_aoc.tr_spec(app,direction,node_file,ts_add))
83
+ ts_add.deep_merge!(aoc_api.console_ts(app))
84
+ return transfer.start(*aoc_api.tr_spec(app,direction,node_file,ts_add))
84
85
  end
85
86
 
86
- NODE4_COMMANDS=[ :browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node, :node_info ]
87
+ NODE4_COMMANDS=[:browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node, :node_info].freeze
87
88
 
88
89
  def execute_node_gen4_command(command_repo,top_node_file)
89
90
  case command_repo
90
91
  when :bearer_token_node
91
- thepath=self.options.get_next_argument('path')
92
- node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
93
- node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER, use_secret: false)
92
+ thepath=options.get_next_argument('path')
93
+ node_file = aoc_api.resolve_node_file(top_node_file,thepath)
94
+ node_api=aoc_api.get_node_api(node_file[:node_info], use_secret: false)
94
95
  return Main.result_status(node_api.oauth_token)
95
96
  when :node_info
96
- thepath=self.options.get_next_argument('path')
97
- node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
98
- node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER, use_secret: false)
99
- return {:type=>:single_object,:data=>{
97
+ thepath=options.get_next_argument('path')
98
+ node_file = aoc_api.resolve_node_file(top_node_file,thepath)
99
+ node_api=aoc_api.get_node_api(node_file[:node_info], use_secret: false)
100
+ return {type: :single_object,data: {
100
101
  url: node_file[:node_info]['url'],
101
102
  username: node_file[:node_info]['access_key'],
102
103
  password: node_api.oauth_token,
103
104
  root_id: node_file[:file_id]
104
105
  }}
105
106
  when :browse
106
- thepath=self.options.get_next_argument('path')
107
- node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
108
- node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
107
+ thepath=options.get_next_argument('path')
108
+ node_file = aoc_api.resolve_node_file(top_node_file,thepath)
109
+ node_api=aoc_api.get_node_api(node_file[:node_info])
109
110
  file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
110
111
  if file_info['type'].eql?('folder')
111
- result=node_api.read("files/#{node_file[:file_id]}/files",self.options.get_option(:value,:optional))
112
+ result=node_api.read("files/#{node_file[:file_id]}/files",options.get_option(:value,:optional))
112
113
  items=result[:data]
113
114
  self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
114
115
  else
115
116
  items=[file_info]
116
117
  end
117
- return {:type=>:object_list,:data=>items,:fields=>['name','type','recursive_size','size','modified_time','access_level']}
118
+ return {type: :object_list,data: items,fields: ['name','type','recursive_size','size','modified_time','access_level']}
118
119
  when :find
119
- thepath=self.options.get_next_argument('path')
120
- node_file=@api_aoc.resolve_node_file(top_node_file,thepath)
121
- test_block=Aspera::Node.file_matcher(self.options.get_option(:value,:optional))
122
- return {:type=>:object_list,:data=>@api_aoc.find_files(node_file,test_block),:fields=>['path']}
120
+ thepath=options.get_next_argument('path')
121
+ node_file=aoc_api.resolve_node_file(top_node_file,thepath)
122
+ test_block=Aspera::Node.file_matcher(options.get_option(:value,:optional))
123
+ return {type: :object_list,data: aoc_api.find_files(node_file,test_block),fields: ['path']}
123
124
  when :mkdir
124
- thepath=self.options.get_next_argument('path')
125
+ thepath=options.get_next_argument('path')
125
126
  containing_folder_path = thepath.split(AoC::PATH_SEPARATOR)
126
127
  new_folder=containing_folder_path.pop
127
- node_file = @api_aoc.resolve_node_file(top_node_file,containing_folder_path.join(AoC::PATH_SEPARATOR))
128
- node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
129
- result=node_api.create("files/#{node_file[:file_id]}/files",{:name=>new_folder,:type=>:folder})[:data]
128
+ node_file = aoc_api.resolve_node_file(top_node_file,containing_folder_path.join(AoC::PATH_SEPARATOR))
129
+ node_api=aoc_api.get_node_api(node_file[:node_info])
130
+ result=node_api.create("files/#{node_file[:file_id]}/files",{name: new_folder,type: :folder})[:data]
130
131
  return Main.result_status("created: #{result['name']} (id=#{result['id']})")
131
132
  when :rename
132
- thepath=self.options.get_next_argument('source path')
133
- newname=self.options.get_next_argument('new name')
134
- node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
135
- node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
136
- result=node_api.update("files/#{node_file[:file_id]}",{:name=>newname})[:data]
133
+ thepath=options.get_next_argument('source path')
134
+ newname=options.get_next_argument('new name')
135
+ node_file = aoc_api.resolve_node_file(top_node_file,thepath)
136
+ node_api=aoc_api.get_node_api(node_file[:node_info])
137
+ result=node_api.update("files/#{node_file[:file_id]}",{name: newname})[:data]
137
138
  return Main.result_status("renamed #{thepath} to #{newname}")
138
139
  when :delete
139
- thepath=self.options.get_next_argument('path')
140
+ thepath=options.get_next_argument('path')
140
141
  return do_bulk_operation(thepath,'deleted','path') do |l_path|
141
142
  raise "expecting String (path), got #{l_path.class.name} (#{l_path})" unless l_path.is_a?(String)
142
- node_file = @api_aoc.resolve_node_file(top_node_file,l_path)
143
- node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
143
+ node_file = aoc_api.resolve_node_file(top_node_file,l_path)
144
+ node_api=aoc_api.get_node_api(node_file[:node_info])
144
145
  result=node_api.delete("files/#{node_file[:file_id]}")[:data]
145
146
  {'path'=>l_path}
146
147
  end
@@ -150,20 +151,26 @@ module Aspera
150
151
  # in same workspace
151
152
  server_home_node_file=client_home_node_file=top_node_file
152
153
  # default is push
153
- case self.options.get_option(:operation,:mandatory)
154
+ case options.get_option(:operation,:mandatory)
154
155
  when :push
155
- client_tr_oper='send'
156
- client_folder=self.options.get_option(:from_folder,:mandatory)
157
- server_folder=self.transfer.destination_folder(client_tr_oper)
156
+ client_tr_oper=Fasp::TransferSpec::DIRECTION_SEND
157
+ client_folder=options.get_option(:from_folder,:mandatory)
158
+ server_folder=transfer.destination_folder(client_tr_oper)
158
159
  when :pull
159
- client_tr_oper='receive'
160
- client_folder=self.transfer.destination_folder(client_tr_oper)
161
- server_folder=self.options.get_option(:from_folder,:mandatory)
160
+ client_tr_oper=Fasp::TransferSpec::DIRECTION_RECEIVE
161
+ client_folder=transfer.destination_folder(client_tr_oper)
162
+ server_folder=options.get_option(:from_folder,:mandatory)
162
163
  end
163
- client_node_file = @api_aoc.resolve_node_file(client_home_node_file,client_folder)
164
- server_node_file = @api_aoc.resolve_node_file(server_home_node_file,server_folder)
164
+ client_node_file = aoc_api.resolve_node_file(client_home_node_file,client_folder)
165
+ server_node_file = aoc_api.resolve_node_file(server_home_node_file,server_folder)
165
166
  # force node as transfer agent
166
- @agents[:transfer].set_agent_instance(Fasp::Node.new(@api_aoc.get_node_api(client_node_file[:node_info],scope: AoC::SCOPE_NODE_USER)))
167
+ client_node_api=aoc_api.get_node_api(client_node_file[:node_info], use_secret: false)
168
+ @agents[:transfer].agent_instance=Fasp::AgentNode.new({
169
+ url: client_node_api.params[:base_url],
170
+ username: client_node_file[:node_info]['access_key'],
171
+ password: client_node_api.oauth_token,
172
+ root_id: client_node_file[:file_id]
173
+ })
167
174
  # additional node to node TS info
168
175
  add_ts={
169
176
  'remote_access_key' => server_node_file[:node_info]['access_key'],
@@ -172,11 +179,11 @@ module Aspera
172
179
  }
173
180
  return Main.result_transfer(transfer_start(AoC::FILES_APP,client_tr_oper,server_node_file,add_ts))
174
181
  when :upload
175
- node_file = @api_aoc.resolve_node_file(top_node_file,self.transfer.destination_folder('send'))
182
+ node_file = aoc_api.resolve_node_file(top_node_file,transfer.destination_folder(Fasp::TransferSpec::DIRECTION_SEND))
176
183
  add_ts={'tags'=>{'aspera'=>{'files'=>{'parentCwd'=>"#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
177
- return Main.result_transfer(transfer_start(AoC::FILES_APP,'send',node_file,add_ts))
184
+ return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_SEND,node_file,add_ts))
178
185
  when :download
179
- source_paths=self.transfer.ts_source_paths
186
+ source_paths=transfer.ts_source_paths
180
187
  # special case for AoC : all files must be in same folder
181
188
  source_folder=source_paths.shift['source']
182
189
  # if a single file: split into folder and path
@@ -185,13 +192,13 @@ module Aspera
185
192
  source_paths=[{'source'=>source_folder.pop}]
186
193
  source_folder=source_folder.join(AoC::PATH_SEPARATOR)
187
194
  end
188
- node_file = @api_aoc.resolve_node_file(top_node_file,source_folder)
195
+ node_file = aoc_api.resolve_node_file(top_node_file,source_folder)
189
196
  # override paths with just filename
190
197
  add_ts={'tags'=>{'aspera'=>{'files'=>{'parentCwd'=>"#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
191
198
  add_ts.merge!({'paths'=>source_paths})
192
- return Main.result_transfer(transfer_start(AoC::FILES_APP,'receive',node_file,add_ts))
199
+ return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_RECEIVE,node_file,add_ts))
193
200
  when :http_node_download
194
- source_paths=self.transfer.ts_source_paths
201
+ source_paths=transfer.ts_source_paths
195
202
  source_folder=source_paths.shift['source']
196
203
  if source_paths.empty?
197
204
  source_folder=source_folder.split(AoC::PATH_SEPARATOR)
@@ -200,35 +207,37 @@ module Aspera
200
207
  end
201
208
  raise CliBadArgument,'one file at a time only in HTTP mode' if source_paths.length > 1
202
209
  file_name = source_paths.first['source']
203
- node_file = @api_aoc.resolve_node_file(top_node_file,File.join(source_folder,file_name))
204
- node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
205
- node_api.call({:operation=>'GET',:subpath=>"files/#{node_file[:file_id]}/content",:save_to_file=>File.join(self.transfer.destination_folder('receive'),file_name)})
210
+ node_file = aoc_api.resolve_node_file(top_node_file,File.join(source_folder,file_name))
211
+ node_api=aoc_api.get_node_api(node_file[:node_info])
212
+ node_api.call({operation: 'GET',subpath: "files/#{node_file[:file_id]}/content",
213
+ save_to_file: File.join(transfer.destination_folder(Fasp::TransferSpec::DIRECTION_RECEIVE),file_name)})
206
214
  return Main.result_status("downloaded: #{file_name}")
207
215
  when :v3
208
216
  # Note: other common actions are unauthorized with user scope
209
- command_legacy=self.options.get_next_command(Node::SIMPLE_ACTIONS)
217
+ command_legacy=options.get_next_command(Node::SIMPLE_ACTIONS)
210
218
  # TODO: shall we support all methods here ? what if there is a link ?
211
- node_api=@api_aoc.get_node_api(top_node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
219
+ node_api=aoc_api.get_node_api(top_node_file[:node_info])
212
220
  return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: node_api)).execute_action(command_legacy)
213
221
  when :file
214
- file_path=self.options.get_option(:path,:optional)
215
- node_file = if !file_path.nil?
216
- @api_aoc.resolve_node_file(top_node_file,file_path) # TODO: allow follow link ?
222
+ command_node_file=options.get_next_command([:show,:permission,:modify])
223
+ file_path=options.get_option(:path,:optional)
224
+ node_file =
225
+ if !file_path.nil?
226
+ aoc_api.resolve_node_file(top_node_file,file_path) # TODO: allow follow link ?
217
227
  else
218
- {node_info: top_node_file[:node_info],file_id: self.options.get_option(:id,:mandatory)}
228
+ {node_info: top_node_file[:node_info],file_id: instance_identifier()}
219
229
  end
220
- node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
221
- command_node_file=self.options.get_next_command([:show,:permission,:modify])
230
+ node_api=aoc_api.get_node_api(node_file[:node_info])
222
231
  case command_node_file
223
232
  when :show
224
233
  items=node_api.read("files/#{node_file[:file_id]}")[:data]
225
- return {:type=>:single_object,:data=>items}
234
+ return {type: :single_object,data: items}
226
235
  when :modify
227
- update_param=self.options.get_next_argument('update data (Hash)')
236
+ update_param=options.get_next_argument('update data (Hash)')
228
237
  res=node_api.update("files/#{node_file[:file_id]}",update_param)[:data]
229
- return {:type=>:single_object,:data=>res}
238
+ return {type: :single_object,data: res}
230
239
  when :permission
231
- command_perm=self.options.get_next_command([:list,:create])
240
+ command_perm=options.get_next_command([:list,:create])
232
241
  case command_perm
233
242
  when :list
234
243
  # generic options : TODO: as arg ? option_url_query
@@ -240,11 +249,11 @@ module Aspera
240
249
  list_options['inherited']||=false
241
250
  end
242
251
  items=node_api.read('permissions',list_options)[:data]
243
- return {:type=>:object_list,:data=>items}
252
+ return {type: :object_list,data: items}
244
253
  when :create
245
254
  #create_param=self.options.get_next_argument('creation data (Hash)')
246
255
  set_workspace_info
247
- access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
256
+ access_id="#{ID_AK_ADMIN}_WS_#{@workspace_id}"
248
257
  node_file[:node_info]
249
258
  params={
250
259
  'file_id' =>node_file[:file_id], # mandatory
@@ -254,23 +263,19 @@ module Aspera
254
263
  'tags' =>{'aspera'=>{'files'=>{'workspace'=>{
255
264
  'id' =>@workspace_id,
256
265
  'workspace_name' =>@workspace_name,
257
- 'user_name' =>c_user_info['name'],
258
- 'shared_by_user_id'=>c_user_info['id'],
259
- 'shared_by_name' =>c_user_info['name'],
260
- 'shared_by_email' =>c_user_info['email'],
266
+ 'user_name' =>aoc_api.user_info['name'],
267
+ 'shared_by_user_id'=>aoc_api.user_info['id'],
268
+ 'shared_by_name' =>aoc_api.user_info['name'],
269
+ 'shared_by_email' =>aoc_api.user_info['email'],
261
270
  'shared_with_name' =>access_id,
262
271
  'access_key' =>node_file[:node_info]['access_key'],
263
272
  'node' =>node_file[:node_info]['name']}}}}}
264
273
  item=node_api.create('permissions',params)[:data]
265
- return {:type=>:single_object,:data=>item}
274
+ return {type: :single_object,data: item}
266
275
  else raise "internal error:shall not reach here (#{command_perm})"
267
276
  end
268
- raise 'internal error:shall not reach here'
269
277
  else raise "internal error:shall not reach here (#{command_node_file})"
270
278
  end
271
- raise 'internal error:shall not reach here'
272
- when :permissions
273
-
274
279
  end # command_repo
275
280
  raise 'ERR'
276
281
  end # execute_node_gen4_command
@@ -278,7 +283,7 @@ module Aspera
278
283
  # build constructor option list for AoC based on options of CLI
279
284
  def aoc_params(subpath)
280
285
  # copy command line options to args
281
- opt=[:link,:url,:auth,:client_id,:client_secret,:scope,:redirect_uri,:private_key,:username,:password].inject({}){|m,i|m[i]=self.options.get_option(i,:optional);m}
286
+ opt=[:link,:url,:auth,:client_id,:client_secret,:scope,:redirect_uri,:private_key,:username,:password].each_with_object({}){|i,m|m[i]=options.get_option(i,:optional);}
282
287
  opt[:subpath]=subpath
283
288
  return opt
284
289
  end
@@ -291,17 +296,16 @@ module Aspera
291
296
  # @persist_ids
292
297
  # returns nil
293
298
  def set_workspace_info
294
- if @api_aoc.params[:auth].has_key?(:url_token)
295
- # TODO: can there be several in list ?
296
- @url_token_data=@api_aoc.read('url_tokens')[:data].first
299
+ @url_token_data=aoc_api.url_token_data
300
+ if @url_token_data.nil?
301
+ @default_workspace_id=aoc_api.user_info['default_workspace_id']
302
+ @persist_ids=[aoc_api.user_info['id']]
303
+ else
297
304
  @default_workspace_id=@url_token_data['data']['workspace_id']
298
305
  @persist_ids=[] # TODO : @url_token_data['id'] ?
299
- else
300
- @default_workspace_id=c_user_info['default_workspace_id']
301
- @persist_ids=[c_user_info['id']]
302
306
  end
303
307
 
304
- ws_name=self.options.get_option(:workspace,:optional)
308
+ ws_name=options.get_option(:workspace,:optional)
305
309
  if ws_name.nil?
306
310
  Log.log.debug('using default workspace'.green)
307
311
  if @default_workspace_id.eql?(nil)
@@ -311,7 +315,7 @@ module Aspera
311
315
  @workspace_id=@default_workspace_id
312
316
  else
313
317
  # lookup another workspace
314
- wss=@api_aoc.read('workspaces',{'q'=>ws_name})[:data]
318
+ wss=aoc_api.read('workspaces',{'q'=>ws_name})[:data]
315
319
  wss=wss.select { |i| i['name'].eql?(ws_name) }
316
320
  case wss.length
317
321
  when 0
@@ -322,7 +326,7 @@ module Aspera
322
326
  raise 'unexpected case'
323
327
  end
324
328
  end
325
- @workspace_data=@api_aoc.read("workspaces/#{@workspace_id}")[:data]
329
+ @workspace_data=aoc_api.read("workspaces/#{@workspace_id}")[:data]
326
330
  Log.log.debug("workspace_id=#{@workspace_id},@workspace_data=#{@workspace_data}".red)
327
331
 
328
332
  @workspace_name||=@workspace_data['name']
@@ -344,16 +348,16 @@ module Aspera
344
348
  home_file_id||=@workspace_data['home_file_id']
345
349
  raise 'node_id must be defined' if home_node_id.to_s.empty?
346
350
  @home_node_file={
347
- node_info: @api_aoc.read("nodes/#{home_node_id}")[:data],
351
+ node_info: aoc_api.read("nodes/#{home_node_id}")[:data],
348
352
  file_id: home_file_id
349
353
  }
350
- @api_aoc.check_get_node_file(@home_node_file)
354
+ aoc_api.check_get_node_file(@home_node_file)
351
355
 
352
356
  return nil
353
357
  end
354
358
 
355
359
  def do_bulk_operation(ids_or_one,success_msg,id_result='id',&do_action)
356
- ids_or_one=[ids_or_one] unless self.options.get_option(:bulk)
360
+ ids_or_one=[ids_or_one] unless options.get_option(:bulk)
357
361
  raise 'expecting Array' unless ids_or_one.is_a?(Array)
358
362
  result_list=[]
359
363
  ids_or_one.each do |id|
@@ -362,75 +366,107 @@ module Aspera
362
366
  res=do_action.call(id)
363
367
  one=res if id.is_a?(Hash) # if block returns a has, let's use this
364
368
  one['status']=success_msg
365
- rescue => e
369
+ rescue StandardError => e
366
370
  one['status']=e.to_s
367
371
  end
368
372
  result_list.push(one)
369
373
  end
370
- return {:type=>:object_list,:data=>result_list,:fields=>[id_result,'status']}
374
+ return {type: :object_list,data: result_list,fields: [id_result,'status']}
375
+ end
376
+
377
+ # get identifier or name from command line
378
+ # @return identifier
379
+ def get_resource_id_from_args(resource_class_path)
380
+ l_res_id=options.get_option(:id)
381
+ l_res_name=options.get_option(:name)
382
+ raise 'Provide either option id or name, not both' unless l_res_id.nil? || l_res_name.nil?
383
+ # try to find item by name (single partial match or exact match)
384
+ l_res_id=aoc_api.lookup_entity_by_name(resource_class_path,l_res_name)['id'] unless l_res_name.nil?
385
+ # if no name or id option, taken on command line (after command)
386
+ if l_res_id.nil?
387
+ l_res_id=options.get_next_argument('identifier')
388
+ l_res_id=aoc_api.lookup_entity_by_name(resource_class_path,options.get_next_argument('identifier'))['id'] if l_res_id.eql?('name')
389
+ end
390
+ return l_res_id
391
+ end
392
+
393
+ def get_resource_path_from_args(resource_class_path)
394
+ return "#{resource_class_path}/#{get_resource_id_from_args(resource_class_path)}"
371
395
  end
372
396
 
373
397
  # package creation params can give just email, and full hash is created
374
- def resolve_package_recipients(package_creation,recipient_list_field)
375
- return unless package_creation.has_key?(recipient_list_field)
376
- raise CliBadArgument,"#{recipient_list_field} must be an Array" unless package_creation[recipient_list_field].is_a?(Array)
377
- new_user_option=self.options.get_option(:new_user_option,:mandatory)
398
+ def resolve_package_recipients(package_data,recipient_list_field)
399
+ return unless package_data.has_key?(recipient_list_field)
400
+ raise CliBadArgument,"#{recipient_list_field} must be an Array" unless package_data[recipient_list_field].is_a?(Array)
401
+ new_user_option=options.get_option(:new_user_option,:mandatory)
402
+ # list with resolved elements
378
403
  resolved_list=[]
379
- package_creation[recipient_list_field].each do |recipient_email_or_info|
380
- case recipient_email_or_info
381
- when Hash
382
- raise 'recipient element hash shall have field id and type' unless recipient_email_or_info.has_key?('id') and recipient_email_or_info.has_key?('type')
383
- # already provided all information ?
384
- resolved_list.push(recipient_email_or_info)
385
- when String
386
- if recipient_email_or_info.include?('@')
387
- # or need to resolve email
388
- item_lookup=@api_aoc.read('contacts',{'current_workspace_id'=>@workspace_id,'q'=>recipient_email_or_info})[:data]
389
- case item_lookup.length
390
- when 1; recipient_user_id=item_lookup.first
391
- when 0; recipient_user_id=@api_aoc.create('contacts',{'current_workspace_id'=>@workspace_id,'email'=>recipient_email_or_info}.merge(new_user_option))[:data]
392
- else raise CliBadArgument,"multiple match for: #{recipient_email_or_info}"
393
- end
394
- resolved_list.push({'id'=>recipient_user_id['source_id'],'type'=>recipient_user_id['source_type']})
395
- else
396
- item_lookup=@api_aoc.read('dropboxes',{'current_workspace_id'=>@workspace_id,'q'=>recipient_email_or_info})[:data]
397
- case item_lookup.length
398
- when 1; recipient_user_id=item_lookup.first
399
- when 0; raise "no such shared inbox in workspace #{@workspace_name}"
400
- else raise CliBadArgument,"multiple match for: #{recipient_email_or_info}"
401
- end
402
- resolved_list.push({'id'=>recipient_user_id['id'],'type'=>'dropbox'})
404
+ package_data[recipient_list_field].each do |short_recipient_info|
405
+ case short_recipient_info
406
+ when Hash # native api information, check keys
407
+ raise "#{recipient_list_field} element shall have fields: id and type" unless short_recipient_info.keys.sort.eql?(['id','type'])
408
+ when String # need to resolve name to type/id
409
+ # email: user, else dropbox
410
+ entity_type=short_recipient_info.include?('@') ? 'contacts' : 'dropboxes'
411
+ begin
412
+ full_recipient_info=aoc_api.lookup_entity_by_name(entity_type,short_recipient_info,{'current_workspace_id'=>@workspace_id})
413
+ rescue RuntimeError => e
414
+ raise e unless e.message.eql?('not found')
415
+ raise "no such shared inbox in workspace #{@workspace_name}" unless entity_type.eql?('contacts')
416
+ full_recipient_info=aoc_api.create('contacts',{'current_workspace_id'=>@workspace_id,'email'=>short_recipient_info}.merge(new_user_option))[:data]
403
417
  end
404
- else
405
- raise "recipient item must be a String (email, shared inboc) or hash (id,type)"
418
+ short_recipient_info=entity_type.eql?('dropboxes') ? {'id'=>full_recipient_info['id'],'type'=>'dropbox'} : {'id'=>full_recipient_info['source_id'],'type'=>full_recipient_info['source_type']}
419
+ else # unexpected extended value, must be String or Hash
420
+ raise "#{recipient_list_field} item must be a String (email, shared inbox) or Hash (id,type)"
421
+ end # type of recipient info
422
+ # add original or resolved recipient info
423
+ resolved_list.push(short_recipient_info)
424
+ end
425
+ # replace with resolved elements
426
+ package_data[recipient_list_field]=resolved_list
427
+ end
428
+
429
+ def normalize_metadata(pkg_data)
430
+ case pkg_data['metadata']
431
+ when NilClass then return
432
+ when Array then return
433
+ when Hash
434
+ api_meta=[]
435
+ pkg_data['metadata'].each do |k,v|
436
+ api_meta.push({
437
+ #'input_type' => 'single-dropdown',
438
+ 'name' => k,
439
+ 'values' => v.is_a?(Array) ? v : [v]
440
+ })
406
441
  end
442
+ pkg_data['metadata']=api_meta
443
+ else raise "metadata field if not of expected type: #{pkg_meta.class}"
407
444
  end
408
- package_creation[recipient_list_field]=resolved_list
445
+ nil
409
446
  end
410
447
 
411
448
  # private
412
449
  def option_url_query(default)
413
- query=self.options.get_option(:query,:optional)
450
+ query=options.get_option(:query,:optional)
414
451
  query=default if query.nil?
415
452
  Log.log.debug("Query=#{query}".bg_red)
416
453
  begin
417
454
  # check it is suitable
418
455
  URI.encode_www_form(query) unless query.nil?
419
- rescue => e
456
+ rescue StandardError => e
420
457
  raise CliBadArgument,"query must be an extended value which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
421
458
  end
422
459
  return query
423
460
  end
424
461
 
425
462
  def assert_public_link_types(expected)
426
- if !expected.include?(@url_token_data['purpose'])
427
- raise CliBadArgument,"public link type is #{@url_token_data['purpose']} but action requires one of #{expected.join(',')}"
428
- end
463
+ raise CliBadArgument,"public link type is #{@url_token_data['purpose']} but action requires one of #{expected.join(',')}" unless expected.include?(@url_token_data['purpose'])
429
464
  end
430
465
 
431
- # Call @api_aoc.read with same parameters, but use paging if necessary to get all results
466
+ # Call aoc_api.read with same parameters.
467
+ # Use paging if necessary to get all results
432
468
  def read_with_paging(resource_class_path,base_query)
433
- raise "Query must be Hash" unless base_query.is_a?(Hash)
469
+ raise 'Query must be Hash' unless base_query.is_a?(Hash)
434
470
  # set default large page if user does not specify own parameters. AoC Caps to 1000 anyway
435
471
  base_query['per_page']=1000 unless base_query.has_key?('per_page')
436
472
  max_items=base_query[MAX_ITEMS]
@@ -445,7 +481,7 @@ module Aspera
445
481
  loop do
446
482
  query=base_query.clone
447
483
  query['page']=current_page
448
- result=@api_aoc.read(resource_class_path,query)
484
+ result=aoc_api.read(resource_class_path,query)
449
485
  total_count=result[:http]['X-Total-Count']
450
486
  page_count+=1
451
487
  current_page+=1
@@ -453,26 +489,28 @@ module Aspera
453
489
  break if add_items.empty?
454
490
  # append new items to full list
455
491
  item_list += add_items
456
- break if !max_pages.nil? and page_count > max_pages
457
- break if !max_items.nil? and item_list.count > max_items
492
+ break if !max_pages.nil? && page_count > max_pages
493
+ break if !max_items.nil? && item_list.count > max_items
458
494
  end
459
495
  return item_list,total_count
460
496
  end
461
497
 
462
498
  def execute_admin_action
463
- @api_aoc.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
464
- command_admin=self.options.get_next_command([ :ats, :resource, :usage_reports, :analytics, :subscription, :auth_providers ])
499
+ # upgrade scope to admin
500
+ aoc_api.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
501
+ command_admin=options.get_next_command([:ats, :resource, :usage_reports, :analytics, :subscription, :auth_providers])
465
502
  case command_admin
466
503
  when :auth_providers
467
- command_auth_prov=self.options.get_next_command([ :list, :update ])
504
+ command_auth_prov=options.get_next_command([:list, :update])
468
505
  case command_auth_prov
469
506
  when :list
470
- providers=@api_aoc.read('admin/auth_providers')[:data]
471
- return {:type=>:object_list,:data=>providers}
507
+ providers=aoc_api.read('admin/auth_providers')[:data]
508
+ return {type: :object_list,data: providers}
472
509
  when :update
510
+ raise 'not implemented'
473
511
  end
474
512
  when :subscription
475
- org=@api_aoc.read('organization')[:data]
513
+ org=aoc_api.read('organization')[:data]
476
514
  bss_api=AoC.new(aoc_params('bss/platform'))
477
515
  graphql_query="
478
516
  query ($organization_id: ID!) {
@@ -523,43 +561,43 @@ module Aspera
523
561
  }
524
562
  "
525
563
  result=bss_api.create('graphql',{'variables'=>{'organization_id'=>org['id']},'query'=>graphql_query})[:data]['data']
526
- return {:type=>:single_object,:data=>result['aoc']['bssSubscription']}
564
+ return {type: :single_object,data: result['aoc']['bssSubscription']}
527
565
  when :ats
528
- ats_api = Rest.new(@api_aoc.params.deep_merge({
529
- :base_url => @api_aoc.params[:base_url]+'/admin/ats/pub/v1',
530
- :auth => {:scope => AoC::SCOPE_FILES_ADMIN_USER}
566
+ ats_api = Rest.new(aoc_api.params.deep_merge({
567
+ base_url: aoc_api.params[:base_url]+'/admin/ats/pub/v1',
568
+ auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
531
569
  }))
532
570
  return Ats.new(@agents).execute_action_gen(ats_api)
533
571
  when :analytics
534
- analytics_api = Rest.new(@api_aoc.params.deep_merge({
535
- :base_url => @api_aoc.params[:base_url].gsub('/api/v1','')+'/analytics/v2',
536
- :auth => {:scope => AoC::SCOPE_FILES_ADMIN_USER}
572
+ analytics_api = Rest.new(aoc_api.params.deep_merge({
573
+ base_url: aoc_api.params[:base_url].gsub('/api/v1','')+'/analytics/v2',
574
+ auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
537
575
  }))
538
- command_analytics=self.options.get_next_command([ :application_events, :transfers ])
576
+ command_analytics=options.get_next_command([:application_events, :transfers])
539
577
  case command_analytics
540
578
  when :application_events
541
579
  event_type=command_analytics.to_s
542
- events=analytics_api.read("organizations/#{c_user_info['organization_id']}/#{event_type}")[:data][event_type]
543
- return {:type=>:object_list,:data=>events}
580
+ events=analytics_api.read("organizations/#{aoc_api.user_info['organization_id']}/#{event_type}")[:data][event_type]
581
+ return {type: :object_list,data: events}
544
582
  when :transfers
545
583
  event_type=command_analytics.to_s
546
- filter_resource=self.options.get_option(:name,:optional) || 'organizations'
547
- filter_id=self.options.get_option(:id,:optional) || case filter_resource
548
- when 'organizations'; c_user_info['organization_id']
549
- when 'users'; c_user_info['id']
550
- when 'nodes'; c_user_info['id']
584
+ filter_resource=options.get_option(:name,:optional) || 'organizations'
585
+ filter_id=options.get_option(:id,:optional) ||
586
+ case filter_resource
587
+ when 'organizations' then aoc_api.user_info['organization_id']
588
+ when 'users' then aoc_api.user_info['id']
589
+ when 'nodes' then aoc_api.user_info['id']
551
590
  else raise 'organizations or users for option --name'
552
591
  end
553
- #
554
- filter=self.options.get_option(:query,:optional) || {}
592
+ filter=options.get_option(:query,:optional) || {}
555
593
  raise 'query must be Hash' unless filter.is_a?(Hash)
556
594
  filter['limit']||=100
557
- if self.options.get_option(:once_only,:mandatory)
595
+ if options.get_option(:once_only,:mandatory)
558
596
  saved_date=[]
559
597
  startdate_persistency=PersistencyActionOnce.new(
560
598
  manager: @agents[:persistency],
561
599
  data: saved_date,
562
- ids: IdGenerator.from_list(['aoc_ana_date',self.options.get_option(:url,:mandatory),@workspace_name].push(filter_resource,filter_id)))
600
+ ids: IdGenerator.from_list(['aoc_ana_date',options.get_option(:url,:mandatory),@workspace_name].push(filter_resource,filter_id)))
563
601
  start_datetime=saved_date.first
564
602
  stop_datetime=Time.now.utc.strftime('%FT%T.%LZ')
565
603
  #Log.log().error("start: #{start_datetime}")
@@ -570,29 +608,27 @@ module Aspera
570
608
  end
571
609
  events=analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",option_url_query(filter))[:data][event_type]
572
610
  startdate_persistency.save unless startdate_persistency.nil?
573
- if !self.options.get_option(:notif_to,:optional).nil?
611
+ if !options.get_option(:notif_to,:optional).nil?
574
612
  events.each do |tr_event|
575
- self.config.send_email_template({ev: tr_event})
613
+ config.send_email_template({ev: tr_event})
576
614
  end
577
615
  end
578
- return {:type=>:object_list,:data=>events}
616
+ return {type: :object_list,data: events}
579
617
  end
580
618
  when :resource
581
- resource_type=self.options.get_next_argument('resource',[:self,:organization,:user,:group,:client,:contact,:dropbox,:node,:operation,:package,:saml_configuration, :workspace, :dropbox_membership,:short_link,:workspace_membership,:application,:client_registration_token,:client_access_key,:kms_profile])
582
- # get path on API
583
- resource_class_path=case resource_type
584
- when :self,:organization
585
- resource_type
586
- when :application
587
- 'admin/apps_new'
588
- when :dropbox
589
- resource_type.to_s+'es'
590
- when :client_registration_token,:client_access_key
591
- "admin/#{resource_type}s"
592
- when :kms_profile
593
- "integrations/#{resource_type}s"
594
- else
595
- resource_type.to_s+'s'
619
+ resource_type=options.get_next_argument('resource',
620
+ [:self,:organization,:user,:group,:client,:contact,:dropbox,:node,:operation,:package,:saml_configuration, :workspace, :dropbox_membership,:short_link,:workspace_membership,
621
+ :application,:client_registration_token,:client_access_key,:kms_profile])
622
+ # get path on API, resource type is singular, but api is plural
623
+ resource_class_path=
624
+ case resource_type
625
+ # special cases: singleton, in admin, with x
626
+ when :self,:organization then resource_type
627
+ when :client_registration_token,:client_access_key then "admin/#{resource_type}s"
628
+ when :application then 'admin/apps_new'
629
+ when :dropbox then resource_type.to_s+'es'
630
+ when :kms_profile then "integrations/#{resource_type}s"
631
+ else resource_type.to_s+'s'
596
632
  end
597
633
  # build list of supported operations
598
634
  singleton_object=[:self,:organization].include?(resource_type)
@@ -602,24 +638,10 @@ module Aspera
602
638
  supported_operations.push(:v4,:v3) if resource_type.eql?(:node)
603
639
  supported_operations.push(:set_pub_key) if resource_type.eql?(:client)
604
640
  supported_operations.push(:shared_folders,:shared_create) if [:node,:workspace].include?(resource_type)
605
- command=self.options.get_next_command(supported_operations)
641
+ command=options.get_next_command(supported_operations)
606
642
  # require identifier for non global commands
607
- if !singleton_object and !global_operations.include?(command)
608
- res_id=self.options.get_option(:id)
609
- res_name=self.options.get_option(:name)
610
- if res_id.nil? and res_name.nil? and resource_type.eql?(:node)
611
- set_workspace_info
612
- set_home_node_file
613
- res_id=@home_node_file[:node_info]['id']
614
- end
615
- if !res_name.nil?
616
- Log.log.warn('name overrides id') unless res_id.nil?
617
- matching=@api_aoc.read(resource_class_path,{:q=>res_name})[:data]
618
- raise CliError,'no resource match name' if matching.empty?
619
- raise CliError,"several resources match name (#{matching.join(',')})" unless matching.length.eql?(1)
620
- res_id=matching.first['id']
621
- end
622
- raise CliBadArgument,'provide either id or name' if res_id.nil?
643
+ if !singleton_object && !global_operations.include?(command)
644
+ res_id=get_resource_id_from_args(resource_class_path)
623
645
  resource_instance_path="#{resource_class_path}/#{res_id}"
624
646
  end
625
647
  resource_instance_path=resource_class_path if singleton_object
@@ -629,79 +651,82 @@ module Aspera
629
651
  id_result='token' if resource_class_path.eql?('admin/client_registration_tokens')
630
652
  # TODO: report inconsistency: creation url is !=, and does not return id.
631
653
  resource_class_path='admin/client_registration/token' if resource_class_path.eql?('admin/client_registration_tokens')
632
- list_or_one=self.options.get_next_argument('creation data (Hash)')
633
- return do_bulk_operation(list_or_one,'created',id_result)do|params|
654
+ list_or_one=options.get_next_argument('creation data (Hash)')
655
+ return do_bulk_operation(list_or_one,'created',id_result) do |params|
634
656
  raise 'expecting Hash' unless params.is_a?(Hash)
635
- @api_aoc.create(resource_class_path,params)[:data]
657
+ aoc_api.create(resource_class_path,params)[:data]
636
658
  end
637
659
  when :list
638
660
  default_fields=['id']
639
661
  default_query={}
640
662
  case resource_type
641
- when :application; default_query={:organization_apps=>true};default_fields.push('app_type','app_name','available','direct_authorizations_allowed','workspace_authorizations_allowed')
642
- when :client,:client_access_key,:dropbox,:group,:package,:saml_configuration,:workspace; default_fields.push('name')
643
- when :client_registration_token; default_fields.push('value','data.client_subject_scopes','created_at')
644
- when :contact; default_fields=['email','name','source_id','source_type']
645
- when :node; default_fields.push('name','host','access_key')
646
- when :operation; default_fields=nil
647
- when :short_link; default_fields.push('short_url','data.url_token_data.purpose')
648
- when :user; default_fields.push('name','email')
663
+ when :application then default_query={organization_apps: true};
664
+ default_fields.push('app_type','app_name','available','direct_authorizations_allowed','workspace_authorizations_allowed')
665
+ when :client,:client_access_key,:dropbox,:group,:package,:saml_configuration,:workspace then default_fields.push('name')
666
+ when :client_registration_token then default_fields.push('value','data.client_subject_scopes','created_at')
667
+ when :contact then default_fields=['email','name','source_id','source_type']
668
+ when :node then default_fields.push('name','host','access_key')
669
+ when :operation then default_fields=nil
670
+ when :short_link then default_fields.push('short_url','data.url_token_data.purpose')
671
+ when :user then default_fields.push('name','email')
649
672
  end
650
673
  item_list,total_count=read_with_paging(resource_class_path,option_url_query(default_query))
651
674
  count_msg="Items: #{item_list.length}/#{total_count}"
652
675
  count_msg=count_msg.bg_red unless item_list.length.eql?(total_count.to_i)
653
676
  self.format.display_status(count_msg)
654
- return {:type=>:object_list,:data=>item_list,:fields=>default_fields}
677
+ return {type: :object_list,data: item_list,fields: default_fields}
655
678
  when :show
656
- object=@api_aoc.read(resource_instance_path)[:data]
657
- fields=object.keys.select{|k|!k.eql?('certificate')}
658
- return { :type=>:single_object, :data =>object, :fields=>fields }
679
+ object=aoc_api.read(resource_instance_path)[:data]
680
+ fields=object.keys.reject{|k|k.eql?('certificate')}
681
+ return { type: :single_object, data: object, fields: fields }
659
682
  when :modify
660
- changes=self.options.get_next_argument('modified parameters (hash)')
661
- @api_aoc.update(resource_instance_path,changes)
683
+ changes=options.get_next_argument('modified parameters (hash)')
684
+ aoc_api.update(resource_instance_path,changes)
662
685
  return Main.result_status('modified')
663
686
  when :delete
664
- return do_bulk_operation(res_id,'deleted')do|one_id|
665
- @api_aoc.delete("#{resource_class_path}/#{one_id.to_s}")
687
+ return do_bulk_operation(res_id,'deleted') do |one_id|
688
+ aoc_api.delete("#{resource_class_path}/#{one_id}")
666
689
  {'id'=>one_id}
667
690
  end
668
691
  when :set_pub_key
669
692
  # special : reads private and generate public
670
- the_private_key=self.options.get_next_argument('private_key')
693
+ the_private_key=options.get_next_argument('private_key')
671
694
  the_public_key=OpenSSL::PKey::RSA.new(the_private_key).public_key.to_s
672
- @api_aoc.update(resource_instance_path,{:jwt_grant_enabled=>true, :public_key=>the_public_key})
695
+ aoc_api.update(resource_instance_path,{jwt_grant_enabled: true, public_key: the_public_key})
673
696
  return Main.result_success
674
697
  when :v3,:v4
675
- res_data=@api_aoc.read(resource_instance_path)[:data]
676
- api_node=@api_aoc.get_node_api(res_data)
698
+ res_data=aoc_api.read(resource_instance_path)[:data]
699
+ api_node=aoc_api.get_node_api(res_data)
677
700
  return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action if command.eql?(:v3)
678
- ak_data=api_node.call({:operation=>'GET',:subpath=>"access_keys/#{res_data['access_key']}",:headers=>{'Accept'=>'application/json'}})[:data]
679
- command_repo=self.options.get_next_command(NODE4_COMMANDS)
701
+ ak_data=api_node.call({operation: 'GET',subpath: "access_keys/#{res_data['access_key']}",headers: {'Accept'=>'application/json'}})[:data]
702
+ command_repo=options.get_next_command(NODE4_COMMANDS)
680
703
  return execute_node_gen4_command(command_repo,{node_info: res_data, file_id: ak_data['root_file_id']})
681
704
  when :shared_folders
682
- read_params = case resource_type
683
- when :workspace;{'access_id'=>"ASPERA_ACCESS_KEY_ADMIN_WS_#{res_id}",'access_type'=>'user'}
684
- when :node;{'include'=>['[]','access_level','permission_count'],'created_by_id'=>'ASPERA_ACCESS_KEY_ADMIN'}
705
+ read_params=
706
+ case resource_type
707
+ when :workspace then{'access_id'=>"#{ID_AK_ADMIN}_WS_#{res_id}",'access_type'=>'user'}
708
+ when :node then{'include'=>['[]','access_level','permission_count'],'created_by_id'=>ID_AK_ADMIN}
685
709
  else raise 'error'
686
710
  end
687
- res_data=@api_aoc.read("#{resource_class_path}/#{res_id}/permissions",read_params)[:data]
688
- fields=case resource_type
689
- when :node;['id','file_id','file.path','access_type']
690
- when :workspace;['id','node_id','file_id','node_name','file.path','tags.aspera.files.workspace.share_as']
711
+ res_data=aoc_api.read("#{resource_instance_path}/permissions",read_params)[:data]
712
+ fields=
713
+ case resource_type
714
+ when :node then['id','file_id','file.path','access_type']
715
+ when :workspace then['id','node_id','file_id','node_name','file.path','tags.aspera.files.workspace.share_as']
691
716
  else raise "unexpected resource type #{resource_type}"
692
717
  end
693
- return { :type=>:object_list, :data =>res_data , :fields=>fields}
718
+ return { type: :object_list, data: res_data, fields: fields}
694
719
  when :shared_create
695
- # TODO
696
- folder_path=self.options.get_next_argument('folder path in node')
697
- user_create_data=self.options.get_next_argument('creation data (Hash)')
698
- res_data=@api_aoc.read(resource_instance_path)[:data]
699
- node_file = @api_aoc.resolve_node_file({node_info: res_data, file_id: ak_data['root_file_id']},folder_path)
720
+ # TODO: finish implementation
721
+ folder_path=options.get_next_argument('folder path in node')
722
+ user_create_data=options.get_next_argument('creation data (Hash)')
723
+ res_data=aoc_api.read(resource_instance_path)[:data]
724
+ node_file = aoc_api.resolve_node_file({node_info: res_data, file_id: ak_data['root_file_id']},folder_path)
700
725
 
701
- #node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
726
+ #node_api=aoc_api.get_node_api(node_file[:node_info])
702
727
  #file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
703
728
 
704
- access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
729
+ access_id="#{ID_AK_ADMIN}_WS_#{@workspace_id}"
705
730
  create_data={
706
731
  'file_id' =>node_file[:file_id],
707
732
  'access_type' =>'user',
@@ -711,10 +736,10 @@ module Aspera
711
736
  'id' =>@workspace_id,
712
737
  'workspace_name' =>@workspace_name,
713
738
  'share_as' =>File.basename(folder_path),
714
- 'user_name' =>c_user_info['name'],
715
- 'shared_by_user_id'=>c_user_info['id'],
716
- 'shared_by_name' =>c_user_info['name'],
717
- 'shared_by_email' =>c_user_info['email'],
739
+ 'user_name' =>aoc_api.user_info['name'],
740
+ 'shared_by_user_id'=>aoc_api.user_info['id'],
741
+ 'shared_by_name' =>aoc_api.user_info['name'],
742
+ 'shared_by_email' =>aoc_api.user_info['email'],
718
743
  'shared_with_name' =>access_id,
719
744
  'access_key' =>node_file[:node_info]['access_key'],
720
745
  'node' =>node_file[:node_info]['name']}
@@ -725,128 +750,136 @@ module Aspera
725
750
  else raise 'unknown command'
726
751
  end
727
752
  when :usage_reports
728
- return {:type=>:object_list,:data=>@api_aoc.read('usage_reports',{:workspace_id=>@workspace_id})[:data]}
753
+ return {type: :object_list,data: aoc_api.read('usage_reports',{workspace_id: @workspace_id})[:data]}
729
754
  end
730
755
  end
731
756
 
732
757
  # must be public
733
- ACTIONS=[ :reminder, :bearer_token, :organization, :tier_restrictions, :user, :workspace, :packages, :files, :gateway, :admin, :automation, :servers]
758
+ ACTIONS=[:reminder, :servers, :bearer_token, :organization, :tier_restrictions, :user, :packages, :files, :admin, :automation, :gateway].freeze
734
759
 
735
760
  def execute_action
736
- command=self.options.get_next_command(ACTIONS)
737
- get_api unless [:reminder,:servers].include?(command)
761
+ command=options.get_next_command(ACTIONS)
738
762
  case command
739
763
  when :reminder
740
764
  # send an email reminder with list of orgs
741
765
  user_email=options.get_option(:username,:mandatory)
742
766
  Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").create('organization_reminders',{email: user_email})[:data]
743
767
  return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
768
+ when :servers
769
+ return {type: :object_list,data: Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
744
770
  when :bearer_token
745
- return {:type=>:text,:data=>@api_aoc.oauth_token}
771
+ return {type: :text,data: aoc_api.oauth_token}
746
772
  when :organization
747
- return { :type=>:single_object, :data =>@api_aoc.read('organization')[:data] }
773
+ return { type: :single_object, data: aoc_api.read('organization')[:data] }
748
774
  when :tier_restrictions
749
- return { :type=>:single_object, :data =>@api_aoc.read('tier_restrictions')[:data] }
775
+ return { type: :single_object, data: aoc_api.read('tier_restrictions')[:data] }
750
776
  when :user
751
- command=self.options.get_next_command([ :workspaces,:info,:shared_inboxes ])
752
- case command
777
+ case options.get_next_command([:workspaces,:profile])
778
+ # when :settings
779
+ # return {type: :object_list,data: aoc_api.read('client_settings/')[:data]}
753
780
  when :workspaces
754
- return {:type=>:object_list,:data=>@api_aoc.read('workspaces')[:data],:fields=>['id','name']}
755
- # when :settings
756
- # return {:type=>:object_list,:data=>@api_aoc.read('client_settings/')[:data]}
757
- when :shared_inboxes
758
- query=option_url_query(nil)
759
- if query.nil?
781
+ case options.get_next_command([:list,:current])
782
+ when :list
783
+ return {type: :object_list,data: aoc_api.read('workspaces')[:data],fields: ['id','name']}
784
+ when :current
760
785
  set_workspace_info
761
- query={'embed[]'=>'dropbox','workspace_id'=>@workspace_id,'aggregate_permissions_by_dropbox'=>true,'sort'=>'dropbox_name'}
786
+ return { type: :single_object, data: @workspace_data }
762
787
  end
763
- return {:type=>:object_list,:data=>@api_aoc.read('dropbox_memberships',query)[:data],:fields=>['dropbox_id','dropbox.name']}
764
- when :info
765
- command=self.options.get_next_command([ :show,:modify ])
766
- case command
788
+ when :profile
789
+ case options.get_next_command([:show,:modify])
767
790
  when :show
768
- return { :type=>:single_object, :data =>c_user_info }
791
+ return { type: :single_object, data: aoc_api.user_info }
769
792
  when :modify
770
- @api_aoc.update("users/#{c_user_info['id']}",self.options.get_next_argument('modified parameters (hash)'))
793
+ aoc_api.update("users/#{aoc_api.user_info['id']}",options.get_next_argument('modified parameters (hash)'))
771
794
  return Main.result_status('modified')
772
795
  end
773
796
  end
774
- when :workspace # show current workspace parameters
775
- set_workspace_info
776
- return { :type=>:single_object, :data =>@workspace_data }
777
797
  when :packages
778
798
  set_workspace_info if @url_token_data.nil?
779
- command_pkg=self.options.get_next_command([ :send, :recv, :list, :show, :delete ])
780
- case command_pkg
799
+ case options.get_next_command([:shared_inboxes, :send, :recv, :list, :show, :delete])
800
+ when :shared_inboxes
801
+ case options.get_next_command([:list, :show])
802
+ when :list
803
+ query=option_url_query(nil)
804
+ if query.nil?
805
+ query={'embed[]'=>'dropbox','workspace_id'=>@workspace_id,'aggregate_permissions_by_dropbox'=>true,'sort'=>'dropbox_name'}
806
+ end
807
+ return {type: :object_list,data: aoc_api.read('dropbox_memberships',query)[:data],fields: ['dropbox_id','dropbox.name']}
808
+ when :show
809
+ return {type: :single_object,data: aoc_api.read(get_resource_path_from_args('dropboxes'),query)[:data]}
810
+ end
781
811
  when :send
782
- package_creation=self.options.get_option(:value,:mandatory)
783
- raise CliBadArgument,'value must be hash, refer to doc' unless package_creation.is_a?(Hash)
812
+ package_data=options.get_option(:value,:mandatory)
813
+ raise CliBadArgument,'value must be hash, refer to doc' unless package_data.is_a?(Hash)
784
814
 
785
815
  if !@url_token_data.nil?
786
816
  assert_public_link_types(['send_package_to_user','send_package_to_dropbox'])
787
817
  box_type=@url_token_data['purpose'].split('_').last
788
- package_creation['recipients']=[{'id'=>@url_token_data['data']["#{box_type}_id"],'type'=>box_type}]
818
+ package_data['recipients']=[{'id'=>@url_token_data['data']["#{box_type}_id"],'type'=>box_type}]
789
819
  @workspace_id=@url_token_data['data']['workspace_id']
790
820
  end
791
821
 
792
- package_creation['workspace_id']=@workspace_id
822
+ package_data['workspace_id']=@workspace_id
793
823
 
794
824
  # list of files to include in package, optional
795
- #package_creation['file_names']=self.transfer.ts_source_paths.map{|i|File.basename(i['source'])}
825
+ #package_data['file_names']=self.transfer.ts_source_paths.map{|i|File.basename(i['source'])}
796
826
 
797
827
  # lookup users
798
- resolve_package_recipients(package_creation,'recipients')
799
- resolve_package_recipients(package_creation,'bcc_recipients')
828
+ resolve_package_recipients(package_data,'recipients')
829
+ resolve_package_recipients(package_data,'bcc_recipients')
830
+ normalize_metadata(package_data)
800
831
 
801
832
  # create a new package container
802
- package_info=@api_aoc.create('packages',package_creation)[:data]
833
+ package_info=aoc_api.create('packages',package_data)[:data]
803
834
 
804
835
  # get node information for the node on which package must be created
805
- node_info=@api_aoc.read("nodes/#{package_info['node_id']}")[:data]
836
+ node_info=aoc_api.read("nodes/#{package_info['node_id']}")[:data]
806
837
 
807
- # tell Aspera what to expect in package: 1 transfer (can also be done after transfer)
808
- @api_aoc.update("packages/#{package_info['id']}",{'sent'=>true,'transfers_expected'=>1})[:data]
838
+ # tell AoC what to expect in package: 1 transfer (can also be done after transfer)
839
+ # TODO: if multisession was used we should probably tell
840
+ # also, currently no "multi-source" , i.e. only from client-side files, unless "node" agent is used
841
+ aoc_api.update("packages/#{package_info['id']}",{'sent'=>true,'transfers_expected'=>1})[:data]
809
842
 
810
- # execute transfer
843
+ # get destination: package folder
811
844
  node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
812
- # raise exception if at least one error
813
- Main.result_transfer(transfer_start(AoC::PACKAGES_APP,'send',node_file,AoC.package_tags(package_info,'upload')))
845
+ # execute transfer, raise exception if at least one error
846
+ Main.result_transfer(transfer_start(AoC::PACKAGES_APP,Fasp::TransferSpec::DIRECTION_SEND,node_file,AoC.package_tags(package_info,'upload')))
814
847
  # return all info on package
815
- return { :type=>:single_object, :data =>package_info}
848
+ return { type: :single_object, data: package_info}
816
849
  when :recv
817
850
  if !@url_token_data.nil?
818
851
  assert_public_link_types(['view_received_package'])
819
- self.options.set_option(:id,@url_token_data['data']['package_id'])
852
+ options.set_option(:id,@url_token_data['data']['package_id'])
820
853
  end
821
854
  # scalar here
822
- ids_to_download=self.options.get_option(:id,:mandatory)
855
+ ids_to_download=instance_identifier()
823
856
  skip_ids_data=[]
824
857
  skip_ids_persistency=nil
825
- if self.options.get_option(:once_only,:mandatory)
858
+ if options.get_option(:once_only,:mandatory)
826
859
  skip_ids_persistency=PersistencyActionOnce.new(
827
860
  manager: @agents[:persistency],
828
861
  data: skip_ids_data,
829
- id: IdGenerator.from_list(['aoc_recv',self.options.get_option(:url,:mandatory),@workspace_id].push(*@persist_ids)))
862
+ id: IdGenerator.from_list(['aoc_recv',options.get_option(:url,:mandatory),@workspace_id].push(*@persist_ids)))
830
863
  end
831
864
  if ids_to_download.eql?(VAL_ALL)
832
865
  # get list of packages in inbox
833
- package_info=@api_aoc.read('packages',{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
866
+ package_info=aoc_api.read('packages',{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
834
867
  # remove from list the ones already downloaded
835
868
  ids_to_download=package_info.map{|e|e['id']}
836
869
  # array here
837
- ids_to_download.select!{|id|!skip_ids_data.include?(id)}
870
+ ids_to_download.reject!{|id|skip_ids_data.include?(id)}
838
871
  end # ALL
839
872
  # list here
840
873
  ids_to_download = [ids_to_download] unless ids_to_download.is_a?(Array)
841
874
  result_transfer=[]
842
875
  self.format.display_status("found #{ids_to_download.length} package(s).")
843
876
  ids_to_download.each do |package_id|
844
- package_info=@api_aoc.read("packages/#{package_id}")[:data]
845
- node_info=@api_aoc.read("nodes/#{package_info['node_id']}")[:data]
877
+ package_info=aoc_api.read("packages/#{package_id}")[:data]
878
+ node_info=aoc_api.read("nodes/#{package_info['node_id']}")[:data]
846
879
  self.format.display_status("downloading package: #{package_info['name']}")
847
880
  add_ts={'paths'=>[{'source'=>'.'}]}
848
881
  node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
849
- statuses=transfer_start(AoC::PACKAGES_APP,'receive',node_file,AoC.package_tags(package_info,'download').merge(add_ts))
882
+ statuses=transfer_start(AoC::PACKAGES_APP,Fasp::TransferSpec::DIRECTION_RECEIVE,node_file,AoC.package_tags(package_info,'download').merge(add_ts))
850
883
  result_transfer.push({'package'=>package_id,Main::STATUS_FIELD=>statuses})
851
884
  # update skip list only if all transfer sessions completed
852
885
  if TransferAgent.session_status(statuses).eql?(:success)
@@ -856,51 +889,55 @@ module Aspera
856
889
  end
857
890
  return Main.result_transfer_multiple(result_transfer)
858
891
  when :show
859
- package_id=self.options.get_next_argument('package ID')
860
- package_info=@api_aoc.read("packages/#{package_id}")[:data]
861
- return { :type=>:single_object, :data =>package_info }
892
+ package_id=options.get_next_argument('package ID')
893
+ package_info=aoc_api.read("packages/#{package_id}")[:data]
894
+ return { type: :single_object, data: package_info }
862
895
  when :list
863
896
  query=option_url_query({'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true})
897
+ if query.has_key?('dropbox_name')
898
+ # convenience: specify name instead of id
899
+ raise 'not both dropbox_name and dropbox_id' if query.has_key?('dropbox_id')
900
+ query['dropbox_id']=aoc_api.lookup_entity_by_name('dropboxes',query['dropbox_name'])['id']
901
+ query.delete('dropbox_name')
902
+ end
864
903
  raise 'option must be Hash' unless query.is_a?(Hash)
865
904
  query['workspace_id']||=@workspace_id
866
- packages=@api_aoc.read('packages',query)[:data]
867
- return {:type=>:object_list,:data=>packages,:fields=>['id','name','bytes_transferred']}
905
+ packages=aoc_api.read('packages',query)[:data]
906
+ return {type: :object_list,data: packages,fields: ['id','name','bytes_transferred']}
868
907
  when :delete
869
- list_or_one=self.options.get_option(:id,:mandatory)
870
- return do_bulk_operation(list_or_one,'deleted')do|id|
871
- raise 'expecting String identifier' unless id.is_a?(String) or id.is_a?(Integer)
872
- @api_aoc.delete("packages/#{id}")[:data]
908
+ list_or_one=instance_identifier()
909
+ return do_bulk_operation(list_or_one,'deleted') do |id|
910
+ raise 'expecting String identifier' unless id.is_a?(String) || id.is_a?(Integer)
911
+ aoc_api.delete("packages/#{id}")[:data]
873
912
  end
874
913
  end
875
914
  when :files
876
915
  # get workspace related information
877
916
  set_workspace_info
878
917
  set_home_node_file
879
- command_repo=self.options.get_next_command(NODE4_COMMANDS.clone.concat([:short_link]))
918
+ command_repo=options.get_next_command([NODE4_COMMANDS,:short_link].flatten)
880
919
  case command_repo
881
- when *NODE4_COMMANDS; return execute_node_gen4_command(command_repo,@home_node_file)
920
+ when *NODE4_COMMANDS then return execute_node_gen4_command(command_repo,@home_node_file)
882
921
  when :short_link
883
- folder_dest=self.options.get_option(:to_folder,:optional)
884
- value_option=self.options.get_option(:value,:optional)
922
+ folder_dest=options.get_option(:to_folder,:optional)
923
+ value_option=options.get_option(:value,:optional)
885
924
  case value_option
886
- when 'public'
887
- value_option={'purpose'=>'token_auth_redirection'}
888
- when 'private'
889
- value_option={'purpose'=>'shared_folder_auth_link'}
890
- when NilClass,Hash
925
+ when 'public' then value_option={'purpose'=>'token_auth_redirection'}
926
+ when 'private' then value_option={'purpose'=>'shared_folder_auth_link'}
927
+ when NilClass,Hash then nil # keep value
891
928
  else raise 'value must be either: public, private, Hash or nil'
892
929
  end
893
930
  create_params=nil
894
931
  node_file=nil
895
932
  if !folder_dest.nil?
896
- node_file = @api_aoc.resolve_node_file(@home_node_file,folder_dest)
933
+ node_file = aoc_api.resolve_node_file(@home_node_file,folder_dest)
897
934
  create_params={
898
935
  file_id: node_file[:file_id],
899
936
  node_id: node_file[:node_info]['id'],
900
937
  workspace_id: @workspace_id
901
938
  }
902
939
  end
903
- if !value_option.nil? and !create_params.nil?
940
+ if !value_option.nil? && !create_params.nil?
904
941
  case value_option['purpose']
905
942
  when 'shared_folder_auth_link'
906
943
  value_option['data']=create_params
@@ -918,11 +955,11 @@ module Aspera
918
955
  else
919
956
  raise 'purpose must be one of: token_auth_redirection or shared_folder_auth_link'
920
957
  end
921
- self.options.set_option(:value,value_option)
958
+ options.set_option(:value,value_option)
922
959
  end
923
- result=self.entity_action(@api_aoc,'short_links',nil,:id,'self')
924
- if result[:data].is_a?(Hash) and result[:data].has_key?('created_at') and result[:data]['resource_type'].eql?('UrlToken')
925
- node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
960
+ result=entity_action(@api_aoc,'short_links',id_default: 'self')
961
+ if result[:data].is_a?(Hash) && result[:data].has_key?('created_at') && result[:data]['resource_type'].eql?('UrlToken')
962
+ node_api=aoc_api.get_node_api(node_file[:node_info])
926
963
  # TODO: access level as arg
927
964
  access_levels=Aspera::Node::ACCESS_LEVELS #['delete','list','mkdir','preview','read','rename','write']
928
965
  perm_data={
@@ -935,8 +972,8 @@ module Aspera
935
972
  'workspace_id' =>@workspace_id,
936
973
  'workspace_name' =>@workspace_name,
937
974
  'folder_name' =>'my folder',
938
- 'created_by_name' =>c_user_info['name'],
939
- 'created_by_email'=>c_user_info['email'],
975
+ 'created_by_name' =>aoc_api.user_info['name'],
976
+ 'created_by_email'=>aoc_api.user_info['email'],
940
977
  'access_key' =>node_file[:node_info]['access_key'],
941
978
  'node' =>node_file[:node_info]['host']
942
979
  }
@@ -950,51 +987,49 @@ module Aspera
950
987
  when :automation
951
988
  Log.log.warn('BETA: work under progress')
952
989
  # automation api is not in the same place
953
- automation_rest_params=@api_aoc.params.clone
990
+ automation_rest_params=aoc_api.params.clone
954
991
  automation_rest_params[:base_url].gsub!('/api/','/automation/')
955
992
  automation_api=Rest.new(automation_rest_params)
956
- command_automation=self.options.get_next_command([ :workflows, :instances ])
993
+ command_automation=options.get_next_command([:workflows, :instances])
957
994
  case command_automation
958
995
  when :instances
959
- return self.entity_action(@api_aoc,'workflow_instances',nil,:id,nil)
996
+ return entity_action(@api_aoc,'workflow_instances')
960
997
  when :workflows
961
- wF_COMMANDS=Plugin::ALL_OPS.clone.push(:action,:launch)
962
- wf_command=self.options.get_next_command(wF_COMMANDS)
998
+ wf_command=options.get_next_command([Plugin::ALL_OPS,:action,:launch].flatten)
963
999
  case wf_command
964
1000
  when *Plugin::ALL_OPS
965
- return self.entity_command(wf_command,automation_api,'workflows',nil,:id)
1001
+ return entity_command(wf_command,automation_api,'workflows',id_default: :id)
966
1002
  when :launch
967
- wf_id=self.options.get_option(:id,:mandatory)
1003
+ wf_id=instance_identifier()
968
1004
  data=automation_api.create("workflows/#{wf_id}/launch",{})[:data]
969
- return {:type=>:single_object,:data=>data}
1005
+ return {type: :single_object,data: data}
970
1006
  when :action
971
- wf_command=self.options.get_next_command([:list,:create,:show])
972
- wf_id=self.options.get_option(:id,:mandatory)
1007
+ #TODO: not complete
1008
+ wf_id=instance_identifier()
1009
+ wf_action_cmd=options.get_next_command([:list,:create,:show])
1010
+ Log.log.warn("Not implemented: #{wf_action_cmd}")
973
1011
  step=automation_api.create('steps',{'workflow_id'=>wf_id})[:data]
974
1012
  automation_api.update("workflows/#{wf_id}",{'step_order'=>[step['id']]})
975
1013
  action=automation_api.create('actions',{'step_id'=>step['id'],'type'=>'manual'})[:data]
976
1014
  automation_api.update("steps/#{step['id']}",{'action_order'=>[action['id']]})
977
1015
  wf=automation_api.read("workflows/#{wf_id}")[:data]
978
- return {:type=>:single_object,:data=>wf}
1016
+ return {type: :single_object,data: wf}
979
1017
  end
980
1018
  end
1019
+ when :admin
1020
+ return execute_admin_action
981
1021
  when :gateway
982
1022
  set_workspace_info
983
1023
  require 'aspera/faspex_gw'
984
1024
  FaspexGW.new(@api_aoc,@workspace_id).start_server
985
- when :admin
986
- return execute_admin_action
987
- when :servers
988
- return {:type=>:object_list,:data=>Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
989
1025
  else
990
1026
  raise "internal error: #{command}"
991
1027
  end # action
992
- raise RuntimeError, 'internal error: command shall return'
1028
+ raise 'internal error: command shall return'
993
1029
  end
994
1030
 
995
- private :c_user_info,:aoc_params,:set_workspace_info,:set_home_node_file,:do_bulk_operation,:resolve_package_recipients,:option_url_query,:assert_public_link_types,:execute_admin_action
996
- private_constant :VAL_ALL,:NODE4_COMMANDS
997
-
1031
+ private :aoc_params,:set_workspace_info,:set_home_node_file,:do_bulk_operation,:resolve_package_recipients,:option_url_query,:assert_public_link_types,:execute_admin_action
1032
+ private_constant :VAL_ALL,:NODE4_COMMANDS, :ID_AK_ADMIN
998
1033
  end # AoC
999
1034
  end # Plugins
1000
1035
  end # Cli