aspera-cli 4.2.0 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +749 -353
  3. data/docs/Makefile +4 -4
  4. data/docs/README.erb.md +743 -283
  5. data/docs/doc_tools.rb +58 -0
  6. data/docs/test_env.conf +9 -1
  7. data/examples/aoc.rb +14 -3
  8. data/examples/faspex4.rb +89 -0
  9. data/lib/aspera/aoc.rb +24 -22
  10. data/lib/aspera/cli/main.rb +48 -20
  11. data/lib/aspera/cli/plugin.rb +13 -6
  12. data/lib/aspera/cli/plugins/aoc.rb +117 -78
  13. data/lib/aspera/cli/plugins/config.rb +127 -80
  14. data/lib/aspera/cli/plugins/faspex.rb +112 -63
  15. data/lib/aspera/cli/plugins/faspex5.rb +29 -25
  16. data/lib/aspera/cli/plugins/node.rb +54 -25
  17. data/lib/aspera/cli/plugins/preview.rb +94 -68
  18. data/lib/aspera/cli/plugins/server.rb +16 -5
  19. data/lib/aspera/cli/transfer_agent.rb +92 -72
  20. data/lib/aspera/cli/version.rb +1 -1
  21. data/lib/aspera/command_line_builder.rb +48 -31
  22. data/lib/aspera/cos_node.rb +4 -3
  23. data/lib/aspera/fasp/http_gw.rb +47 -26
  24. data/lib/aspera/fasp/local.rb +31 -24
  25. data/lib/aspera/fasp/manager.rb +3 -0
  26. data/lib/aspera/fasp/node.rb +23 -1
  27. data/lib/aspera/fasp/parameters.rb +72 -89
  28. data/lib/aspera/fasp/parameters.yaml +531 -0
  29. data/lib/aspera/fasp/uri.rb +1 -1
  30. data/lib/aspera/faspex_gw.rb +10 -9
  31. data/lib/aspera/id_generator.rb +22 -0
  32. data/lib/aspera/node.rb +11 -3
  33. data/lib/aspera/oauth.rb +131 -135
  34. data/lib/aspera/persistency_action_once.rb +11 -7
  35. data/lib/aspera/persistency_folder.rb +6 -26
  36. data/lib/aspera/rest.rb +1 -1
  37. data/lib/aspera/sync.rb +40 -35
  38. data/lib/aspera/timer_limiter.rb +22 -0
  39. data/lib/aspera/web_auth.rb +105 -0
  40. metadata +22 -4
  41. data/docs/transfer_spec.html +0 -99
  42. data/lib/aspera/fasp/aoc.rb +0 -24
@@ -5,6 +5,7 @@ require 'aspera/cli/transfer_agent'
5
5
  require 'aspera/aoc'
6
6
  require 'aspera/node'
7
7
  require 'aspera/persistency_action_once'
8
+ require 'aspera/id_generator'
8
9
  require 'securerandom'
9
10
  require 'resolv'
10
11
  require 'date'
@@ -39,7 +40,6 @@ module Aspera
39
40
  self.options.add_opt_simple(:new_user_option,'new user creation option')
40
41
  self.options.add_opt_simple(:from_folder,'share to share source folder')
41
42
  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
43
  self.options.add_opt_boolean(:bulk,'bulk operation')
44
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)
@@ -83,19 +83,29 @@ module Aspera
83
83
  return self.transfer.start(*@api_aoc.tr_spec(app,direction,node_file,ts_add))
84
84
  end
85
85
 
86
- NODE4_COMMANDS=[ :browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node ]
86
+ NODE4_COMMANDS=[ :browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node, :node_info ]
87
87
 
88
88
  def execute_node_gen4_command(command_repo,top_node_file)
89
89
  case command_repo
90
90
  when :bearer_token_node
91
91
  thepath=self.options.get_next_argument('path')
92
92
  node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
93
- node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
93
+ node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER, use_secret: false)
94
94
  return Main.result_status(node_api.oauth_token)
95
+ when :node_info
96
+ thepath=self.options.get_next_argument('path')
97
+ node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
98
+ node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER, use_secret: false)
99
+ return {:type=>:single_object,:data=>{
100
+ url: node_file[:node_info]['url'],
101
+ username: node_file[:node_info]['access_key'],
102
+ password: node_api.oauth_token,
103
+ root_id: node_file[:file_id]
104
+ }}
95
105
  when :browse
96
106
  thepath=self.options.get_next_argument('path')
97
107
  node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
98
- node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
108
+ node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
99
109
  file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
100
110
  if file_info['type'].eql?('folder')
101
111
  result=node_api.read("files/#{node_file[:file_id]}/files",self.options.get_option(:value,:optional))
@@ -115,14 +125,14 @@ module Aspera
115
125
  containing_folder_path = thepath.split(AoC::PATH_SEPARATOR)
116
126
  new_folder=containing_folder_path.pop
117
127
  node_file = @api_aoc.resolve_node_file(top_node_file,containing_folder_path.join(AoC::PATH_SEPARATOR))
118
- node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
128
+ node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
119
129
  result=node_api.create("files/#{node_file[:file_id]}/files",{:name=>new_folder,:type=>:folder})[:data]
120
130
  return Main.result_status("created: #{result['name']} (id=#{result['id']})")
121
131
  when :rename
122
132
  thepath=self.options.get_next_argument('source path')
123
133
  newname=self.options.get_next_argument('new name')
124
134
  node_file = @api_aoc.resolve_node_file(top_node_file,thepath)
125
- node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
135
+ node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
126
136
  result=node_api.update("files/#{node_file[:file_id]}",{:name=>newname})[:data]
127
137
  return Main.result_status("renamed #{thepath} to #{newname}")
128
138
  when :delete
@@ -130,7 +140,7 @@ module Aspera
130
140
  return do_bulk_operation(thepath,'deleted','path') do |l_path|
131
141
  raise "expecting String (path), got #{l_path.class.name} (#{l_path})" unless l_path.is_a?(String)
132
142
  node_file = @api_aoc.resolve_node_file(top_node_file,l_path)
133
- node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
143
+ node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
134
144
  result=node_api.delete("files/#{node_file[:file_id]}")[:data]
135
145
  {'path'=>l_path}
136
146
  end
@@ -153,7 +163,7 @@ module Aspera
153
163
  client_node_file = @api_aoc.resolve_node_file(client_home_node_file,client_folder)
154
164
  server_node_file = @api_aoc.resolve_node_file(server_home_node_file,server_folder)
155
165
  # force node as transfer agent
156
- @agents[:transfer].set_agent_instance(Fasp::Node.new(@api_aoc.get_node_api(client_node_file[:node_info],AoC::SCOPE_NODE_USER)))
166
+ @agents[:transfer].set_agent_instance(Fasp::Node.new(@api_aoc.get_node_api(client_node_file[:node_info],scope: AoC::SCOPE_NODE_USER)))
157
167
  # additional node to node TS info
158
168
  add_ts={
159
169
  'remote_access_key' => server_node_file[:node_info]['access_key'],
@@ -191,14 +201,14 @@ module Aspera
191
201
  raise CliBadArgument,'one file at a time only in HTTP mode' if source_paths.length > 1
192
202
  file_name = source_paths.first['source']
193
203
  node_file = @api_aoc.resolve_node_file(top_node_file,File.join(source_folder,file_name))
194
- node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
204
+ node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
195
205
  node_api.call({:operation=>'GET',:subpath=>"files/#{node_file[:file_id]}/content",:save_to_file=>File.join(self.transfer.destination_folder('receive'),file_name)})
196
206
  return Main.result_status("downloaded: #{file_name}")
197
207
  when :v3
198
- # Note: other "common" actions are unauthorized with user scope
208
+ # Note: other common actions are unauthorized with user scope
199
209
  command_legacy=self.options.get_next_command(Node::SIMPLE_ACTIONS)
200
210
  # TODO: shall we support all methods here ? what if there is a link ?
201
- node_api=@api_aoc.get_node_api(top_node_file[:node_info],AoC::SCOPE_NODE_USER)
211
+ node_api=@api_aoc.get_node_api(top_node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
202
212
  return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: node_api)).execute_action(command_legacy)
203
213
  when :file
204
214
  file_path=self.options.get_option(:path,:optional)
@@ -207,21 +217,21 @@ module Aspera
207
217
  else
208
218
  {node_info: top_node_file[:node_info],file_id: self.options.get_option(:id,:mandatory)}
209
219
  end
210
- node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
220
+ node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
211
221
  command_node_file=self.options.get_next_command([:show,:permission,:modify])
212
222
  case command_node_file
213
223
  when :show
214
224
  items=node_api.read("files/#{node_file[:file_id]}")[:data]
215
225
  return {:type=>:single_object,:data=>items}
216
226
  when :modify
217
- update_param=self.options.get_next_argument("update data (Hash)")
227
+ update_param=self.options.get_next_argument('update data (Hash)')
218
228
  res=node_api.update("files/#{node_file[:file_id]}",update_param)[:data]
219
229
  return {:type=>:single_object,:data=>res}
220
230
  when :permission
221
231
  command_perm=self.options.get_next_command([:list,:create])
222
232
  case command_perm
223
233
  when :list
224
- # generic options : TODO: as arg ?
234
+ # generic options : TODO: as arg ? option_url_query
225
235
  list_options||={'include'=>['[]','access_level','permission_count']}
226
236
  # special value: ALL will show all permissions
227
237
  if !VAL_ALL.eql?(node_file[:file_id])
@@ -229,11 +239,10 @@ module Aspera
229
239
  list_options['file_id']=node_file[:file_id]
230
240
  list_options['inherited']||=false
231
241
  end
232
- #option_url_query
233
242
  items=node_api.read('permissions',list_options)[:data]
234
243
  return {:type=>:object_list,:data=>items}
235
244
  when :create
236
- #create_param=self.options.get_next_argument("creation data (Hash)")
245
+ #create_param=self.options.get_next_argument('creation data (Hash)')
237
246
  set_workspace_info
238
247
  access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
239
248
  node_file[:node_info]
@@ -256,14 +265,14 @@ module Aspera
256
265
  return {:type=>:single_object,:data=>item}
257
266
  else raise "internal error:shall not reach here (#{command_perm})"
258
267
  end
259
- raise "internal error:shall not reach here"
268
+ raise 'internal error:shall not reach here'
260
269
  else raise "internal error:shall not reach here (#{command_node_file})"
261
270
  end
262
- raise "internal error:shall not reach here"
271
+ raise 'internal error:shall not reach here'
263
272
  when :permissions
264
273
 
265
274
  end # command_repo
266
- raise "ERR"
275
+ raise 'ERR'
267
276
  end # execute_node_gen4_command
268
277
 
269
278
  # build constructor option list for AoC based on options of CLI
@@ -294,15 +303,15 @@ module Aspera
294
303
 
295
304
  ws_name=self.options.get_option(:workspace,:optional)
296
305
  if ws_name.nil?
297
- Log.log.debug("using default workspace".green)
306
+ Log.log.debug('using default workspace'.green)
298
307
  if @default_workspace_id.eql?(nil)
299
- raise CliError,"no default workspace defined for user, please specify workspace"
308
+ raise CliError,'no default workspace defined for user, please specify workspace'
300
309
  end
301
310
  # get default workspace
302
311
  @workspace_id=@default_workspace_id
303
312
  else
304
313
  # lookup another workspace
305
- wss=@api_aoc.read("workspaces",{'q'=>ws_name})[:data]
314
+ wss=@api_aoc.read('workspaces',{'q'=>ws_name})[:data]
306
315
  wss=wss.select { |i| i['name'].eql?(ws_name) }
307
316
  case wss.length
308
317
  when 0
@@ -310,14 +319,14 @@ module Aspera
310
319
  when 1
311
320
  @workspace_id=wss.first['id']
312
321
  else
313
- raise "unexpected case"
322
+ raise 'unexpected case'
314
323
  end
315
324
  end
316
325
  @workspace_data=@api_aoc.read("workspaces/#{@workspace_id}")[:data]
317
326
  Log.log.debug("workspace_id=#{@workspace_id},@workspace_data=#{@workspace_data}".red)
318
327
 
319
328
  @workspace_name||=@workspace_data['name']
320
- Log.log.info("current workspace is "+@workspace_name.red)
329
+ Log.log.info('current workspace is '+@workspace_name.red)
321
330
 
322
331
  # display workspace
323
332
  self.format.display_status("Current Workspace: #{@workspace_name.red}#{@workspace_id == @default_workspace_id ? ' (default)' : ''}")
@@ -333,7 +342,7 @@ module Aspera
333
342
  end
334
343
  home_node_id||=@workspace_data['home_node_id']||@workspace_data['node_id']
335
344
  home_file_id||=@workspace_data['home_file_id']
336
- raise "node_id must be defined" if home_node_id.to_s.empty?
345
+ raise 'node_id must be defined' if home_node_id.to_s.empty?
337
346
  @home_node_file={
338
347
  node_info: @api_aoc.read("nodes/#{home_node_id}")[:data],
339
348
  file_id: home_file_id
@@ -345,7 +354,7 @@ module Aspera
345
354
 
346
355
  def do_bulk_operation(ids_or_one,success_msg,id_result='id',&do_action)
347
356
  ids_or_one=[ids_or_one] unless self.options.get_option(:bulk)
348
- raise "expecting Array" unless ids_or_one.is_a?(Array)
357
+ raise 'expecting Array' unless ids_or_one.is_a?(Array)
349
358
  result_list=[]
350
359
  ids_or_one.each do |id|
351
360
  one={id_result=>id}
@@ -401,7 +410,8 @@ module Aspera
401
410
 
402
411
  # private
403
412
  def option_url_query(default)
404
- query=self.options.get_option(:query,:optional)||default
413
+ query=self.options.get_option(:query,:optional)
414
+ query=default if query.nil?
405
415
  Log.log.debug("Query=#{query}".bg_red)
406
416
  begin
407
417
  # check it is suitable
@@ -418,6 +428,37 @@ module Aspera
418
428
  end
419
429
  end
420
430
 
431
+ # Call @api_aoc.read with same parameters, but use paging if necessary to get all results
432
+ def read_with_paging(resource_class_path,base_query)
433
+ raise "Query must be Hash" unless base_query.is_a?(Hash)
434
+ # set default large page if user does not specify own parameters. AoC Caps to 1000 anyway
435
+ base_query['per_page']=1000 unless base_query.has_key?('per_page')
436
+ max_items=base_query[MAX_ITEMS]
437
+ base_query.delete(MAX_ITEMS)
438
+ max_pages=base_query[MAX_PAGES]
439
+ base_query.delete(MAX_PAGES)
440
+ item_list=[]
441
+ total_count=nil
442
+ current_page=base_query['page']
443
+ current_page=1 if current_page.nil?
444
+ page_count=0
445
+ loop do
446
+ query=base_query.clone
447
+ query['page']=current_page
448
+ result=@api_aoc.read(resource_class_path,query)
449
+ total_count=result[:http]['X-Total-Count']
450
+ page_count+=1
451
+ current_page+=1
452
+ add_items=result[:data]
453
+ break if add_items.empty?
454
+ # append new items to full list
455
+ item_list += add_items
456
+ break if !max_pages.nil? and page_count > max_pages
457
+ break if !max_items.nil? and item_list.count > max_items
458
+ end
459
+ return item_list,total_count
460
+ end
461
+
421
462
  def execute_admin_action
422
463
  @api_aoc.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
423
464
  command_admin=self.options.get_next_command([ :ats, :resource, :usage_reports, :analytics, :subscription, :auth_providers ])
@@ -507,18 +548,18 @@ module Aspera
507
548
  when 'organizations'; c_user_info['organization_id']
508
549
  when 'users'; c_user_info['id']
509
550
  when 'nodes'; c_user_info['id']
510
- else raise "organizations or users for option --name"
551
+ else raise 'organizations or users for option --name'
511
552
  end
512
553
  #
513
554
  filter=self.options.get_option(:query,:optional) || {}
514
- raise "query must be Hash" unless filter.is_a?(Hash)
555
+ raise 'query must be Hash' unless filter.is_a?(Hash)
515
556
  filter['limit']||=100
516
557
  if self.options.get_option(:once_only,:mandatory)
517
558
  saved_date=[]
518
559
  startdate_persistency=PersistencyActionOnce.new(
519
560
  manager: @agents[:persistency],
520
561
  data: saved_date,
521
- ids: ['aoc_ana_date',self.options.get_option(:url,:mandatory),@workspace_name].push(filter_resource,filter_id))
562
+ ids: IdGenerator.from_list(['aoc_ana_date',self.options.get_option(:url,:mandatory),@workspace_name].push(filter_resource,filter_id)))
522
563
  start_datetime=saved_date.first
523
564
  stop_datetime=Time.now.utc.strftime('%FT%T.%LZ')
524
565
  #Log.log().error("start: #{start_datetime}")
@@ -527,30 +568,23 @@ module Aspera
527
568
  filter['start_time'] = start_datetime unless start_datetime.nil?
528
569
  filter['stop_time'] = stop_datetime
529
570
  end
530
- notification=self.options.get_option(:notify,:optional)
531
571
  events=analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",option_url_query(filter))[:data][event_type]
532
572
  startdate_persistency.save unless startdate_persistency.nil?
533
- if !notification.nil?
534
- require 'erb'
535
- events.each do |transfer|
536
- email_to_send={}
537
- notification.each do |k,v|
538
- email_to_send[k.to_sym]=ERB.new(v).result(binding)
539
- end
540
- Log.log().error("send email: #{email_to_send}")
541
- self.config.send_email(email_to_send)
573
+ if !self.options.get_option(:notif_to,:optional).nil?
574
+ events.each do |tr_event|
575
+ self.config.send_email_template({ev: tr_event})
542
576
  end
543
577
  end
544
578
  return {:type=>:object_list,:data=>events}
545
579
  end
546
580
  when :resource
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])
581
+ resource_type=self.options.get_next_argument('resource',[:self,:organization,:user,:group,:client,:contact,:dropbox,:node,:operation,:package,:saml_configuration, :workspace, :dropbox_membership,:short_link,:workspace_membership,:application,:client_registration_token,:client_access_key,:kms_profile])
548
582
  # get path on API
549
583
  resource_class_path=case resource_type
550
584
  when :self,:organization
551
- "#{resource_type}"
552
- when :apps_new
553
- "admin/#{resource_type}"
585
+ resource_type
586
+ when :application
587
+ 'admin/apps_new'
554
588
  when :dropbox
555
589
  resource_type.to_s+'es'
556
590
  when :client_registration_token,:client_access_key
@@ -579,13 +613,13 @@ module Aspera
579
613
  res_id=@home_node_file[:node_info]['id']
580
614
  end
581
615
  if !res_name.nil?
582
- Log.log.warn("name overrides id") unless res_id.nil?
616
+ Log.log.warn('name overrides id') unless res_id.nil?
583
617
  matching=@api_aoc.read(resource_class_path,{:q=>res_name})[:data]
584
- raise CliError,"no resource match name" if matching.empty?
618
+ raise CliError,'no resource match name' if matching.empty?
585
619
  raise CliError,"several resources match name (#{matching.join(',')})" unless matching.length.eql?(1)
586
620
  res_id=matching.first['id']
587
621
  end
588
- raise CliBadArgument,"provide either id or name" if res_id.nil?
622
+ raise CliBadArgument,'provide either id or name' if res_id.nil?
589
623
  resource_instance_path="#{resource_class_path}/#{res_id}"
590
624
  end
591
625
  resource_instance_path=resource_class_path if singleton_object
@@ -595,26 +629,29 @@ module Aspera
595
629
  id_result='token' if resource_class_path.eql?('admin/client_registration_tokens')
596
630
  # TODO: report inconsistency: creation url is !=, and does not return id.
597
631
  resource_class_path='admin/client_registration/token' if resource_class_path.eql?('admin/client_registration_tokens')
598
- list_or_one=self.options.get_next_argument("creation data (Hash)")
632
+ list_or_one=self.options.get_next_argument('creation data (Hash)')
599
633
  return do_bulk_operation(list_or_one,'created',id_result)do|params|
600
- raise "expecting Hash" unless params.is_a?(Hash)
634
+ raise 'expecting Hash' unless params.is_a?(Hash)
601
635
  @api_aoc.create(resource_class_path,params)[:data]
602
636
  end
603
637
  when :list
604
- default_fields=['id','name']
605
- list_query=nil
638
+ default_fields=['id']
639
+ default_query={}
606
640
  case resource_type
607
- when :node; default_fields.push('host','access_key')
641
+ when :application; default_query={:organization_apps=>true};default_fields.push('app_type','app_name','available','direct_authorizations_allowed','workspace_authorizations_allowed')
642
+ when :client,:client_access_key,:dropbox,:group,:package,:saml_configuration,:workspace; default_fields.push('name')
643
+ when :client_registration_token; default_fields.push('value','data.client_subject_scopes','created_at')
644
+ when :contact; default_fields=['email','name','source_id','source_type']
645
+ when :node; default_fields.push('name','host','access_key')
608
646
  when :operation; default_fields=nil
609
- when :contact; default_fields=["email","name","source_id","source_type"]
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']
647
+ when :short_link; default_fields.push('short_url','data.url_token_data.purpose')
648
+ when :user; default_fields.push('name','email')
612
649
  end
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)
650
+ item_list,total_count=read_with_paging(resource_class_path,option_url_query(default_query))
651
+ count_msg="Items: #{item_list.length}/#{total_count}"
652
+ count_msg=count_msg.bg_red unless item_list.length.eql?(total_count.to_i)
616
653
  self.format.display_status(count_msg)
617
- return {:type=>:object_list,:data=>result[:data],:fields=>default_fields}
654
+ return {:type=>:object_list,:data=>item_list,:fields=>default_fields}
618
655
  when :show
619
656
  object=@api_aoc.read(resource_instance_path)[:data]
620
657
  fields=object.keys.select{|k|!k.eql?('certificate')}
@@ -644,8 +681,8 @@ module Aspera
644
681
  when :shared_folders
645
682
  read_params = case resource_type
646
683
  when :workspace;{'access_id'=>"ASPERA_ACCESS_KEY_ADMIN_WS_#{res_id}",'access_type'=>'user'}
647
- when :node;{'include'=>['[]','access_level','permission_count'],'created_by_id'=>"ASPERA_ACCESS_KEY_ADMIN"}
648
- else raise "error"
684
+ when :node;{'include'=>['[]','access_level','permission_count'],'created_by_id'=>'ASPERA_ACCESS_KEY_ADMIN'}
685
+ else raise 'error'
649
686
  end
650
687
  res_data=@api_aoc.read("#{resource_class_path}/#{res_id}/permissions",read_params)[:data]
651
688
  fields=case resource_type
@@ -661,7 +698,7 @@ module Aspera
661
698
  res_data=@api_aoc.read(resource_instance_path)[:data]
662
699
  node_file = @api_aoc.resolve_node_file({node_info: res_data, file_id: ak_data['root_file_id']},folder_path)
663
700
 
664
- #node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
701
+ #node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
665
702
  #file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
666
703
 
667
704
  access_id="ASPERA_ACCESS_KEY_ADMIN_WS_#{@workspace_id}"
@@ -685,7 +722,7 @@ module Aspera
685
722
  create_data.deep_merge!(user_create_data)
686
723
  Log.dump(:data,create_data)
687
724
  raise :ERROR
688
- else raise "unknown command"
725
+ else raise 'unknown command'
689
726
  end
690
727
  when :usage_reports
691
728
  return {:type=>:object_list,:data=>@api_aoc.read('usage_reports',{:workspace_id=>@workspace_id})[:data]}
@@ -716,7 +753,7 @@ module Aspera
716
753
  when :workspaces
717
754
  return {:type=>:object_list,:data=>@api_aoc.read('workspaces')[:data],:fields=>['id','name']}
718
755
  # when :settings
719
- # return {:type=>:object_list,:data=>@api_aoc.read("client_settings/")[:data]}
756
+ # return {:type=>:object_list,:data=>@api_aoc.read('client_settings/')[:data]}
720
757
  when :shared_inboxes
721
758
  query=option_url_query(nil)
722
759
  if query.nil?
@@ -761,7 +798,7 @@ module Aspera
761
798
  resolve_package_recipients(package_creation,'recipients')
762
799
  resolve_package_recipients(package_creation,'bcc_recipients')
763
800
 
764
- # create a new package with one file
801
+ # create a new package container
765
802
  package_info=@api_aoc.create('packages',package_creation)[:data]
766
803
 
767
804
  # get node information for the node on which package must be created
@@ -772,7 +809,7 @@ module Aspera
772
809
 
773
810
  # execute transfer
774
811
  node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
775
- # raise esception if at least one error
812
+ # raise exception if at least one error
776
813
  Main.result_transfer(transfer_start(AoC::PACKAGES_APP,'send',node_file,AoC.package_tags(package_info,'upload')))
777
814
  # return all info on package
778
815
  return { :type=>:single_object, :data =>package_info}
@@ -789,7 +826,7 @@ module Aspera
789
826
  skip_ids_persistency=PersistencyActionOnce.new(
790
827
  manager: @agents[:persistency],
791
828
  data: skip_ids_data,
792
- ids: ['aoc_recv',self.options.get_option(:url,:mandatory),@workspace_id].push(*@persist_ids))
829
+ id: IdGenerator.from_list(['aoc_recv',self.options.get_option(:url,:mandatory),@workspace_id].push(*@persist_ids)))
793
830
  end
794
831
  if ids_to_download.eql?(VAL_ALL)
795
832
  # get list of packages in inbox
@@ -810,21 +847,23 @@ module Aspera
810
847
  add_ts={'paths'=>[{'source'=>'.'}]}
811
848
  node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
812
849
  statuses=transfer_start(AoC::PACKAGES_APP,'receive',node_file,AoC.package_tags(package_info,'download').merge(add_ts))
813
- result_transfer.push({'package'=>package_id,'status'=>statuses.map{|i|i.to_s}.join(',')})
850
+ result_transfer.push({'package'=>package_id,Main::STATUS_FIELD=>statuses})
814
851
  # update skip list only if all transfer sessions completed
815
852
  if TransferAgent.session_status(statuses).eql?(:success)
816
853
  skip_ids_data.push(package_id)
817
854
  skip_ids_persistency.save unless skip_ids_persistency.nil?
818
855
  end
819
856
  end
820
- return {:type=>:object_list,:data=>result_transfer}
857
+ return Main.result_transfer_multiple(result_transfer)
821
858
  when :show
822
859
  package_id=self.options.get_next_argument('package ID')
823
860
  package_info=@api_aoc.read("packages/#{package_id}")[:data]
824
861
  return { :type=>:single_object, :data =>package_info }
825
862
  when :list
826
- # list all packages ('page'=>1,'per_page'=>10,)'sort'=>'-sent_at',
827
- packages=@api_aoc.read('packages',{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
863
+ query=option_url_query({'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true})
864
+ raise 'option must be Hash' unless query.is_a?(Hash)
865
+ query['workspace_id']||=@workspace_id
866
+ packages=@api_aoc.read('packages',query)[:data]
828
867
  return {:type=>:object_list,:data=>packages,:fields=>['id','name','bytes_transferred']}
829
868
  when :delete
830
869
  list_or_one=self.options.get_option(:id,:mandatory)
@@ -883,7 +922,7 @@ module Aspera
883
922
  end
884
923
  result=self.entity_action(@api_aoc,'short_links',nil,:id,'self')
885
924
  if result[:data].is_a?(Hash) and result[:data].has_key?('created_at') and result[:data]['resource_type'].eql?('UrlToken')
886
- node_api=@api_aoc.get_node_api(node_file[:node_info],AoC::SCOPE_NODE_USER)
925
+ node_api=@api_aoc.get_node_api(node_file[:node_info],scope: AoC::SCOPE_NODE_USER)
887
926
  # TODO: access level as arg
888
927
  access_levels=Aspera::Node::ACCESS_LEVELS #['delete','list','mkdir','preview','read','rename','write']
889
928
  perm_data={
@@ -907,9 +946,9 @@ module Aspera
907
946
  end
908
947
  return result
909
948
  end # files command
910
- throw "Error: shall not reach this line"
949
+ throw 'Error: shall not reach this line'
911
950
  when :automation
912
- Log.log.warn("BETA: work under progress")
951
+ Log.log.warn('BETA: work under progress')
913
952
  # automation api is not in the same place
914
953
  automation_rest_params=@api_aoc.params.clone
915
954
  automation_rest_params[:base_url].gsub!('/api/','/automation/')
@@ -932,9 +971,9 @@ module Aspera
932
971
  wf_command=self.options.get_next_command([:list,:create,:show])
933
972
  wf_id=self.options.get_option(:id,:mandatory)
934
973
  step=automation_api.create('steps',{'workflow_id'=>wf_id})[:data]
935
- automation_api.update("workflows/#{wf_id}",{'step_order'=>[step["id"]]})
936
- action=automation_api.create('actions',{'step_id'=>step["id"],'type'=>'manual'})[:data]
937
- automation_api.update("steps/#{step["id"]}",{'action_order'=>[action["id"]]})
974
+ automation_api.update("workflows/#{wf_id}",{'step_order'=>[step['id']]})
975
+ action=automation_api.create('actions',{'step_id'=>step['id'],'type'=>'manual'})[:data]
976
+ automation_api.update("steps/#{step['id']}",{'action_order'=>[action['id']]})
938
977
  wf=automation_api.read("workflows/#{wf_id}")[:data]
939
978
  return {:type=>:single_object,:data=>wf}
940
979
  end
@@ -950,7 +989,7 @@ module Aspera
950
989
  else
951
990
  raise "internal error: #{command}"
952
991
  end # action
953
- raise RuntimeError, "internal error: command shall return"
992
+ raise RuntimeError, 'internal error: command shall return'
954
993
  end
955
994
 
956
995
  private :c_user_info,:aoc_params,:set_workspace_info,:set_home_node_file,:do_bulk_operation,:resolve_package_recipients,:option_url_query,:assert_public_link_types,:execute_admin_action