aspera-cli 4.0.0 → 4.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +843 -304
  3. data/bin/dascli +13 -0
  4. data/docs/Makefile +4 -4
  5. data/docs/README.erb.md +805 -172
  6. data/docs/test_env.conf +22 -3
  7. data/examples/aoc.rb +14 -3
  8. data/examples/faspex4.rb +89 -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 +89 -49
  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 +188 -173
  15. data/lib/aspera/cli/plugins/ats.rb +2 -2
  16. data/lib/aspera/cli/plugins/config.rb +218 -145
  17. data/lib/aspera/cli/plugins/console.rb +2 -2
  18. data/lib/aspera/cli/plugins/faspex.rb +114 -61
  19. data/lib/aspera/cli/plugins/faspex5.rb +85 -43
  20. data/lib/aspera/cli/plugins/node.rb +3 -3
  21. data/lib/aspera/cli/plugins/preview.rb +59 -45
  22. data/lib/aspera/cli/plugins/server.rb +23 -8
  23. data/lib/aspera/cli/transfer_agent.rb +77 -49
  24. data/lib/aspera/cli/version.rb +1 -1
  25. data/lib/aspera/command_line_builder.rb +49 -31
  26. data/lib/aspera/cos_node.rb +33 -28
  27. data/lib/aspera/environment.rb +2 -2
  28. data/lib/aspera/fasp/connect.rb +28 -21
  29. data/lib/aspera/fasp/http_gw.rb +140 -28
  30. data/lib/aspera/fasp/installation.rb +93 -46
  31. data/lib/aspera/fasp/local.rb +88 -45
  32. data/lib/aspera/fasp/manager.rb +15 -0
  33. data/lib/aspera/fasp/node.rb +4 -4
  34. data/lib/aspera/fasp/parameters.rb +59 -101
  35. data/lib/aspera/fasp/parameters.yaml +531 -0
  36. data/lib/aspera/fasp/resume_policy.rb +13 -12
  37. data/lib/aspera/fasp/uri.rb +1 -1
  38. data/lib/aspera/log.rb +1 -1
  39. data/lib/aspera/node.rb +61 -1
  40. data/lib/aspera/oauth.rb +49 -46
  41. data/lib/aspera/persistency_folder.rb +9 -4
  42. data/lib/aspera/preview/file_types.rb +53 -21
  43. data/lib/aspera/preview/generator.rb +3 -3
  44. data/lib/aspera/rest.rb +29 -18
  45. data/lib/aspera/secrets.rb +20 -0
  46. data/lib/aspera/sync.rb +40 -35
  47. data/lib/aspera/temp_file_manager.rb +19 -0
  48. data/lib/aspera/web_auth.rb +105 -0
  49. metadata +54 -20
  50. data/docs/transfer_spec.html +0 -99
@@ -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,22 @@ 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_boolean(:bulk,'bulk operation')
43
+ self.options.add_opt_boolean(:default_ports,'use standard FASP ports or get from node api')
45
44
  self.options.set_option(:bulk,:no)
46
45
  self.options.set_option(:default_ports,:yes)
47
46
  self.options.set_option(:new_user_option,{'package_contact'=>true})
@@ -52,20 +51,19 @@ module Aspera
52
51
  self.options.parse_options!
53
52
  AoC.set_use_default_ports(self.options.get_option(:default_ports))
54
53
  return if env[:man_only]
55
- update_aoc_api
56
54
  end
57
55
 
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
56
+ def get_api
57
+ if @api_aoc.nil?
58
+ @api_aoc=AoC.new(aoc_params(AoC::API_V1))
59
+ # add keychain for access key secrets
60
+ @api_aoc.key_chain=@agents[:secret]
61
+ end
62
+ return @api_aoc
66
63
  end
67
64
 
68
- def user_info
65
+ # cached user information
66
+ def c_user_info
69
67
  if @user_info.nil?
70
68
  # get our user's default information
71
69
  # self?embed[]=default_workspace&embed[]=organization
@@ -80,16 +78,11 @@ module Aspera
80
78
  # starts transfer using transfer agent
81
79
  def transfer_start(app,direction,node_file,ts_add)
82
80
  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']))
81
+ ts_add.deep_merge!(AoC.console_ts(app,c_user_info['name'],c_user_info['email']))
84
82
  return self.transfer.start(*@api_aoc.tr_spec(app,direction,node_file,ts_add))
85
83
  end
86
84
 
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
85
+ NODE4_COMMANDS=[ :browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node ]
93
86
 
94
87
  def execute_node_gen4_command(command_repo,top_node_file)
95
88
  case command_repo
@@ -113,14 +106,8 @@ module Aspera
113
106
  return {:type=>:object_list,:data=>items,:fields=>['name','type','recursive_size','size','modified_time','access_level']}
114
107
  when :find
115
108
  thepath=self.options.get_next_argument('path')
116
- exec_prefix='exec:'
117
- expression=self.options.get_option(:value,:optional)||"#{exec_prefix}true"
118
109
  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
110
+ test_block=Aspera::Node.file_matcher(self.options.get_option(:value,:optional))
124
111
  return {:type=>:object_list,:data=>@api_aoc.find_files(node_file,test_block),:fields=>['path']}
125
112
  when :mkdir
126
113
  thepath=self.options.get_next_argument('path')
@@ -213,69 +200,79 @@ module Aspera
213
200
  node_api=@api_aoc.get_node_api(top_node_file[:node_info],AoC::SCOPE_NODE_USER)
214
201
  return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: node_api)).execute_action(command_legacy)
215
202
  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)
203
+ file_path=self.options.get_option(:path,:optional)
204
+ node_file = if !file_path.nil?
205
+ @api_aoc.resolve_node_file(top_node_file,file_path) # TODO: allow follow link ?
206
+ else
207
+ {node_info: top_node_file[:node_info],file_id: self.options.get_option(:id,:mandatory)}
208
+ end
224
209
  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
210
+ command_node_file=self.options.get_next_command([:show,:permission,:modify])
211
+ case command_node_file
227
212
  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"
213
+ items=node_api.read("files/#{node_file[:file_id]}")[:data]
214
+ return {:type=>:single_object,:data=>items}
215
+ when :modify
216
+ update_param=self.options.get_next_argument("update data (Hash)")
217
+ res=node_api.update("files/#{node_file[:file_id]}",update_param)[:data]
218
+ return {:type=>:single_object,:data=>res}
219
+ when :permission
220
+ command_perm=self.options.get_next_command([:list,:create])
221
+ case command_perm
222
+ when :list
223
+ # generic options : TODO: as arg ?
224
+ list_options||={'include'=>['[]','access_level','permission_count']}
225
+ # special value: ALL will show all permissions
226
+ if !VAL_ALL.eql?(node_file[:file_id])
227
+ # add which one to get
228
+ list_options['file_id']=node_file[:file_id]
229
+ list_options['inherited']||=false
230
+ end
231
+ #option_url_query
232
+ items=node_api.read('permissions',list_options)[:data]
233
+ return {:type=>:object_list,:data=>items}
234
+ when :create
235
+ #create_param=self.options.get_next_argument("creation data (Hash)")
236
+ set_workspace_info
237
+ access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
238
+ node_file[:node_info]
239
+ params={
240
+ 'file_id' =>node_file[:file_id], # mandatory
241
+ 'access_type' =>'user', # mandatory: user or group
242
+ 'access_id' =>access_id, # id of user or group
243
+ 'access_levels'=>Aspera::Node::ACCESS_LEVELS,
244
+ 'tags' =>{'aspera'=>{'files'=>{'workspace'=>{
245
+ 'id' =>@workspace_id,
246
+ 'workspace_name' =>@workspace_name,
247
+ 'user_name' =>c_user_info['name'],
248
+ 'shared_by_user_id'=>c_user_info['id'],
249
+ 'shared_by_name' =>c_user_info['name'],
250
+ 'shared_by_email' =>c_user_info['email'],
251
+ 'shared_with_name' =>access_id,
252
+ 'access_key' =>node_file[:node_info]['access_key'],
253
+ 'node' =>node_file[:node_info]['name']}}}}}
254
+ item=node_api.create('permissions',params)[:data]
255
+ return {:type=>:single_object,:data=>item}
256
+ else raise "internal error:shall not reach here (#{command_perm})"
257
+ end
258
+ raise "internal error:shall not reach here"
259
+ else raise "internal error:shall not reach here (#{command_node_file})"
256
260
  end
261
+ raise "internal error:shall not reach here"
262
+ when :permissions
263
+
257
264
  end # command_repo
258
- throw "ERR"
265
+ raise "ERR"
259
266
  end # execute_node_gen4_command
260
267
 
261
268
  # build constructor option list for AoC based on options of CLI
262
269
  def aoc_params(subpath)
263
270
  # 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}
271
+ 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
272
  opt[:subpath]=subpath
266
273
  return opt
267
274
  end
268
275
 
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
276
  # initialize apis and authentication
280
277
  # set:
281
278
  # @default_workspace_id
@@ -290,8 +287,8 @@ module Aspera
290
287
  @default_workspace_id=@url_token_data['data']['workspace_id']
291
288
  @persist_ids=[] # TODO : @url_token_data['id'] ?
292
289
  else
293
- @default_workspace_id=user_info['default_workspace_id']
294
- @persist_ids=[user_info['id']]
290
+ @default_workspace_id=c_user_info['default_workspace_id']
291
+ @persist_ids=[c_user_info['id']]
295
292
  end
296
293
 
297
294
  ws_name=self.options.get_option(:workspace,:optional)
@@ -401,7 +398,8 @@ module Aspera
401
398
  package_creation[recipient_list_field]=resolved_list
402
399
  end
403
400
 
404
- def url_query(default)
401
+ # private
402
+ def option_url_query(default)
405
403
  query=self.options.get_option(:query,:optional)||default
406
404
  Log.log.debug("Query=#{query}".bg_red)
407
405
  begin
@@ -420,8 +418,7 @@ module Aspera
420
418
  end
421
419
 
422
420
  def execute_admin_action
423
- self.options.set_option(:scope,AoC::SCOPE_FILES_ADMIN)
424
- update_aoc_api
421
+ @api_aoc.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
425
422
  command_admin=self.options.get_next_command([ :ats, :resource, :usage_reports, :analytics, :subscription, :auth_providers ])
426
423
  case command_admin
427
424
  when :auth_providers
@@ -490,20 +487,7 @@ module Aspera
490
487
  :base_url => @api_aoc.params[:base_url]+'/admin/ats/pub/v1',
491
488
  :auth => {:scope => AoC::SCOPE_FILES_ADMIN_USER}
492
489
  }))
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']}
490
+ return Ats.new(@agents).execute_action_gen(ats_api)
507
491
  when :analytics
508
492
  analytics_api = Rest.new(@api_aoc.params.deep_merge({
509
493
  :base_url => @api_aoc.params[:base_url].gsub('/api/v1','')+'/analytics/v2',
@@ -513,19 +497,20 @@ module Aspera
513
497
  case command_analytics
514
498
  when :application_events
515
499
  event_type=command_analytics.to_s
516
- events=analytics_api.read("organizations/#{user_info['organization_id']}/#{event_type}")[:data][event_type]
500
+ events=analytics_api.read("organizations/#{c_user_info['organization_id']}/#{event_type}")[:data][event_type]
517
501
  return {:type=>:object_list,:data=>events}
518
502
  when :transfers
519
503
  event_type=command_analytics.to_s
520
504
  filter_resource=self.options.get_option(:name,:optional) || 'organizations'
521
505
  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']
506
+ when 'organizations'; c_user_info['organization_id']
507
+ when 'users'; c_user_info['id']
508
+ when 'nodes'; c_user_info['id']
525
509
  else raise "organizations or users for option --name"
526
510
  end
527
511
  #
528
512
  filter=self.options.get_option(:query,:optional) || {}
513
+ raise "query must be Hash" unless filter.is_a?(Hash)
529
514
  filter['limit']||=100
530
515
  if self.options.get_option(:once_only,:mandatory)
531
516
  saved_date=[]
@@ -541,18 +526,11 @@ module Aspera
541
526
  filter['start_time'] = start_datetime unless start_datetime.nil?
542
527
  filter['stop_time'] = stop_datetime
543
528
  end
544
- notification=self.options.get_option(:notify,:optional)
545
- events=analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",url_query(filter))[:data][event_type]
529
+ events=analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",option_url_query(filter))[:data][event_type]
546
530
  startdate_persistency.save unless startdate_persistency.nil?
547
- if !notification.nil?
548
- require 'erb'
549
- events.each do |transfer|
550
- email_to_send={}
551
- notification.each do |k,v|
552
- email_to_send[k.to_sym]=ERB.new(v).result(binding)
553
- end
554
- Log.log().error("send email: #{email_to_send}")
555
- self.config.send_email(email_to_send)
531
+ if !self.options.get_option(:notif_to,:optional).nil?
532
+ events.each do |tr_event|
533
+ self.config.send_email_template({ev: tr_event})
556
534
  end
557
535
  end
558
536
  return {:type=>:object_list,:data=>events}
@@ -581,7 +559,7 @@ module Aspera
581
559
  supported_operations.push(:delete,*global_operations) unless singleton_object
582
560
  supported_operations.push(:v4,:v3) if resource_type.eql?(:node)
583
561
  supported_operations.push(:set_pub_key) if resource_type.eql?(:client)
584
- supported_operations.push(:shared_folders) if [:node,:workspace].include?(resource_type)
562
+ supported_operations.push(:shared_folders,:shared_create) if [:node,:workspace].include?(resource_type)
585
563
  command=self.options.get_next_command(supported_operations)
586
564
  # require identifier for non global commands
587
565
  if !singleton_object and !global_operations.include?(command)
@@ -624,8 +602,10 @@ module Aspera
624
602
  when :apps_new; list_query={:organization_apps=>true};default_fields=['app_type','available']
625
603
  when :client_registration_token; default_fields=['id','value','data.client_subject_scopes','created_at']
626
604
  end
627
- result=@api_aoc.read(resource_class_path,url_query(list_query))
628
- self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
605
+ result=@api_aoc.read(resource_class_path,option_url_query(list_query))
606
+ count_msg="Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}"
607
+ count_msg=count_msg.bg_red unless result[:data].length.eql?(result[:http]['X-Total-Count'].to_i)
608
+ self.format.display_status(count_msg)
629
609
  return {:type=>:object_list,:data=>result[:data],:fields=>default_fields}
630
610
  when :show
631
611
  object=@api_aoc.read(resource_instance_path)[:data]
@@ -648,11 +628,11 @@ module Aspera
648
628
  return Main.result_success
649
629
  when :v3,:v4
650
630
  res_data=@api_aoc.read(resource_instance_path)[:data]
651
- find_ak_secret(res_data['access_key'])
652
631
  api_node=@api_aoc.get_node_api(res_data)
653
632
  return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action if command.eql?(:v3)
654
633
  ak_data=api_node.call({:operation=>'GET',:subpath=>"access_keys/#{res_data['access_key']}",:headers=>{'Accept'=>'application/json'}})[:data]
655
- return node_gen4_execute_action({node_info: res_data, file_id: ak_data['root_file_id']})
634
+ command_repo=self.options.get_next_command(NODE4_COMMANDS)
635
+ return execute_node_gen4_command(command_repo,{node_info: res_data, file_id: ak_data['root_file_id']})
656
636
  when :shared_folders
657
637
  read_params = case resource_type
658
638
  when :workspace;{'access_id'=>"ASPERA_ACCESS_KEY_ADMIN_WS_#{res_id}",'access_type'=>'user'}
@@ -663,26 +643,59 @@ module Aspera
663
643
  fields=case resource_type
664
644
  when :node;['id','file_id','file.path','access_type']
665
645
  when :workspace;['id','node_id','file_id','node_name','file.path','tags.aspera.files.workspace.share_as']
666
- else raise "error"
646
+ else raise "unexpected resource type #{resource_type}"
667
647
  end
668
648
  return { :type=>:object_list, :data =>res_data , :fields=>fields}
669
- else raise :ERROR
649
+ when :shared_create
650
+ # TODO
651
+ folder_path=self.options.get_next_argument('folder path in node')
652
+ user_create_data=self.options.get_next_argument('creation data (Hash)')
653
+ res_data=@api_aoc.read(resource_instance_path)[:data]
654
+ node_file = @api_aoc.resolve_node_file({node_info: res_data, file_id: ak_data['root_file_id']},folder_path)
655
+
656
+ #node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
657
+ #file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
658
+
659
+ access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
660
+ create_data={
661
+ 'file_id' =>node_file[:file_id],
662
+ 'access_type' =>'user',
663
+ 'access_id' =>access_id,
664
+ 'access_levels'=>['list','read','write','delete','mkdir','rename','preview'],
665
+ 'tags' =>{'aspera'=>{'files'=>{'workspace'=>{
666
+ 'id' =>@workspace_id,
667
+ 'workspace_name' =>@workspace_name,
668
+ 'share_as' =>File.basename(folder_path),
669
+ 'user_name' =>c_user_info['name'],
670
+ 'shared_by_user_id'=>c_user_info['id'],
671
+ 'shared_by_name' =>c_user_info['name'],
672
+ 'shared_by_email' =>c_user_info['email'],
673
+ 'shared_with_name' =>access_id,
674
+ 'access_key' =>node_file[:node_info]['access_key'],
675
+ 'node' =>node_file[:node_info]['name']}
676
+ }}}}
677
+ create_data.deep_merge!(user_create_data)
678
+ Log.dump(:data,create_data)
679
+ raise :ERROR
680
+ else raise "unknown command"
670
681
  end
671
682
  when :usage_reports
672
- return {:type=>:object_list,:data=>@api_aoc.read("usage_reports",{:workspace_id=>@workspace_id})[:data]}
683
+ return {:type=>:object_list,:data=>@api_aoc.read('usage_reports',{:workspace_id=>@workspace_id})[:data]}
673
684
  end
674
685
  end
675
686
 
676
- ACTIONS=[ :apiinfo, :bearer_token, :organization, :tier_restrictions, :user, :workspace, :packages, :files, :gateway, :admin, :automation, :servers]
687
+ # must be public
688
+ ACTIONS=[ :reminder, :bearer_token, :organization, :tier_restrictions, :user, :workspace, :packages, :files, :gateway, :admin, :automation, :servers]
677
689
 
678
690
  def execute_action
679
691
  command=self.options.get_next_command(ACTIONS)
692
+ get_api unless [:reminder,:servers].include?(command)
680
693
  case command
681
- when :apiinfo
682
- api_info={}
683
- num=1
684
- Resolv::DNS.open{|dns|dns.each_address('api.ibmaspera.com'){|a| api_info["api.#{num}"]=a;num+=1}}
685
- return {:type=>:single_object,:data=>api_info}
694
+ when :reminder
695
+ # send an email reminder with list of orgs
696
+ user_email=options.get_option(:username,:mandatory)
697
+ Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").create('organization_reminders',{email: user_email})[:data]
698
+ return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
686
699
  when :bearer_token
687
700
  return {:type=>:text,:data=>@api_aoc.oauth_token}
688
701
  when :organization
@@ -693,23 +706,23 @@ module Aspera
693
706
  command=self.options.get_next_command([ :workspaces,:info,:shared_inboxes ])
694
707
  case command
695
708
  when :workspaces
696
- return {:type=>:object_list,:data=>@api_aoc.read("workspaces")[:data],:fields=>['id','name']}
709
+ return {:type=>:object_list,:data=>@api_aoc.read('workspaces')[:data],:fields=>['id','name']}
697
710
  # when :settings
698
711
  # return {:type=>:object_list,:data=>@api_aoc.read("client_settings/")[:data]}
699
712
  when :shared_inboxes
700
- query=url_query(nil)
713
+ query=option_url_query(nil)
701
714
  if query.nil?
702
715
  set_workspace_info
703
716
  query={'embed[]'=>'dropbox','workspace_id'=>@workspace_id,'aggregate_permissions_by_dropbox'=>true,'sort'=>'dropbox_name'}
704
717
  end
705
- return {:type=>:object_list,:data=>@api_aoc.read("dropbox_memberships",query)[:data],:fields=>['dropbox_id','dropbox.name']}
718
+ return {:type=>:object_list,:data=>@api_aoc.read('dropbox_memberships',query)[:data],:fields=>['dropbox_id','dropbox.name']}
706
719
  when :info
707
720
  command=self.options.get_next_command([ :show,:modify ])
708
721
  case command
709
722
  when :show
710
- return { :type=>:single_object, :data =>user_info }
723
+ return { :type=>:single_object, :data =>c_user_info }
711
724
  when :modify
712
- @api_aoc.update("users/#{user_info['id']}",self.options.get_next_argument('modified parameters (hash)'))
725
+ @api_aoc.update("users/#{c_user_info['id']}",self.options.get_next_argument('modified parameters (hash)'))
713
726
  return Main.result_status('modified')
714
727
  end
715
728
  end
@@ -722,7 +735,7 @@ module Aspera
722
735
  case command_pkg
723
736
  when :send
724
737
  package_creation=self.options.get_option(:value,:mandatory)
725
- raise CliBadArgument,"value must be hash, refer to doc" unless package_creation.is_a?(Hash)
738
+ raise CliBadArgument,'value must be hash, refer to doc' unless package_creation.is_a?(Hash)
726
739
 
727
740
  if !@url_token_data.nil?
728
741
  assert_public_link_types(['send_package_to_user','send_package_to_dropbox'])
@@ -789,26 +802,26 @@ module Aspera
789
802
  add_ts={'paths'=>[{'source'=>'.'}]}
790
803
  node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
791
804
  statuses=transfer_start(AoC::PACKAGES_APP,'receive',node_file,AoC.package_tags(package_info,'download').merge(add_ts))
792
- result_transfer.push({'package'=>package_id,'status'=>statuses.map{|i|i.to_s}.join(',')})
805
+ result_transfer.push({'package'=>package_id,Main::STATUS_FIELD=>statuses})
793
806
  # update skip list only if all transfer sessions completed
794
807
  if TransferAgent.session_status(statuses).eql?(:success)
795
808
  skip_ids_data.push(package_id)
796
809
  skip_ids_persistency.save unless skip_ids_persistency.nil?
797
810
  end
798
811
  end
799
- return {:type=>:object_list,:data=>result_transfer}
812
+ return Main.result_transfer_multiple(result_transfer)
800
813
  when :show
801
814
  package_id=self.options.get_next_argument('package ID')
802
815
  package_info=@api_aoc.read("packages/#{package_id}")[:data]
803
816
  return { :type=>:single_object, :data =>package_info }
804
817
  when :list
805
818
  # list all packages ('page'=>1,'per_page'=>10,)'sort'=>'-sent_at',
806
- packages=@api_aoc.read("packages",{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
819
+ packages=@api_aoc.read('packages',{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
807
820
  return {:type=>:object_list,:data=>packages,:fields=>['id','name','bytes_transferred']}
808
821
  when :delete
809
822
  list_or_one=self.options.get_option(:id,:mandatory)
810
823
  return do_bulk_operation(list_or_one,'deleted')do|id|
811
- raise "expecting String identifier" unless id.is_a?(String) or id.is_a?(Integer)
824
+ raise 'expecting String identifier' unless id.is_a?(String) or id.is_a?(Integer)
812
825
  @api_aoc.delete("packages/#{id}")[:data]
813
826
  end
814
827
  end
@@ -816,7 +829,6 @@ module Aspera
816
829
  # get workspace related information
817
830
  set_workspace_info
818
831
  set_home_node_file
819
- find_ak_secret(@home_node_file[:node_info]['access_key'],false)
820
832
  command_repo=self.options.get_next_command(NODE4_COMMANDS.clone.concat([:short_link]))
821
833
  case command_repo
822
834
  when *NODE4_COMMANDS; return execute_node_gen4_command(command_repo,@home_node_file)
@@ -829,7 +841,7 @@ module Aspera
829
841
  when 'private'
830
842
  value_option={'purpose'=>'shared_folder_auth_link'}
831
843
  when NilClass,Hash
832
- else raise "value must be either: public, private, Hash or nil"
844
+ else raise 'value must be either: public, private, Hash or nil'
833
845
  end
834
846
  create_params=nil
835
847
  node_file=nil
@@ -857,30 +869,33 @@ module Aspera
857
869
  }
858
870
  value_option['user_selected_name']=nil
859
871
  else
860
- raise "purpose must be one of: token_auth_redirection or shared_folder_auth_link"
872
+ raise 'purpose must be one of: token_auth_redirection or shared_folder_auth_link'
861
873
  end
862
874
  self.options.set_option(:value,value_option)
863
875
  end
864
876
  result=self.entity_action(@api_aoc,'short_links',nil,:id,'self')
865
877
  if result[:data].is_a?(Hash) and result[:data].has_key?('created_at') and result[:data]['resource_type'].eql?('UrlToken')
866
878
  node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
879
+ # TODO: access level as arg
880
+ access_levels=Aspera::Node::ACCESS_LEVELS #['delete','list','mkdir','preview','read','rename','write']
867
881
  perm_data={
868
- "file_id" =>node_file[:file_id],
869
- "access_type" =>"user",
870
- "access_id" =>result[:data]['resource_id'],
871
- "access_levels"=>["delete","list","mkdir","preview","read","rename","write"],
872
- "tags" =>{
873
- "url_token" =>true,
874
- "workspace_id" =>@workspace_id,
875
- "workspace_name" =>@workspace_name,
876
- "folder_name" =>"my folder",
877
- "created_by_name" =>user_info['name'],
878
- "created_by_email"=>user_info['email'],
879
- "access_key" =>node_file[:node_info]['access_key'],
880
- "node" =>node_file[:node_info]['host']
882
+ 'file_id' =>node_file[:file_id],
883
+ 'access_type' =>'user',
884
+ 'access_id' =>result[:data]['resource_id'],
885
+ 'access_levels'=>access_levels,
886
+ 'tags' =>{
887
+ 'url_token' =>true,
888
+ 'workspace_id' =>@workspace_id,
889
+ 'workspace_name' =>@workspace_name,
890
+ 'folder_name' =>'my folder',
891
+ 'created_by_name' =>c_user_info['name'],
892
+ 'created_by_email'=>c_user_info['email'],
893
+ 'access_key' =>node_file[:node_info]['access_key'],
894
+ 'node' =>node_file[:node_info]['host']
881
895
  }
882
896
  }
883
897
  node_api.create("permissions?file_id=#{node_file[:file_id]}",perm_data)
898
+ # TODO: event ?
884
899
  end
885
900
  return result
886
901
  end # files command
@@ -923,17 +938,17 @@ module Aspera
923
938
  when :admin
924
939
  return execute_admin_action
925
940
  when :servers
926
- self.format.display_status("Beta feature")
927
- server_api=Rest.new(base_url: 'https://eudemo.asperademo.com')
928
- require 'json'
929
- servers=JSON.parse(server_api.read('servers')[:data])
930
- return {:type=>:object_list,:data=>servers}
941
+ return {:type=>:object_list,:data=>Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
931
942
  else
932
943
  raise "internal error: #{command}"
933
944
  end # action
934
945
  raise RuntimeError, "internal error: command shall return"
935
946
  end
936
- end # Aspera
947
+
948
+ 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
949
+ private_constant :VAL_ALL,:NODE4_COMMANDS
950
+
951
+ end # AoC
937
952
  end # Plugins
938
953
  end # Cli
939
954
  end # Aspera
@@ -107,7 +107,7 @@ module Aspera
107
107
  :auth => {
108
108
  :type => :basic,
109
109
  :username => access_key_id,
110
- :password => self.config.get_secret(access_key_id)}})
110
+ :password => @agents[:secret].get_secret(access_key_id)}})
111
111
  command=self.options.get_next_command(Node::COMMON_ACTIONS)
112
112
  return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action(command)
113
113
  when :cluster
@@ -116,7 +116,7 @@ module Aspera
116
116
  :auth => {
117
117
  :type => :basic,
118
118
  :username => access_key_id,
119
- :password => self.config.get_secret(access_key_id)
119
+ :password => @agents[:secret].get_secret(access_key_id)
120
120
  }}
121
121
  api_ak_auth=Rest.new(rest_params)
122
122
  return {:type=>:single_object, :data=>api_ak_auth.read("servers")[:data]}