aspera-cli 4.0.0.pre3 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +695 -205
  3. data/bin/dascli +13 -0
  4. data/docs/README.erb.md +615 -157
  5. data/docs/test_env.conf +23 -5
  6. data/docs/transfer_spec.html +1 -1
  7. data/examples/aoc.rb +14 -3
  8. data/examples/faspex4.rb +78 -0
  9. data/lib/aspera/aoc.rb +87 -108
  10. data/lib/aspera/cli/formater.rb +2 -0
  11. data/lib/aspera/cli/main.rb +46 -34
  12. data/lib/aspera/cli/plugin.rb +9 -4
  13. data/lib/aspera/cli/plugins/alee.rb +1 -1
  14. data/lib/aspera/cli/plugins/aoc.rb +207 -182
  15. data/lib/aspera/cli/plugins/ats.rb +2 -2
  16. data/lib/aspera/cli/plugins/config.rb +173 -117
  17. data/lib/aspera/cli/plugins/console.rb +2 -2
  18. data/lib/aspera/cli/plugins/faspex.rb +51 -36
  19. data/lib/aspera/cli/plugins/faspex5.rb +82 -41
  20. data/lib/aspera/cli/plugins/node.rb +3 -3
  21. data/lib/aspera/cli/plugins/preview.rb +35 -25
  22. data/lib/aspera/cli/plugins/server.rb +23 -8
  23. data/lib/aspera/cli/transfer_agent.rb +7 -6
  24. data/lib/aspera/cli/version.rb +1 -1
  25. data/lib/aspera/cos_node.rb +33 -28
  26. data/lib/aspera/environment.rb +2 -2
  27. data/lib/aspera/fasp/connect.rb +28 -21
  28. data/lib/aspera/fasp/http_gw.rb +140 -28
  29. data/lib/aspera/fasp/installation.rb +101 -53
  30. data/lib/aspera/fasp/local.rb +88 -45
  31. data/lib/aspera/fasp/manager.rb +15 -0
  32. data/lib/aspera/fasp/node.rb +4 -4
  33. data/lib/aspera/fasp/parameters.rb +6 -18
  34. data/lib/aspera/fasp/resume_policy.rb +13 -12
  35. data/lib/aspera/log.rb +1 -1
  36. data/lib/aspera/node.rb +61 -1
  37. data/lib/aspera/oauth.rb +49 -46
  38. data/lib/aspera/persistency_folder.rb +9 -4
  39. data/lib/aspera/preview/file_types.rb +53 -21
  40. data/lib/aspera/preview/generator.rb +3 -3
  41. data/lib/aspera/rest.rb +29 -18
  42. data/lib/aspera/secrets.rb +20 -0
  43. data/lib/aspera/temp_file_manager.rb +19 -0
  44. data/lib/aspera/web_auth.rb +105 -0
  45. metadata +42 -22
@@ -151,6 +151,8 @@ module Aspera
151
151
  else
152
152
  if user_asked_fields_list_str.start_with?('+')
153
153
  result_default_fields(results,table_rows_hash_val).push(*user_asked_fields_list_str.gsub(/^\+/,'').split(','))
154
+ elsif user_asked_fields_list_str.start_with?('-')
155
+ result_default_fields(results,table_rows_hash_val).select{|i| ! user_asked_fields_list_str.gsub(/^\-/,'').split(',').include?(i)}
154
156
  else
155
157
  user_asked_fields_list_str.split(',')
156
158
  end
@@ -10,6 +10,7 @@ require 'aspera/persistency_folder'
10
10
  require 'aspera/log'
11
11
  require 'aspera/rest'
12
12
  require 'aspera/nagios'
13
+ require 'aspera/secrets'
13
14
 
14
15
  module Aspera
15
16
  module Cli
@@ -53,13 +54,22 @@ module Aspera
53
54
  @help_url='http://www.rubydoc.info/gems/'+GEM_NAME
54
55
  @gem_url='https://rubygems.org/gems/'+GEM_NAME
55
56
  # give command line arguments to option manager (no parsing)
56
- @plugin_env[:options]=@opt_mgr=Manager.new(self.program_name,argv,app_banner())
57
+ app_main_folder=ENV[conf_dir_env_var]
58
+ # if env var undefined or empty
59
+ if app_main_folder.nil? or app_main_folder.empty?
60
+ user_home_folder=Dir.home
61
+ raise CliError,"Home folder does not exist: #{user_home_folder}. Check your user environment or use #{conf_dir_env_var}." unless Dir.exist?(user_home_folder)
62
+ app_main_folder=File.join(user_home_folder,Plugins::Config::ASPERA_HOME_FOLDER_NAME,PROGRAM_NAME)
63
+ end
64
+ @plugin_env[:options]=@opt_mgr=Manager.new(PROGRAM_NAME,argv,app_banner())
57
65
  @plugin_env[:formater]=Formater.new(@plugin_env[:options])
58
- Rest.user_agent=self.program_name
66
+ Rest.user_agent=PROGRAM_NAME
59
67
  # must override help methods before parser called (in other constructors)
60
68
  init_global_options()
69
+ # secret manager
70
+ @plugin_env[:secret]=Aspera::Secrets.new
61
71
  # the Config plugin adds the @preset parser
62
- @plugin_env[:config]=Plugins::Config.new(@plugin_env,self.program_name,@help_url,Aspera::Cli::VERSION)
72
+ @plugin_env[:config]=Plugins::Config.new(@plugin_env,PROGRAM_NAME,@help_url,Aspera::Cli::VERSION,app_main_folder)
63
73
  # the TransferAgent plugin may use the @preset parser
64
74
  @plugin_env[:transfer]=TransferAgent.new(@plugin_env)
65
75
  Log.log.debug('created plugin env'.red)
@@ -73,21 +83,21 @@ module Aspera
73
83
  end
74
84
 
75
85
  def app_banner
76
- banner = "NAME\n\t#{self.program_name} -- a command line tool for Aspera Applications (v#{Aspera::Cli::VERSION})\n\n"
86
+ banner = "NAME\n\t#{PROGRAM_NAME} -- a command line tool for Aspera Applications (v#{Aspera::Cli::VERSION})\n\n"
77
87
  banner << "SYNOPSIS\n"
78
- banner << "\t#{self.program_name} COMMANDS [OPTIONS] [ARGS]\n"
79
- banner << "\n"
80
- banner << "DESCRIPTION\n"
88
+ banner << "\t#{PROGRAM_NAME} COMMANDS [OPTIONS] [ARGS]\n"
89
+ banner << "\nDESCRIPTION\n"
81
90
  banner << "\tUse Aspera application to perform operations on command line.\n"
82
91
  banner << "\tDocumentation and examples: #{@gem_url}\n"
83
- banner << "\texecute: #{self.program_name} conf doc\n"
92
+ banner << "\texecute: #{PROGRAM_NAME} conf doc\n"
84
93
  banner << "\tor visit: #{@help_url}\n"
85
- banner << "\n"
86
- banner << "COMMANDS\n"
87
- banner << "\tTo list first level commands, execute: #{self.program_name}\n"
94
+ banner << "\nENVIRONMENT VARIABLES\n"
95
+ banner << "\t#{conf_dir_env_var} config folder, default: $HOME/#{Plugins::Config::ASPERA_HOME_FOLDER_NAME}/#{PROGRAM_NAME}\n"
96
+ banner << "\t#any option can be set as an environment variable, refer to the manual\n"
97
+ banner << "\nCOMMANDS\n"
98
+ banner << "\tTo list first level commands, execute: #{PROGRAM_NAME}\n"
88
99
  banner << "\tNote that commands can be written shortened (provided it is unique).\n"
89
- banner << "\n"
90
- banner << "OPTIONS\n"
100
+ banner << "\nOPTIONS\n"
91
101
  banner << "\tOptions begin with a '-' (minus), and value is provided on command line.\n"
92
102
  banner << "\tSpecial values are supported beginning with special prefix, like: #{ExtendedValue.instance.modifiers.map{|m|"@#{m}:"}.join(' ')}.\n"
93
103
  banner << "\tDates format is 'DD-MM-YY HH:MM:SS', or 'now' or '-<num>h'\n\n"
@@ -167,7 +177,7 @@ module Aspera
167
177
  # override main option parser with a brand new, to avoid having global options
168
178
  plugin_env=@plugin_env.clone
169
179
  plugin_env[:man_only]=true
170
- plugin_env[:options]=Manager.new(self.program_name,[],'')
180
+ plugin_env[:options]=Manager.new(PROGRAM_NAME,[],'')
171
181
  get_plugin_instance_with_options(plugin_name_sym,plugin_env)
172
182
  # display generated help for plugin options
173
183
  @plugin_env[:formater].display_message(:error,plugin_env[:options].parser.to_s)
@@ -178,10 +188,14 @@ module Aspera
178
188
 
179
189
  protected
180
190
 
191
+ def conf_dir_env_var
192
+ return "#{PROGRAM_NAME}_home".upcase
193
+ end
194
+
181
195
  # early debug for parser
182
196
  # Note: does not accept shortcuts
183
197
  def early_debug_setup(argv)
184
- Log.instance.program_name=self.program_name
198
+ Log.instance.program_name=PROGRAM_NAME
185
199
  argv.each do |arg|
186
200
  case arg
187
201
  when '--'
@@ -205,10 +219,6 @@ module Aspera
205
219
  return Main.result_nothing
206
220
  end
207
221
 
208
- def options;@opt_mgr;end
209
-
210
- def program_name;PROGRAM_NAME;end
211
-
212
222
  # this is the main function called by initial script just after constructor
213
223
  def process_command_line
214
224
  Log.log.debug('process_command_line')
@@ -222,16 +232,7 @@ module Aspera
222
232
  # load global default options and process
223
233
  @plugin_env[:config].add_plugin_default_preset(Plugins::Config::CONF_GLOBAL_SYM)
224
234
  @opt_mgr.parse_options!
225
- # dual execution locking
226
- lock_port=@opt_mgr.get_option(:lock_port,:optional)
227
- if !lock_port.nil?
228
- begin
229
- # no need to close later, will be freed on process exit. must save in member else it is garbage collected
230
- @tcp_server=TCPServer.new('127.0.0.1',lock_port.to_i)
231
- rescue => e
232
- raise CliError,"Another instance is already running (lock port=#{lock_port})."
233
- end
234
- end
235
+ @plugin_env[:config].periodic_check_newer_gem_version
235
236
  if @option_show_config and @opt_mgr.command_or_arg_empty?
236
237
  command_sym=Plugins::Config::CONF_PLUGIN_SYM
237
238
  else
@@ -255,6 +256,17 @@ module Aspera
255
256
  @plugin_env[:formater].display_results({:type=>:single_object,:data=>@opt_mgr.declared_options(false)})
256
257
  Process.exit(0)
257
258
  end
259
+ # locking for single execution (only after "per plugin" option, in case lock port is there)
260
+ lock_port=@opt_mgr.get_option(:lock_port,:optional)
261
+ if !lock_port.nil?
262
+ begin
263
+ # no need to close later, will be freed on process exit. must save in member else it is garbage collected
264
+ Log.log.debug("Opening lock port #{lock_port.to_i}")
265
+ @tcp_server=TCPServer.new('127.0.0.1',lock_port.to_i)
266
+ rescue => e
267
+ raise CliError,"Another instance is already running (#{e.message})."
268
+ end
269
+ end
258
270
  # execute and display
259
271
  @plugin_env[:formater].display_results(command_plugin.execute_action)
260
272
  # finish
@@ -262,11 +274,11 @@ module Aspera
262
274
  rescue CliBadArgument => e; exception_info=[e,'Argument',:usage]
263
275
  rescue CliNoSuchId => e; exception_info=[e,'Identifier']
264
276
  rescue CliError => e; exception_info=[e,'Tool',:usage]
265
- rescue Fasp::Error => e; exception_info=[e,"FASP(ascp]"]
266
- rescue Aspera::RestCallError => e; exception_info=[e,"Rest"]
267
- rescue SocketError => e; exception_info=[e,"Network"]
268
- rescue StandardError => e; exception_info=[e,"Other",:debug]
269
- rescue Interrupt => e; exception_info=[e,"Interruption",:debug]
277
+ rescue Fasp::Error => e; exception_info=[e,'FASP(ascp)']
278
+ rescue Aspera::RestCallError => e; exception_info=[e,'Rest']
279
+ rescue SocketError => e; exception_info=[e,'Network']
280
+ rescue StandardError => e; exception_info=[e,'Other',:debug]
281
+ rescue Interrupt => e; exception_info=[e,'Interruption',:debug]
270
282
  end
271
283
  # cleanup file list files
272
284
  TempFileManager.instance.cleanup
@@ -67,7 +67,10 @@ module Aspera
67
67
  when :delete
68
68
  rest_api.delete(one_res_path)
69
69
  return Main.result_status("deleted")
70
+ else
71
+ raise "unknown action: #{command}"
70
72
  end
73
+ raise "internal error should not reach here"
71
74
  end
72
75
 
73
76
  # implement generic rest operations on given resource path
@@ -77,13 +80,15 @@ module Aspera
77
80
  return entity_command(command,rest_api,res_class_path,display_fields,id_symb,id_default,subkey)
78
81
  end
79
82
 
80
- def options;@agents[:options];end
83
+ def options; return @agents[:options];end
81
84
 
82
- def transfer;@agents[:transfer];end
85
+ def transfer; return @agents[:transfer];end
83
86
 
84
- def config;return @agents[:config];end
87
+ def config; return @agents[:config];end
85
88
 
86
- def format;return @agents[:formater];end
89
+ def format; return @agents[:formater];end
90
+
91
+ def persistency; return @agents[:persistency];end
87
92
 
88
93
  end # Plugin
89
94
  end # Cli
@@ -12,7 +12,7 @@ module Aspera
12
12
  command=self.options.get_next_command(ACTIONS)
13
13
  case command
14
14
  when :entitlement
15
- entitlement_id = self.options.get_option(:username,:mandatory),
15
+ entitlement_id = self.options.get_option(:username,:mandatory)
16
16
  customer_id = self.options.get_option(:password,:mandatory)
17
17
  api_metering=AoC.metering_api(entitlement_id,customer_id)
18
18
  return {:type=>:single_object, :data=>api_metering.read('entitlement')[:data]}
@@ -3,6 +3,7 @@ require 'aspera/cli/plugins/ats'
3
3
  require 'aspera/cli/basic_auth_plugin'
4
4
  require 'aspera/cli/transfer_agent'
5
5
  require 'aspera/aoc'
6
+ require 'aspera/node'
6
7
  require 'aspera/persistency_action_once'
7
8
  require 'securerandom'
8
9
  require 'resolv'
@@ -12,9 +13,8 @@ module Aspera
12
13
  module Cli
13
14
  module Plugins
14
15
  class Aoc < BasicAuthPlugin
16
+ # special value for package id
15
17
  VAL_ALL='ALL'
16
- private_constant :VAL_ALL
17
- attr_reader :api_aoc
18
18
  def initialize(env)
19
19
  super(env)
20
20
  @default_workspace_id=nil
@@ -25,23 +25,23 @@ module Aspera
25
25
  @api_aoc=nil
26
26
  @url_token_data=nil
27
27
  @user_info=nil
28
- @ats=Ats.new(@agents)
29
- self.options.add_opt_list(:auth,Oauth.auth_types,"type of Oauth authentication")
30
- self.options.add_opt_list(:operation,[:push,:pull],"client operation for transfers")
31
- self.options.add_opt_simple(:client_id,"API client identifier in application")
32
- self.options.add_opt_simple(:client_secret,"API client passcode")
33
- self.options.add_opt_simple(:redirect_uri,"API client redirect URI")
34
- self.options.add_opt_simple(:private_key,"RSA private key PEM value for JWT (prefix file path with @val:@file:)")
35
- self.options.add_opt_simple(:workspace,"name of workspace")
36
- self.options.add_opt_simple(:eid,"identifier") # used ?
37
- self.options.add_opt_simple(:name,"resource name")
38
- self.options.add_opt_simple(:link,"public link to shared resource")
39
- self.options.add_opt_simple(:new_user_option,"new user creation option")
40
- self.options.add_opt_simple(:from_folder,"share to share source folder")
41
- self.options.add_opt_simple(:scope,"scope for AoC API calls")
42
- self.options.add_opt_simple(:notify,"notify users that file was received")
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")
28
+ @api_aoc=nil
29
+ self.options.add_opt_list(:auth,Oauth.auth_types,'OAuth type of authentication')
30
+ self.options.add_opt_list(:operation,[:push,:pull],'client operation for transfers')
31
+ self.options.add_opt_simple(:client_id,'OAuth API client identifier in application')
32
+ self.options.add_opt_simple(:client_secret,'OAuth API client passcode')
33
+ self.options.add_opt_simple(:redirect_uri,'OAuth API client redirect URI')
34
+ self.options.add_opt_simple(:private_key,'OAuth JWT RSA private key PEM value (prefix file path with @val:@file:)')
35
+ self.options.add_opt_simple(:workspace,'name of workspace')
36
+ self.options.add_opt_simple(:name,'resource name')
37
+ self.options.add_opt_simple(:path,'file or folder path')
38
+ self.options.add_opt_simple(:link,'public link to shared resource')
39
+ self.options.add_opt_simple(:new_user_option,'new user creation option')
40
+ self.options.add_opt_simple(:from_folder,'share to share source folder')
41
+ self.options.add_opt_simple(:scope,'OAuth scope for AoC API calls')
42
+ self.options.add_opt_simple(:notify,'notify users that file was received')
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
45
  self.options.set_option(:bulk,:no)
46
46
  self.options.set_option(:default_ports,:yes)
47
47
  self.options.set_option(:new_user_option,{'package_contact'=>true})
@@ -52,20 +52,19 @@ module Aspera
52
52
  self.options.parse_options!
53
53
  AoC.set_use_default_ports(self.options.get_option(:default_ports))
54
54
  return if env[:man_only]
55
- update_aoc_api
56
55
  end
57
56
 
58
- # call this to populate single AK secret in AoC API object, from options
59
- # make sure secret is available
60
- def find_ak_secret(ak,mandatory=true)
61
- # secret hash is already provisioned
62
- # optionally override with specific secret
63
- @api_aoc.add_secrets({ak=>self.config.get_secret(ak,mandatory)})
64
- # check that secret was provided as single value or dictionary
65
- raise CliBadArgument,"Please provide option secret or entry in option secrets for: #{ak}" unless @api_aoc.has_secret(ak) or !mandatory
57
+ def get_api
58
+ if @api_aoc.nil?
59
+ @api_aoc=AoC.new(aoc_params(AoC::API_V1))
60
+ # add keychain for access key secrets
61
+ @api_aoc.key_chain=@agents[:secret]
62
+ end
63
+ return @api_aoc
66
64
  end
67
65
 
68
- def user_info
66
+ # cached user information
67
+ def c_user_info
69
68
  if @user_info.nil?
70
69
  # get our user's default information
71
70
  # self?embed[]=default_workspace&embed[]=organization
@@ -80,16 +79,11 @@ module Aspera
80
79
  # starts transfer using transfer agent
81
80
  def transfer_start(app,direction,node_file,ts_add)
82
81
  ts_add.deep_merge!(AoC.analytics_ts(app,direction,@workspace_id,@workspace_name))
83
- ts_add.deep_merge!(AoC.console_ts(app,user_info['name'],user_info['email']))
82
+ ts_add.deep_merge!(AoC.console_ts(app,c_user_info['name'],c_user_info['email']))
84
83
  return self.transfer.start(*@api_aoc.tr_spec(app,direction,node_file,ts_add))
85
84
  end
86
85
 
87
- NODE4_COMMANDS=[ :browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node, :permissions ]
88
-
89
- def node_gen4_execute_action(top_node_file)
90
- command_repo=self.options.get_next_command(NODE4_COMMANDS)
91
- return execute_node_gen4_command(command_repo,top_node_file)
92
- end
86
+ NODE4_COMMANDS=[ :browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node ]
93
87
 
94
88
  def execute_node_gen4_command(command_repo,top_node_file)
95
89
  case command_repo
@@ -113,14 +107,8 @@ module Aspera
113
107
  return {:type=>:object_list,:data=>items,:fields=>['name','type','recursive_size','size','modified_time','access_level']}
114
108
  when :find
115
109
  thepath=self.options.get_next_argument('path')
116
- exec_prefix='exec:'
117
- expression=self.options.get_option(:value,:optional)||"#{exec_prefix}true"
118
110
  node_file=@api_aoc.resolve_node_file(top_node_file,thepath)
119
- if expression.start_with?(exec_prefix)
120
- test_block=eval "lambda{|f|#{expression[exec_prefix.length..-1]}}"
121
- else
122
- test_block=lambda{|f|f['name'].match(/#{expression}/)}
123
- end
111
+ test_block=Aspera::Node.file_matcher(self.options.get_option(:value,:optional))
124
112
  return {:type=>:object_list,:data=>@api_aoc.find_files(node_file,test_block),:fields=>['path']}
125
113
  when :mkdir
126
114
  thepath=self.options.get_next_argument('path')
@@ -139,12 +127,12 @@ module Aspera
139
127
  return Main.result_status("renamed #{thepath} to #{newname}")
140
128
  when :delete
141
129
  thepath=self.options.get_next_argument('path')
142
- return do_bulk_operation(thepath,'deleted','path') do |thepath|
143
- raise "expecting String (path), got #{thepath.class.name} (#{thepath})" unless thepath.is_a?(String)
144
- node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
130
+ return do_bulk_operation(thepath,'deleted','path') do |l_path|
131
+ raise "expecting String (path), got #{l_path.class.name} (#{l_path})" unless l_path.is_a?(String)
132
+ node_file = @api_aoc.resolve_node_file(top_node_file,l_path)
145
133
  node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
146
134
  result=node_api.delete("files/#{node_file[:file_id]}")[:data]
147
- {'path'=>thepath}
135
+ {'path'=>l_path}
148
136
  end
149
137
  when :transfer
150
138
  # client side is agent
@@ -213,69 +201,79 @@ module Aspera
213
201
  node_api=@api_aoc.get_node_api(top_node_file[:node_info],AoC::SCOPE_NODE_USER)
214
202
  return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: node_api)).execute_action(command_legacy)
215
203
  when :file
216
- fileid=self.options.get_next_argument('file id')
217
- node_file = @api_aoc.resolve_node_file(top_node_file)
218
- node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
219
- items=node_api.read("files/#{fileid}")[:data]
220
- return {:type=>:single_object,:data=>items}
221
- when :permissions
222
- fileid=self.options.get_next_argument('file id')
223
- node_file = @api_aoc.resolve_node_file(top_node_file)
204
+ file_path=self.options.get_option(:path,:optional)
205
+ node_file = if !file_path.nil?
206
+ @api_aoc.resolve_node_file(top_node_file,file_path) # TODO: allow follow link ?
207
+ else
208
+ {node_info: top_node_file[:node_info],file_id: self.options.get_option(:id,:mandatory)}
209
+ end
224
210
  node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
225
- command_perms=self.options.get_next_command([:show,:create])
226
- case command_perms
211
+ command_node_file=self.options.get_next_command([:show,:permission,:modify])
212
+ case command_node_file
227
213
  when :show
228
- items=node_api.read('permissions',{'include'=>['[]','access_level','permission_count'],'file_id'=>fileid,'inherited'=>false})[:data]
229
- return {:type=>:object_list,:data=>items}
230
- when :create
231
- #value=self.options.get_next_argument('creation value')
232
- set_workspace_info
233
- access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
234
- node_file[:node_info]
235
- params={
236
- "file_id"=>fileid,
237
- "access_type"=>"user",
238
- "access_id"=>access_id,
239
- "access_levels"=>["list","read","write","delete","mkdir","rename","preview"],
240
- "tags"=>{
241
- "aspera"=>{
242
- "files"=>{
243
- "workspace"=>{
244
- "id"=>@workspace_id,
245
- "workspace_name"=>@workspace_name,
246
- "user_name"=>user_info['name'],
247
- "shared_by_user_id"=>user_info['id'],
248
- "shared_by_name"=>user_info['name'],
249
- "shared_by_email"=>user_info['email'],
250
- "shared_with_name"=>access_id,
251
- "access_key"=>node_file[:node_info]['access_key'],
252
- "node"=>node_file[:node_info]['name']}}}}}
253
- item=node_api.create('permissions',params)[:data]
254
- return {:type=>:single_object,:data=>item}
255
- else raise "error"
214
+ items=node_api.read("files/#{node_file[:file_id]}")[:data]
215
+ return {:type=>:single_object,:data=>items}
216
+ when :modify
217
+ update_param=self.options.get_next_argument("update data (Hash)")
218
+ res=node_api.update("files/#{node_file[:file_id]}",update_param)[:data]
219
+ return {:type=>:single_object,:data=>res}
220
+ when :permission
221
+ command_perm=self.options.get_next_command([:list,:create])
222
+ case command_perm
223
+ when :list
224
+ # generic options : TODO: as arg ?
225
+ list_options||={'include'=>['[]','access_level','permission_count']}
226
+ # special value: ALL will show all permissions
227
+ if !VAL_ALL.eql?(node_file[:file_id])
228
+ # add which one to get
229
+ list_options['file_id']=node_file[:file_id]
230
+ list_options['inherited']||=false
231
+ end
232
+ #option_url_query
233
+ items=node_api.read('permissions',list_options)[:data]
234
+ return {:type=>:object_list,:data=>items}
235
+ when :create
236
+ #create_param=self.options.get_next_argument("creation data (Hash)")
237
+ set_workspace_info
238
+ access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
239
+ node_file[:node_info]
240
+ params={
241
+ 'file_id' =>node_file[:file_id], # mandatory
242
+ 'access_type' =>'user', # mandatory: user or group
243
+ 'access_id' =>access_id, # id of user or group
244
+ 'access_levels'=>Aspera::Node::ACCESS_LEVELS,
245
+ 'tags' =>{'aspera'=>{'files'=>{'workspace'=>{
246
+ 'id' =>@workspace_id,
247
+ 'workspace_name' =>@workspace_name,
248
+ 'user_name' =>c_user_info['name'],
249
+ 'shared_by_user_id'=>c_user_info['id'],
250
+ 'shared_by_name' =>c_user_info['name'],
251
+ 'shared_by_email' =>c_user_info['email'],
252
+ 'shared_with_name' =>access_id,
253
+ 'access_key' =>node_file[:node_info]['access_key'],
254
+ 'node' =>node_file[:node_info]['name']}}}}}
255
+ item=node_api.create('permissions',params)[:data]
256
+ return {:type=>:single_object,:data=>item}
257
+ else raise "internal error:shall not reach here (#{command_perm})"
258
+ end
259
+ raise "internal error:shall not reach here"
260
+ else raise "internal error:shall not reach here (#{command_node_file})"
256
261
  end
262
+ raise "internal error:shall not reach here"
263
+ when :permissions
264
+
257
265
  end # command_repo
258
- throw "ERR"
266
+ raise "ERR"
259
267
  end # execute_node_gen4_command
260
268
 
261
269
  # build constructor option list for AoC based on options of CLI
262
270
  def aoc_params(subpath)
263
271
  # copy command line options to args
264
- opt=[:link,:url,:auth,:client_id,:client_secret,:scope,:redirect_uri,:private_key,:username].inject({}){|m,i|m[i]=self.options.get_option(i,:optional);m}
272
+ 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}
265
273
  opt[:subpath]=subpath
266
274
  return opt
267
275
  end
268
276
 
269
- # Create a new AoC API REST object and set @api_aoc.
270
- # Parameters based on command line options
271
- # @return nil
272
- def update_aoc_api
273
- @api_aoc=AoC.new(aoc_params('api/v1'))
274
- # add access key secrets
275
- @api_aoc.add_secrets(self.config.get_secrets)
276
- return nil
277
- end
278
-
279
277
  # initialize apis and authentication
280
278
  # set:
281
279
  # @default_workspace_id
@@ -290,8 +288,8 @@ module Aspera
290
288
  @default_workspace_id=@url_token_data['data']['workspace_id']
291
289
  @persist_ids=[] # TODO : @url_token_data['id'] ?
292
290
  else
293
- @default_workspace_id=user_info['default_workspace_id']
294
- @persist_ids=[user_info['id']]
291
+ @default_workspace_id=c_user_info['default_workspace_id']
292
+ @persist_ids=[c_user_info['id']]
295
293
  end
296
294
 
297
295
  ws_name=self.options.get_option(:workspace,:optional)
@@ -401,7 +399,8 @@ module Aspera
401
399
  package_creation[recipient_list_field]=resolved_list
402
400
  end
403
401
 
404
- def url_query(default)
402
+ # private
403
+ def option_url_query(default)
405
404
  query=self.options.get_option(:query,:optional)||default
406
405
  Log.log.debug("Query=#{query}".bg_red)
407
406
  begin
@@ -420,8 +419,7 @@ module Aspera
420
419
  end
421
420
 
422
421
  def execute_admin_action
423
- self.options.set_option(:scope,AoC::SCOPE_FILES_ADMIN)
424
- update_aoc_api
422
+ @api_aoc.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
425
423
  command_admin=self.options.get_next_command([ :ats, :resource, :usage_reports, :analytics, :subscription, :auth_providers ])
426
424
  case command_admin
427
425
  when :auth_providers
@@ -490,20 +488,7 @@ module Aspera
490
488
  :base_url => @api_aoc.params[:base_url]+'/admin/ats/pub/v1',
491
489
  :auth => {:scope => AoC::SCOPE_FILES_ADMIN_USER}
492
490
  }))
493
- return @ats.execute_action_gen(ats_api)
494
- # when :search_nodes
495
- # query=self.options.get_option(:query,:optional) || '*'
496
- # nodes=@api_aoc.read("search_nodes",{'q'=>query})[:data]
497
- # # simplify output
498
- # nodes=nodes.map do |i|
499
- # item=i['_source']
500
- # item['score']=i['_score']
501
- # nodedata=item['access_key_recursive_counts'].first
502
- # item.delete('access_key_recursive_counts')
503
- # item['node']=nodedata
504
- # item
505
- # end
506
- # return {:type=>:object_list,:data=>nodes,:fields=>['host_name','node_status.cluster_id','node_status.node_id']}
491
+ return Ats.new(@agents).execute_action_gen(ats_api)
507
492
  when :analytics
508
493
  analytics_api = Rest.new(@api_aoc.params.deep_merge({
509
494
  :base_url => @api_aoc.params[:base_url].gsub('/api/v1','')+'/analytics/v2',
@@ -513,19 +498,20 @@ module Aspera
513
498
  case command_analytics
514
499
  when :application_events
515
500
  event_type=command_analytics.to_s
516
- events=analytics_api.read("organizations/#{user_info['organization_id']}/#{event_type}")[:data][event_type]
501
+ events=analytics_api.read("organizations/#{c_user_info['organization_id']}/#{event_type}")[:data][event_type]
517
502
  return {:type=>:object_list,:data=>events}
518
503
  when :transfers
519
504
  event_type=command_analytics.to_s
520
505
  filter_resource=self.options.get_option(:name,:optional) || 'organizations'
521
506
  filter_id=self.options.get_option(:id,:optional) || case filter_resource
522
- when 'organizations'; user_info['organization_id']
523
- when 'users'; user_info['id']
524
- when 'nodes'; user_info['id']
507
+ when 'organizations'; c_user_info['organization_id']
508
+ when 'users'; c_user_info['id']
509
+ when 'nodes'; c_user_info['id']
525
510
  else raise "organizations or users for option --name"
526
511
  end
527
512
  #
528
513
  filter=self.options.get_option(:query,:optional) || {}
514
+ raise "query must be Hash" unless filter.is_a?(Hash)
529
515
  filter['limit']||=100
530
516
  if self.options.get_option(:once_only,:mandatory)
531
517
  saved_date=[]
@@ -542,7 +528,7 @@ module Aspera
542
528
  filter['stop_time'] = stop_datetime
543
529
  end
544
530
  notification=self.options.get_option(:notify,:optional)
545
- events=analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",url_query(filter))[:data][event_type]
531
+ events=analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",option_url_query(filter))[:data][event_type]
546
532
  startdate_persistency.save unless startdate_persistency.nil?
547
533
  if !notification.nil?
548
534
  require 'erb'
@@ -558,17 +544,31 @@ module Aspera
558
544
  return {:type=>:object_list,:data=>events}
559
545
  end
560
546
  when :resource
561
- 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,'admin/apps_new'.to_sym,'admin/client_registration_token'.to_sym,'integrations/kms_profile'.to_sym])
562
- resource_class_path=resource_type.to_s+case resource_type;when :dropbox;'es';when :self,:organization,'admin/apps_new'.to_sym;'';else; 's';end
547
+ 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,:apps_new,:client_registration_token,:client_access_key,:kms_profile])
548
+ # get path on API
549
+ resource_class_path=case resource_type
550
+ when :self,:organization
551
+ "#{resource_type}"
552
+ when :apps_new
553
+ "admin/#{resource_type}"
554
+ when :dropbox
555
+ resource_type.to_s+'es'
556
+ when :client_registration_token,:client_access_key
557
+ "admin/#{resource_type}s"
558
+ when :kms_profile
559
+ "integrations/#{resource_type}s"
560
+ else
561
+ resource_type.to_s+'s'
562
+ end
563
+ # build list of supported operations
563
564
  singleton_object=[:self,:organization].include?(resource_type)
564
565
  global_operations=[:create,:list]
565
566
  supported_operations=[:show,:modify]
566
567
  supported_operations.push(:delete,*global_operations) unless singleton_object
567
568
  supported_operations.push(:v4,:v3) if resource_type.eql?(:node)
568
569
  supported_operations.push(:set_pub_key) if resource_type.eql?(:client)
569
- supported_operations.push(:shared_folders) if [:node,:workspace].include?(resource_type)
570
+ supported_operations.push(:shared_folders,:shared_create) if [:node,:workspace].include?(resource_type)
570
571
  command=self.options.get_next_command(supported_operations)
571
-
572
572
  # require identifier for non global commands
573
573
  if !singleton_object and !global_operations.include?(command)
574
574
  res_id=self.options.get_option(:id)
@@ -607,11 +607,13 @@ module Aspera
607
607
  when :node; default_fields.push('host','access_key')
608
608
  when :operation; default_fields=nil
609
609
  when :contact; default_fields=["email","name","source_id","source_type"]
610
- when 'admin/apps_new'.to_sym; list_query={:organization_apps=>true};default_fields=['app_type','available']
611
- when 'admin/client_registration_token'.to_sym; default_fields=['id','value','data.client_subject_scopes','created_at']
610
+ when :apps_new; list_query={:organization_apps=>true};default_fields=['app_type','available']
611
+ when :client_registration_token; default_fields=['id','value','data.client_subject_scopes','created_at']
612
612
  end
613
- result=@api_aoc.read(resource_class_path,url_query(list_query))
614
- self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
613
+ result=@api_aoc.read(resource_class_path,option_url_query(list_query))
614
+ count_msg="Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}"
615
+ count_msg=count_msg.bg_red unless result[:data].length.eql?(result[:http]['X-Total-Count'].to_i)
616
+ self.format.display_status(count_msg)
615
617
  return {:type=>:object_list,:data=>result[:data],:fields=>default_fields}
616
618
  when :show
617
619
  object=@api_aoc.read(resource_instance_path)[:data]
@@ -634,23 +636,11 @@ module Aspera
634
636
  return Main.result_success
635
637
  when :v3,:v4
636
638
  res_data=@api_aoc.read(resource_instance_path)[:data]
637
- find_ak_secret(res_data['access_key'])
638
639
  api_node=@api_aoc.get_node_api(res_data)
639
640
  return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action if command.eql?(:v3)
640
641
  ak_data=api_node.call({:operation=>'GET',:subpath=>"access_keys/#{res_data['access_key']}",:headers=>{'Accept'=>'application/json'}})[:data]
641
- return node_gen4_execute_action({node_info: res_data, file_id: ak_data['root_file_id']})
642
- # when :info
643
- # object=@api_aoc.read(resource_instance_path)[:data]
644
- # access_key=object['access_key']
645
- # match_list=@api_aoc.read('admin/search_nodes',{:q=>"access_key:\"#{access_key}\""})[:data]
646
- # result=match_list.select{|i|i["_source"]["access_key_recursive_counts"].first["access_key"].eql?(access_key)}
647
- # return Main.result_status('Private node') if result.empty?
648
- # raise CliError,"more than one match" unless result.length.eql?(1)
649
- # result=result.first["_source"]
650
- # result.merge!(result['access_key_recursive_counts'].first)
651
- # result.delete('access_key_recursive_counts')
652
- # result.delete('token')
653
- # return { :type=>:single_object, :data =>result}
642
+ command_repo=self.options.get_next_command(NODE4_COMMANDS)
643
+ return execute_node_gen4_command(command_repo,{node_info: res_data, file_id: ak_data['root_file_id']})
654
644
  when :shared_folders
655
645
  read_params = case resource_type
656
646
  when :workspace;{'access_id'=>"ASPERA_ACCESS_KEY_ADMIN_WS_#{res_id}",'access_type'=>'user'}
@@ -661,26 +651,59 @@ module Aspera
661
651
  fields=case resource_type
662
652
  when :node;['id','file_id','file.path','access_type']
663
653
  when :workspace;['id','node_id','file_id','node_name','file.path','tags.aspera.files.workspace.share_as']
664
- else raise "error"
654
+ else raise "unexpected resource type #{resource_type}"
665
655
  end
666
656
  return { :type=>:object_list, :data =>res_data , :fields=>fields}
667
- else raise :ERROR
657
+ when :shared_create
658
+ # TODO
659
+ folder_path=self.options.get_next_argument('folder path in node')
660
+ user_create_data=self.options.get_next_argument('creation data (Hash)')
661
+ res_data=@api_aoc.read(resource_instance_path)[:data]
662
+ node_file = @api_aoc.resolve_node_file({node_info: res_data, file_id: ak_data['root_file_id']},folder_path)
663
+
664
+ #node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
665
+ #file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
666
+
667
+ access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
668
+ create_data={
669
+ 'file_id' =>node_file[:file_id],
670
+ 'access_type' =>'user',
671
+ 'access_id' =>access_id,
672
+ 'access_levels'=>['list','read','write','delete','mkdir','rename','preview'],
673
+ 'tags' =>{'aspera'=>{'files'=>{'workspace'=>{
674
+ 'id' =>@workspace_id,
675
+ 'workspace_name' =>@workspace_name,
676
+ 'share_as' =>File.basename(folder_path),
677
+ 'user_name' =>c_user_info['name'],
678
+ 'shared_by_user_id'=>c_user_info['id'],
679
+ 'shared_by_name' =>c_user_info['name'],
680
+ 'shared_by_email' =>c_user_info['email'],
681
+ 'shared_with_name' =>access_id,
682
+ 'access_key' =>node_file[:node_info]['access_key'],
683
+ 'node' =>node_file[:node_info]['name']}
684
+ }}}}
685
+ create_data.deep_merge!(user_create_data)
686
+ Log.dump(:data,create_data)
687
+ raise :ERROR
688
+ else raise "unknown command"
668
689
  end
669
690
  when :usage_reports
670
- return {:type=>:object_list,:data=>@api_aoc.read("usage_reports",{:workspace_id=>@workspace_id})[:data]}
691
+ return {:type=>:object_list,:data=>@api_aoc.read('usage_reports',{:workspace_id=>@workspace_id})[:data]}
671
692
  end
672
693
  end
673
694
 
674
- ACTIONS=[ :apiinfo, :bearer_token, :organization, :tier_restrictions, :user, :workspace, :packages, :files, :gateway, :admin, :automation, :servers]
695
+ # must be public
696
+ ACTIONS=[ :reminder, :bearer_token, :organization, :tier_restrictions, :user, :workspace, :packages, :files, :gateway, :admin, :automation, :servers]
675
697
 
676
698
  def execute_action
677
699
  command=self.options.get_next_command(ACTIONS)
700
+ get_api unless [:reminder,:servers].include?(command)
678
701
  case command
679
- when :apiinfo
680
- api_info={}
681
- num=1
682
- Resolv::DNS.open{|dns|dns.each_address('api.ibmaspera.com'){|a| api_info["api.#{num}"]=a;num+=1}}
683
- return {:type=>:single_object,:data=>api_info}
702
+ when :reminder
703
+ # send an email reminder with list of orgs
704
+ user_email=options.get_option(:username,:mandatory)
705
+ Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").create('organization_reminders',{email: user_email})[:data]
706
+ return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
684
707
  when :bearer_token
685
708
  return {:type=>:text,:data=>@api_aoc.oauth_token}
686
709
  when :organization
@@ -691,23 +714,23 @@ module Aspera
691
714
  command=self.options.get_next_command([ :workspaces,:info,:shared_inboxes ])
692
715
  case command
693
716
  when :workspaces
694
- return {:type=>:object_list,:data=>@api_aoc.read("workspaces")[:data],:fields=>['id','name']}
717
+ return {:type=>:object_list,:data=>@api_aoc.read('workspaces')[:data],:fields=>['id','name']}
695
718
  # when :settings
696
719
  # return {:type=>:object_list,:data=>@api_aoc.read("client_settings/")[:data]}
697
720
  when :shared_inboxes
698
- query=url_query(nil)
721
+ query=option_url_query(nil)
699
722
  if query.nil?
700
723
  set_workspace_info
701
724
  query={'embed[]'=>'dropbox','workspace_id'=>@workspace_id,'aggregate_permissions_by_dropbox'=>true,'sort'=>'dropbox_name'}
702
725
  end
703
- return {:type=>:object_list,:data=>@api_aoc.read("dropbox_memberships",query)[:data],:fields=>['dropbox_id','dropbox.name']}
726
+ return {:type=>:object_list,:data=>@api_aoc.read('dropbox_memberships',query)[:data],:fields=>['dropbox_id','dropbox.name']}
704
727
  when :info
705
728
  command=self.options.get_next_command([ :show,:modify ])
706
729
  case command
707
730
  when :show
708
- return { :type=>:single_object, :data =>user_info }
731
+ return { :type=>:single_object, :data =>c_user_info }
709
732
  when :modify
710
- @api_aoc.update("users/#{user_info['id']}",self.options.get_next_argument('modified parameters (hash)'))
733
+ @api_aoc.update("users/#{c_user_info['id']}",self.options.get_next_argument('modified parameters (hash)'))
711
734
  return Main.result_status('modified')
712
735
  end
713
736
  end
@@ -720,7 +743,7 @@ module Aspera
720
743
  case command_pkg
721
744
  when :send
722
745
  package_creation=self.options.get_option(:value,:mandatory)
723
- raise CliBadArgument,"value must be hash, refer to doc" unless package_creation.is_a?(Hash)
746
+ raise CliBadArgument,'value must be hash, refer to doc' unless package_creation.is_a?(Hash)
724
747
 
725
748
  if !@url_token_data.nil?
726
749
  assert_public_link_types(['send_package_to_user','send_package_to_dropbox'])
@@ -801,12 +824,12 @@ module Aspera
801
824
  return { :type=>:single_object, :data =>package_info }
802
825
  when :list
803
826
  # list all packages ('page'=>1,'per_page'=>10,)'sort'=>'-sent_at',
804
- packages=@api_aoc.read("packages",{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
827
+ packages=@api_aoc.read('packages',{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
805
828
  return {:type=>:object_list,:data=>packages,:fields=>['id','name','bytes_transferred']}
806
829
  when :delete
807
830
  list_or_one=self.options.get_option(:id,:mandatory)
808
831
  return do_bulk_operation(list_or_one,'deleted')do|id|
809
- raise "expecting String identifier" unless id.is_a?(String) or id.is_a?(Integer)
832
+ raise 'expecting String identifier' unless id.is_a?(String) or id.is_a?(Integer)
810
833
  @api_aoc.delete("packages/#{id}")[:data]
811
834
  end
812
835
  end
@@ -814,7 +837,6 @@ module Aspera
814
837
  # get workspace related information
815
838
  set_workspace_info
816
839
  set_home_node_file
817
- find_ak_secret(@home_node_file[:node_info]['access_key'],false)
818
840
  command_repo=self.options.get_next_command(NODE4_COMMANDS.clone.concat([:short_link]))
819
841
  case command_repo
820
842
  when *NODE4_COMMANDS; return execute_node_gen4_command(command_repo,@home_node_file)
@@ -827,7 +849,7 @@ module Aspera
827
849
  when 'private'
828
850
  value_option={'purpose'=>'shared_folder_auth_link'}
829
851
  when NilClass,Hash
830
- else raise "value must be either: public, private, Hash or nil"
852
+ else raise 'value must be either: public, private, Hash or nil'
831
853
  end
832
854
  create_params=nil
833
855
  node_file=nil
@@ -855,30 +877,33 @@ module Aspera
855
877
  }
856
878
  value_option['user_selected_name']=nil
857
879
  else
858
- raise "purpose must be one of: token_auth_redirection or shared_folder_auth_link"
880
+ raise 'purpose must be one of: token_auth_redirection or shared_folder_auth_link'
859
881
  end
860
882
  self.options.set_option(:value,value_option)
861
883
  end
862
884
  result=self.entity_action(@api_aoc,'short_links',nil,:id,'self')
863
885
  if result[:data].is_a?(Hash) and result[:data].has_key?('created_at') and result[:data]['resource_type'].eql?('UrlToken')
864
886
  node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
887
+ # TODO: access level as arg
888
+ access_levels=Aspera::Node::ACCESS_LEVELS #['delete','list','mkdir','preview','read','rename','write']
865
889
  perm_data={
866
- "file_id" =>node_file[:file_id],
867
- "access_type" =>"user",
868
- "access_id" =>result[:data]['resource_id'],
869
- "access_levels"=>["delete","list","mkdir","preview","read","rename","write"],
870
- "tags" =>{
871
- "url_token" =>true,
872
- "workspace_id" =>@workspace_id,
873
- "workspace_name" =>@workspace_name,
874
- "folder_name" =>"my folder",
875
- "created_by_name" =>user_info['name'],
876
- "created_by_email"=>user_info['email'],
877
- "access_key" =>node_file[:node_info]['access_key'],
878
- "node" =>node_file[:node_info]['host']
890
+ 'file_id' =>node_file[:file_id],
891
+ 'access_type' =>'user',
892
+ 'access_id' =>result[:data]['resource_id'],
893
+ 'access_levels'=>access_levels,
894
+ 'tags' =>{
895
+ 'url_token' =>true,
896
+ 'workspace_id' =>@workspace_id,
897
+ 'workspace_name' =>@workspace_name,
898
+ 'folder_name' =>'my folder',
899
+ 'created_by_name' =>c_user_info['name'],
900
+ 'created_by_email'=>c_user_info['email'],
901
+ 'access_key' =>node_file[:node_info]['access_key'],
902
+ 'node' =>node_file[:node_info]['host']
879
903
  }
880
904
  }
881
905
  node_api.create("permissions?file_id=#{node_file[:file_id]}",perm_data)
906
+ # TODO: event ?
882
907
  end
883
908
  return result
884
909
  end # files command
@@ -921,17 +946,17 @@ module Aspera
921
946
  when :admin
922
947
  return execute_admin_action
923
948
  when :servers
924
- self.format.display_status("Beta feature")
925
- server_api=Rest.new(base_url: 'https://eudemo.asperademo.com')
926
- require 'json'
927
- servers=JSON.parse(server_api.read('servers')[:data])
928
- return {:type=>:object_list,:data=>servers}
949
+ return {:type=>:object_list,:data=>Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
929
950
  else
930
951
  raise "internal error: #{command}"
931
952
  end # action
932
953
  raise RuntimeError, "internal error: command shall return"
933
954
  end
934
- end # Aspera
955
+
956
+ 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
957
+ private_constant :VAL_ALL,:NODE4_COMMANDS
958
+
959
+ end # AoC
935
960
  end # Plugins
936
961
  end # Cli
937
962
  end # Aspera