aspera-cli 4.6.0 → 4.7.0

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