aspera-cli 4.10.0 → 4.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/BUGS.md +20 -0
  4. data/CHANGELOG.md +509 -0
  5. data/CONTRIBUTING.md +118 -0
  6. data/README.md +621 -378
  7. data/bin/ascli +4 -4
  8. data/bin/asession +11 -11
  9. data/docs/test_env.conf +28 -19
  10. data/examples/aoc.rb +4 -4
  11. data/examples/dascli +11 -9
  12. data/examples/faspex4.rb +8 -8
  13. data/examples/node.rb +11 -11
  14. data/examples/server.rb +9 -9
  15. data/lib/aspera/aoc.rb +273 -266
  16. data/lib/aspera/ascmd.rb +56 -54
  17. data/lib/aspera/ats_api.rb +4 -4
  18. data/lib/aspera/cli/basic_auth_plugin.rb +15 -12
  19. data/lib/aspera/cli/extended_value.rb +5 -5
  20. data/lib/aspera/cli/formater.rb +64 -64
  21. data/lib/aspera/cli/listener/line_dump.rb +1 -1
  22. data/lib/aspera/cli/listener/logger.rb +1 -1
  23. data/lib/aspera/cli/listener/progress.rb +5 -6
  24. data/lib/aspera/cli/listener/progress_multi.rb +14 -19
  25. data/lib/aspera/cli/main.rb +66 -67
  26. data/lib/aspera/cli/manager.rb +110 -110
  27. data/lib/aspera/cli/plugin.rb +54 -37
  28. data/lib/aspera/cli/plugins/alee.rb +4 -4
  29. data/lib/aspera/cli/plugins/aoc.rb +308 -669
  30. data/lib/aspera/cli/plugins/ats.rb +44 -46
  31. data/lib/aspera/cli/plugins/bss.rb +10 -10
  32. data/lib/aspera/cli/plugins/config.rb +447 -344
  33. data/lib/aspera/cli/plugins/console.rb +12 -12
  34. data/lib/aspera/cli/plugins/cos.rb +18 -20
  35. data/lib/aspera/cli/plugins/faspex.rb +110 -112
  36. data/lib/aspera/cli/plugins/faspex5.rb +67 -46
  37. data/lib/aspera/cli/plugins/node.rb +364 -288
  38. data/lib/aspera/cli/plugins/orchestrator.rb +46 -46
  39. data/lib/aspera/cli/plugins/preview.rb +122 -114
  40. data/lib/aspera/cli/plugins/server.rb +137 -83
  41. data/lib/aspera/cli/plugins/shares.rb +30 -29
  42. data/lib/aspera/cli/plugins/sync.rb +13 -33
  43. data/lib/aspera/cli/transfer_agent.rb +57 -57
  44. data/lib/aspera/cli/version.rb +1 -1
  45. data/lib/aspera/colors.rb +3 -3
  46. data/lib/aspera/command_line_builder.rb +27 -27
  47. data/lib/aspera/cos_node.rb +22 -20
  48. data/lib/aspera/data_repository.rb +1 -1
  49. data/lib/aspera/environment.rb +30 -28
  50. data/lib/aspera/fasp/agent_base.rb +15 -15
  51. data/lib/aspera/fasp/agent_connect.rb +23 -21
  52. data/lib/aspera/fasp/agent_direct.rb +65 -67
  53. data/lib/aspera/fasp/agent_httpgw.rb +72 -68
  54. data/lib/aspera/fasp/agent_node.rb +23 -21
  55. data/lib/aspera/fasp/agent_trsdk.rb +20 -20
  56. data/lib/aspera/fasp/error.rb +3 -2
  57. data/lib/aspera/fasp/error_info.rb +11 -8
  58. data/lib/aspera/fasp/installation.rb +78 -78
  59. data/lib/aspera/fasp/listener.rb +1 -1
  60. data/lib/aspera/fasp/parameters.rb +75 -72
  61. data/lib/aspera/fasp/parameters.yaml +2 -2
  62. data/lib/aspera/fasp/resume_policy.rb +8 -8
  63. data/lib/aspera/fasp/transfer_spec.rb +35 -2
  64. data/lib/aspera/fasp/uri.rb +7 -7
  65. data/lib/aspera/faspex_gw.rb +7 -5
  66. data/lib/aspera/hash_ext.rb +3 -3
  67. data/lib/aspera/id_generator.rb +5 -5
  68. data/lib/aspera/keychain/encrypted_hash.rb +23 -28
  69. data/lib/aspera/keychain/macos_security.rb +21 -20
  70. data/lib/aspera/log.rb +7 -7
  71. data/lib/aspera/nagios.rb +19 -18
  72. data/lib/aspera/node.rb +209 -35
  73. data/lib/aspera/oauth.rb +37 -36
  74. data/lib/aspera/open_application.rb +19 -11
  75. data/lib/aspera/persistency_action_once.rb +4 -4
  76. data/lib/aspera/persistency_folder.rb +13 -13
  77. data/lib/aspera/preview/file_types.rb +8 -8
  78. data/lib/aspera/preview/generator.rb +67 -67
  79. data/lib/aspera/preview/utils.rb +27 -27
  80. data/lib/aspera/proxy_auto_config.js +41 -41
  81. data/lib/aspera/proxy_auto_config.rb +16 -16
  82. data/lib/aspera/rest.rb +56 -60
  83. data/lib/aspera/rest_call_error.rb +2 -1
  84. data/lib/aspera/rest_error_analyzer.rb +18 -17
  85. data/lib/aspera/rest_errors_aspera.rb +16 -16
  86. data/lib/aspera/secret_hider.rb +15 -13
  87. data/lib/aspera/ssh.rb +11 -10
  88. data/lib/aspera/sync.rb +158 -44
  89. data/lib/aspera/temp_file_manager.rb +2 -2
  90. data/lib/aspera/uri_reader.rb +4 -4
  91. data/lib/aspera/web_auth.rb +14 -13
  92. data.tar.gz.sig +0 -0
  93. metadata +8 -5
  94. metadata.gz.sig +0 -0
@@ -18,23 +18,21 @@ require 'cgi'
18
18
  module Aspera
19
19
  module Cli
20
20
  module Plugins
21
- class Faspex < BasicAuthPlugin
21
+ class Faspex < Aspera::Cli::BasicAuthPlugin
22
22
  # required hash key for source in config
23
23
  KEY_NODE = 'node' # value must be hash with url, username, password
24
24
  KEY_PATH = 'path' # value must be same sub-path as in Faspex's node
25
- VAL_ALL = 'ALL'
26
25
  # added field in result that identifies the package
27
26
  PACKAGE_MATCH_FIELD = 'package_id'
28
27
  # list of supported atoms
29
28
  ATOM_MAILBOXES = %i[inbox archive sent].freeze
30
29
  # allowed parameters for inbox.atom
31
30
  ATOM_PARAMS = %w[page count startIndex].freeze
32
- # with special parameters (from Plugin class) : max and pmax
33
- ATOM_EXT_PARAMS = ATOM_PARAMS + [MAX_ITEMS, MAX_PAGES]
31
+ # with special parameters (from Plugin class) : max and pmax (from Plugin)
32
+ ATOM_EXT_PARAMS = [MAX_ITEMS, MAX_PAGES].concat(ATOM_PARAMS).freeze
34
33
  # sub path in url for public link delivery
35
34
  PUB_LINK_EXTERNAL_MATCH = 'external_deliveries/'
36
- private_constant :KEY_NODE,:KEY_PATH,:VAL_ALL,:PACKAGE_MATCH_FIELD,:ATOM_MAILBOXES,:ATOM_PARAMS,
37
- :ATOM_EXT_PARAMS,:PUB_LINK_EXTERNAL_MATCH
35
+ private_constant(*%i[KEY_NODE KEY_PATH PACKAGE_MATCH_FIELD ATOM_MAILBOXES ATOM_PARAMS ATOM_EXT_PARAMS PUB_LINK_EXTERNAL_MATCH])
38
36
 
39
37
  class << self
40
38
  def detect(base_url)
@@ -56,45 +54,45 @@ module Aspera
56
54
  # extract elements from anonymous faspex link
57
55
  def get_link_data(publink)
58
56
  publink_uri = URI.parse(publink)
59
- raise CliBadArgument, 'Public link does not match Faspex format' unless (m = publink_uri.path.match(/^(.*)\/(external.*)$/))
57
+ raise CliBadArgument, 'Public link does not match Faspex format' unless (m = publink_uri.path.match(%r{^(.*)/(external.*)$}))
60
58
  base = m[1]
61
59
  subpath = m[2]
62
60
  port_add = publink_uri.port.eql?(publink_uri.default_port) ? '' : ":#{publink_uri.port}"
63
61
  result = {
64
62
  base_url: "#{publink_uri.scheme}://#{publink_uri.host}#{port_add}#{base}",
65
63
  subpath: subpath,
66
- query: URI.decode_www_form(publink_uri.query).each_with_object({}){|v,h|h[v.first] = v.last;}
64
+ query: URI.decode_www_form(publink_uri.query).each_with_object({}){|v, h|h[v.first] = v.last; }
67
65
  }
68
- Log.dump('publink',result)
66
+ Log.dump('publink', result)
69
67
  return result
70
68
  end
71
69
 
72
70
  # get faspe: URI from entry in xml, and fix problems..
73
71
  def get_fasp_uri_from_entry(entry, raise_no_link: true)
74
- unless entry.has_key?('link')
72
+ unless entry.key?('link')
75
73
  raise CliBadArgument, 'package has no link (deleted?)' if raise_no_link
76
74
  return nil
77
75
  end
78
76
  result = entry['link'].find{|e| e['rel'].eql?('package')}['href']
79
77
  # tags in the end of URL is not well % encoded... there are "=" that should be %3D
80
78
  # TODO: enter ticket to Faspex ?
81
- ###XXif m=result.match(/(=+)$/);result.gsub!(/=+$/,"#{"%3D"*m[1].length}");end
79
+ # ##XXif m=result.match(/(=+)$/);result.gsub!(/=+$/,"#{"%3D"*m[1].length}");end
82
80
  return result
83
81
  end
84
82
 
85
83
  def textify_package_list(table_data)
86
84
  return table_data.map do |e|
87
- e.keys.each {|k| e[k] = e[k].first if e[k].is_a?(Array) && (e[k].length == 1)}
88
- e['items'] = e.has_key?('link') ? e['link'].length : 0
85
+ e.each_key {|k| e[k] = e[k].first if e[k].is_a?(Array) && (e[k].length == 1)}
86
+ e['items'] = e.key?('link') ? e['link'].length : 0
89
87
  e
90
88
  end
91
89
  end
92
90
 
93
91
  # field_sym : :id or :name
94
- def get_source_id(source_list,source_name)
92
+ def get_source_id(source_list, source_name)
95
93
  source_ids = source_list.select { |i| i['name'].eql?(source_name) }
96
94
  if source_ids.empty?
97
- raise CliError,%Q(No such Faspex source "#{source_name}" in [#{source_list.map{|i| %Q("#{i['name']}")}.join(', ')}])
95
+ raise CliError, %Q(No such Faspex source "#{source_name}" in [#{source_list.map{|i| %Q("#{i['name']}")}.join(', ')}])
98
96
  end
99
97
  return source_ids.first['id']
100
98
  end
@@ -104,13 +102,13 @@ module Aspera
104
102
  @api_v3 = nil
105
103
  @api_v4 = nil
106
104
  super(env)
107
- options.add_opt_simple(:link,'public link for specific operation')
108
- options.add_opt_simple(:delivery_info,'package delivery information (extended value)')
109
- options.add_opt_simple(:source_name,'create package from remote source (by name)')
110
- options.add_opt_simple(:storage,'Faspex local storage definition')
111
- options.add_opt_simple(:recipient,'use if recipient is a dropbox (with *)')
112
- options.add_opt_list(:box,ATOM_MAILBOXES,'package box')
113
- options.set_option(:box,:inbox)
105
+ options.add_opt_simple(:link, 'public link for specific operation')
106
+ options.add_opt_simple(:delivery_info, 'package delivery information (extended value)')
107
+ options.add_opt_simple(:source_name, 'create package from remote source (by name)')
108
+ options.add_opt_simple(:storage, 'Faspex local storage definition')
109
+ options.add_opt_simple(:recipient, 'use if recipient is a dropbox (with *)')
110
+ options.add_opt_list(:box, ATOM_MAILBOXES, 'package box')
111
+ options.set_option(:box, :inbox)
114
112
  options.parse_options!
115
113
  end
116
114
 
@@ -123,13 +121,13 @@ module Aspera
123
121
 
124
122
  def api_v4
125
123
  if @api_v4.nil?
126
- faspex_api_base = options.get_option(:url,is_type: :mandatory)
124
+ faspex_api_base = options.get_option(:url, is_type: :mandatory)
127
125
  @api_v4 = Rest.new({
128
126
  base_url: faspex_api_base + '/api',
129
127
  auth: {
130
128
  type: :oauth2,
131
129
  base_url: faspex_api_base + '/auth/oauth2',
132
- auth: {type: :basic, username: options.get_option(:username,is_type: :mandatory), password: options.get_option(:password,is_type: :mandatory)},
130
+ auth: {type: :basic, username: options.get_option(:username, is_type: :mandatory), password: options.get_option(:password, is_type: :mandatory)},
133
131
  crtype: :generic,
134
132
  generic: {grant_type: 'password'},
135
133
  scope: 'admin'
@@ -140,11 +138,11 @@ module Aspera
140
138
 
141
139
  # query supports : {"startIndex":10,"count":1,"page":109,"max":2,"pmax":1}
142
140
  def mailbox_filtered_entries(stop_at_id: nil)
143
- recipient_names = [options.get_option(:recipient) || options.get_option(:username,is_type: :mandatory)]
141
+ recipient_names = [options.get_option(:recipient) || options.get_option(:username, is_type: :mandatory)]
144
142
  # some workgroup messages have no star in recipient name
145
143
  recipient_names.push(recipient_names.first[1..-1]) if recipient_names.first.start_with?('*')
146
144
  # mailbox is in ATOM_MAILBOXES
147
- mailbox = options.get_option(:box,is_type: :mandatory)
145
+ mailbox = options.get_option(:box, is_type: :mandatory)
148
146
  # parameters
149
147
  mailbox_query = options.get_option(:query)
150
148
  max_items = nil
@@ -153,7 +151,7 @@ module Aspera
153
151
  if !mailbox_query.nil?
154
152
  raise 'query: must be Hash or nil' unless mailbox_query.is_a?(Hash)
155
153
  raise "query: supported params: #{ATOM_EXT_PARAMS}" unless (mailbox_query.keys - ATOM_EXT_PARAMS).empty?
156
- raise 'query: startIndex and page are exclusive' if mailbox_query.has_key?('startIndex') && mailbox_query.has_key?('page')
154
+ raise 'query: startIndex and page are exclusive' if mailbox_query.key?('startIndex') && mailbox_query.key?('page')
157
155
  max_items = mailbox_query[MAX_ITEMS]
158
156
  mailbox_query.delete(MAX_ITEMS)
159
157
  max_pages = mailbox_query[MAX_PAGES]
@@ -162,11 +160,11 @@ module Aspera
162
160
  loop do
163
161
  # get a batch of package information
164
162
  # order: first batch is latest packages, and then in a batch ids are increasing
165
- atom_xml = api_v3.call({operation: 'GET',subpath: "#{mailbox}.atom",headers: {'Accept' => 'application/xml'},url_params: mailbox_query})[:http].body
163
+ atom_xml = api_v3.call({operation: 'GET', subpath: "#{mailbox}.atom", headers: {'Accept' => 'application/xml'}, url_params: mailbox_query})[:http].body
166
164
  box_data = XmlSimple.xml_in(atom_xml, {'ForceArray' => true})
167
- Log.dump(:box_data,box_data)
168
- items = box_data.has_key?('entry') ? box_data['entry'] : []
169
- Log.log.debug("new items: #{items.count}")
165
+ Log.dump(:box_data, box_data)
166
+ items = box_data.key?('entry') ? box_data['entry'] : []
167
+ Log.log.debug{"new items: #{items.count}"}
170
168
  # it is the end if page is empty
171
169
  break if items.empty?
172
170
  stop_condition = false
@@ -174,7 +172,7 @@ module Aspera
174
172
  items.reverse_each do |package|
175
173
  package[PACKAGE_MATCH_FIELD] =
176
174
  case mailbox
177
- when :inbox,:archive
175
+ when :inbox, :archive
178
176
  recipient = package['to'].find{|i|recipient_names.include?(i['name'].first)}
179
177
  recipient.nil? ? nil : recipient['recipient_delivery_id'].first
180
178
  else # :sent
@@ -186,33 +184,33 @@ module Aspera
186
184
  result.push(package) unless package[PACKAGE_MATCH_FIELD].nil?
187
185
  end
188
186
  break if stop_condition
189
- #result.push({PACKAGE_MATCH_FIELD=>'======'})
190
- Log.log.debug("total items: #{result.count}")
187
+ # result.push({PACKAGE_MATCH_FIELD=>'======'})
188
+ Log.log.debug{"total items: #{result.count}"}
191
189
  # reach the limit ?
192
190
  if !max_items.nil? && (result.count >= max_items)
193
- result = result.slice(0,max_items) if result.count > max_items
191
+ result = result.slice(0, max_items) if result.count > max_items
194
192
  break
195
193
  end
196
194
  link = box_data['link'].find{|i|i['rel'].eql?('next')}
197
- Log.log.debug("link: #{link}")
195
+ Log.log.debug{"link: #{link}"}
198
196
  # no next link
199
197
  break if link.nil?
200
198
  # replace parameters with the ones from next link
201
199
  params = CGI.parse(URI.parse(link['href']).query)
202
- mailbox_query = params.keys.each_with_object({}){|i,m|;m[i] = params[i].first;}
203
- Log.log.debug("query: #{mailbox_query}")
200
+ mailbox_query = params.keys.each_with_object({}){|i, m|; m[i] = params[i].first; }
201
+ Log.log.debug{"query: #{mailbox_query}"}
204
202
  break if !max_pages.nil? && (mailbox_query['page'].to_i > max_pages)
205
203
  end
206
204
  return result
207
205
  end
208
206
 
209
207
  # retrieve transfer spec from pub link for send package
210
- def send_publink_to_ts(public_link_url,package_create_params)
208
+ def send_publink_to_ts(public_link_url, package_create_params)
211
209
  delivery_info = package_create_params['delivery']
212
210
  # pub link user
213
211
  link_data = self.class.get_link_data(public_link_url)
214
- if !['external/submissions/new','external/dropbox_submissions/new'].include?(link_data[:subpath])
215
- raise CliBadArgument,"pub link is #{link_data[:subpath]}, expecting external/submissions/new"
212
+ if !['external/submissions/new', 'external/dropbox_submissions/new'].include?(link_data[:subpath])
213
+ raise CliBadArgument, "pub link is #{link_data[:subpath]}, expecting external/submissions/new"
216
214
  end
217
215
  create_path = link_data[:subpath].split('/')[0..-2].join('/')
218
216
  package_create_params[:passcode] = link_data[:query]['passcode']
@@ -220,7 +218,7 @@ module Aspera
220
218
  delivery_info[:source_paths_list] = transfer.ts_source_paths.map{|i|i['source']}.join("\r\n")
221
219
  api_public_link = Rest.new({base_url: link_data[:base_url]})
222
220
  # Hum, as this does not always work (only user, but not dropbox), we get the javascript and need hack
223
- #pkg_created=api_public_link.create(create_path,package_create_params)[:data]
221
+ # pkg_created=api_public_link.create(create_path,package_create_params)[:data]
224
222
  # so extract data from javascript
225
223
  pkgdatares = api_public_link.call({
226
224
  operation: 'POST',
@@ -229,10 +227,10 @@ module Aspera
229
227
  headers: {'Accept' => 'text/javascript'}})[:http].body
230
228
  # get args of function call
231
229
  pkgdatares.delete!("\n") # one line
232
- pkgdatares.gsub!(/^[^"]+\("\{/,'{') # delete header
233
- pkgdatares.gsub!(/"\);[^"]+$/,'"') # delete trailer
234
- pkgdatares.gsub!(/\}", *"/,'},"') # between two args
235
- pkgdatares.gsub!('\\"','"') # remove protecting quote
230
+ pkgdatares.gsub!(/^[^"]+\("\{/, '{') # delete header
231
+ pkgdatares.gsub!(/"\);[^"]+$/, '"') # delete trailer
232
+ pkgdatares.gsub!(/\}", *"/, '},"') # between two args
233
+ pkgdatares.gsub!('\\"', '"') # remove protecting quote
236
234
  begin
237
235
  pkgdatares = JSON.parse("[#{pkgdatares}]")
238
236
  rescue JSON::ParserError # => e
@@ -250,9 +248,9 @@ module Aspera
250
248
  nagios = Nagios.new
251
249
  begin
252
250
  api_v3.read('me')
253
- nagios.add_ok('faspex api','accessible')
251
+ nagios.add_ok('faspex api', 'accessible')
254
252
  rescue StandardError => e
255
- nagios.add_critical('faspex api',e.to_s)
253
+ nagios.add_critical('faspex api', e.to_s)
256
254
  end
257
255
  return nagios.result
258
256
  when :package
@@ -262,12 +260,12 @@ module Aspera
262
260
  return {
263
261
  type: :object_list,
264
262
  data: mailbox_filtered_entries,
265
- fields: [PACKAGE_MATCH_FIELD,'title','items'],
263
+ fields: [PACKAGE_MATCH_FIELD, 'title', 'items'],
266
264
  textify: lambda {|table_data|Faspex.textify_package_list(table_data)}
267
265
  }
268
266
  when :send
269
- delivery_info = options.get_option(:delivery_info,is_type: :mandatory)
270
- raise CliBadArgument,'delivery_info must be hash, refer to doc' unless delivery_info.is_a?(Hash)
267
+ delivery_info = options.get_option(:delivery_info, is_type: :mandatory)
268
+ raise CliBadArgument, 'delivery_info must be hash, refer to doc' unless delivery_info.is_a?(Hash)
271
269
  # actual parameter to faspex API
272
270
  package_create_params = {'delivery' => delivery_info}
273
271
  public_link_url = options.get_option(:link)
@@ -278,8 +276,8 @@ module Aspera
278
276
  first_source['paths'].push(*transfer.ts_source_paths.map{|i|i['source']})
279
277
  source_name = options.get_option(:source_name)
280
278
  if !source_name.nil?
281
- source_list = api_v3.call({operation: 'GET',subpath: 'source_shares',headers: {'Accept' => 'application/json'}})[:data]['items']
282
- source_id = self.class.get_source_id(source_list,source_name)
279
+ source_list = api_v3.call({operation: 'GET', subpath: 'source_shares', headers: {'Accept' => 'application/json'}})[:data]['items']
280
+ source_id = self.class.get_source_id(source_list, source_name)
283
281
  first_source['id'] = source_id
284
282
  end
285
283
  pkg_created = api_v3.call({
@@ -290,17 +288,17 @@ module Aspera
290
288
  })[:data]
291
289
  if !source_name.nil?
292
290
  # no transfer spec if remote source
293
- return {data: [pkg_created['links']['status']],type: :value_list,name: 'link'}
291
+ return {data: [pkg_created['links']['status']], type: :value_list, name: 'link'}
294
292
  end
295
- raise CliBadArgument,'expecting one session exactly' if pkg_created['xfer_sessions'].length != 1
293
+ raise CliBadArgument, 'expecting one session exactly' if pkg_created['xfer_sessions'].length != 1
296
294
  transfer_spec = pkg_created['xfer_sessions'].first
297
295
  # use source from cmd line, this one only contains destination (already in dest root)
298
296
  transfer_spec.delete('paths')
299
297
  else # publink
300
- transfer_spec = send_publink_to_ts(public_link_url,package_create_params)
298
+ transfer_spec = send_publink_to_ts(public_link_url, package_create_params)
301
299
  end
302
- #Log.dump('transfer_spec',transfer_spec)
303
- return Main.result_transfer(transfer.start(transfer_spec,{src: :node_gen3}))
300
+ # Log.dump('transfer_spec',transfer_spec)
301
+ return Main.result_transfer(transfer.start(transfer_spec))
304
302
  when :recv
305
303
  link_url = options.get_option(:link)
306
304
  # list of faspex ID/URI to download
@@ -309,46 +307,46 @@ module Aspera
309
307
  skip_ids_persistency = nil
310
308
  case link_url
311
309
  when nil # usual case: no link
312
- if options.get_option(:once_only,is_type: :mandatory)
310
+ if options.get_option(:once_only, is_type: :mandatory)
313
311
  skip_ids_persistency = PersistencyActionOnce.new(
314
312
  manager: @agents[:persistency],
315
313
  data: skip_ids_data,
316
314
  id: IdGenerator.from_list([
317
315
  'faspex_recv',
318
- options.get_option(:url,is_type: :mandatory),
319
- options.get_option(:username,is_type: :mandatory),
320
- options.get_option(:box,is_type: :mandatory).to_s
316
+ options.get_option(:url, is_type: :mandatory),
317
+ options.get_option(:username, is_type: :mandatory),
318
+ options.get_option(:box, is_type: :mandatory).to_s
321
319
  ]))
322
320
  end
323
321
  # get command line parameters
324
322
  delivid = instance_identifier
325
323
  raise 'empty id' if delivid.empty?
326
324
  recipient = options.get_option(:recipient)
327
- if delivid.eql?(VAL_ALL)
328
- pkg_id_uri = mailbox_filtered_entries.map{|i|{id: i[PACKAGE_MATCH_FIELD],uri: self.class.get_fasp_uri_from_entry(i, raise_no_link: false)}}
325
+ if VAL_ALL.eql?(delivid)
326
+ pkg_id_uri = mailbox_filtered_entries.map{|i|{id: i[PACKAGE_MATCH_FIELD], uri: self.class.get_fasp_uri_from_entry(i, raise_no_link: false)}}
329
327
  elsif !recipient.nil? && recipient.start_with?('*')
330
328
  found_package_link = mailbox_filtered_entries(stop_at_id: delivid).find{|p|p[PACKAGE_MATCH_FIELD].eql?(delivid)}['link'].first['href']
331
329
  raise 'Not Found. Dropbox and Workgroup packages can use the link option with faspe:' if found_package_link.nil?
332
- pkg_id_uri = [{id: delivid,uri: found_package_link}]
330
+ pkg_id_uri = [{id: delivid, uri: found_package_link}]
333
331
  else
334
332
  # TODO: delivery id is the right one if package was receive by workgroup
335
333
  endpoint =
336
- case options.get_option(:box,is_type: :mandatory)
337
- when :inbox,:archive then'received'
334
+ case options.get_option(:box, is_type: :mandatory)
335
+ when :inbox, :archive then'received'
338
336
  when :sent then 'sent'
339
337
  end
340
- entry_xml = api_v3.call({operation: 'GET',subpath: "#{endpoint}/#{delivid}",headers: {'Accept' => 'application/xml'}})[:http].body
338
+ entry_xml = api_v3.call({operation: 'GET', subpath: "#{endpoint}/#{delivid}", headers: {'Accept' => 'application/xml'}})[:http].body
341
339
  package_entry = XmlSimple.xml_in(entry_xml, {'ForceArray' => true})
342
- pkg_id_uri = [{id: delivid,uri: self.class.get_fasp_uri_from_entry(package_entry)}]
340
+ pkg_id_uri = [{id: delivid, uri: self.class.get_fasp_uri_from_entry(package_entry)}]
343
341
  end
344
342
  when /^faspe:/
345
- pkg_id_uri = [{id: 'package',uri: link_url}]
343
+ pkg_id_uri = [{id: 'package', uri: link_url}]
346
344
  else
347
345
  link_data = self.class.get_link_data(link_url)
348
346
  if !link_data[:subpath].start_with?(PUB_LINK_EXTERNAL_MATCH)
349
- raise CliBadArgument,"Pub link is #{link_data[:subpath]}. Expecting #{PUB_LINK_EXTERNAL_MATCH}"
347
+ raise CliBadArgument, "Pub link is #{link_data[:subpath]}. Expecting #{PUB_LINK_EXTERNAL_MATCH}"
350
348
  end
351
- # Note: unauthenticated API (authorization is in url params)
349
+ # NOTE: unauthenticated API (authorization is in url params)
352
350
  api_public_link = Rest.new({base_url: link_data[:base_url]})
353
351
  pkgdatares = api_public_link.call(
354
352
  operation: 'GET',
@@ -360,15 +358,15 @@ module Aspera
360
358
  raise CliError, 'Unexpected response: package not found ?'
361
359
  end
362
360
  package_entry = XmlSimple.xml_in(pkgdatares[:http].body, {'ForceArray' => false})
363
- Log.dump(:package_entry,package_entry)
361
+ Log.dump(:package_entry, package_entry)
364
362
  transfer_uri = self.class.get_fasp_uri_from_entry(package_entry)
365
- pkg_id_uri = [{id: package_entry['id'],uri: transfer_uri}]
363
+ pkg_id_uri = [{id: package_entry['id'], uri: transfer_uri}]
366
364
  end # public link
367
365
  # prune packages already downloaded
368
366
  # TODO : remove ids from skip not present in inbox to avoid growing too big
369
367
  # skip_ids_data.select!{|id|pkg_id_uri.select{|p|p[:id].eql?(id)}}
370
368
  pkg_id_uri.reject!{|i|skip_ids_data.include?(i[:id])}
371
- Log.dump(:pkg_id_uri,pkg_id_uri)
369
+ Log.dump(:pkg_id_uri, pkg_id_uri)
372
370
  return Main.result_status('no new package') if pkg_id_uri.empty?
373
371
  result_transfer = []
374
372
  pkg_id_uri.each do |id_uri|
@@ -378,20 +376,20 @@ module Aspera
378
376
  else
379
377
  transfer_spec = Fasp::Uri.new(id_uri[:uri]).transfer_spec
380
378
  # NOTE: only external users have token in faspe: link !
381
- if !transfer_spec.has_key?('token')
382
- sanitized = id_uri[:uri].gsub('&','&amp;')
379
+ if !transfer_spec.key?('token')
380
+ sanitized = id_uri[:uri].gsub('&', '&amp;')
383
381
  xmlpayload =
384
382
  %Q(<?xml version="1.0" encoding="UTF-8"?><url-list xmlns="http://schemas.asperasoft.com/xml/url-list"><url href="#{sanitized}"/></url-list>)
385
383
  transfer_spec['token'] = api_v3.call({
386
384
  operation: 'POST',
387
385
  subpath: 'issue-token?direction=down',
388
- headers: {'Accept' => 'text/plain','Content-Type' => 'application/vnd.aspera.url-list+xml'},
386
+ headers: {'Accept' => 'text/plain', 'Content-Type' => 'application/vnd.aspera.url-list+xml'},
389
387
  text_body_params: xmlpayload})[:http].body
390
388
  end
391
389
  transfer_spec['direction'] = Fasp::TransferSpec::DIRECTION_RECEIVE
392
- statuses = transfer.start(transfer_spec,{src: :node_gen3})
390
+ statuses = transfer.start(transfer_spec)
393
391
  end
394
- result_transfer.push({'package' => id_uri[:id],Main::STATUS_FIELD => statuses})
392
+ result_transfer.push({'package' => id_uri[:id], Main::STATUS_FIELD => statuses})
395
393
  # skip only if all sessions completed
396
394
  skip_ids_data.push(id_uri[:id]) if TransferAgent.session_status(statuses).eql?(:success)
397
395
  end
@@ -400,87 +398,87 @@ module Aspera
400
398
  end
401
399
  when :source
402
400
  command_source = options.get_next_command(%i[list id name])
403
- source_list = api_v3.call({operation: 'GET',subpath: 'source_shares',headers: {'Accept' => 'application/json'}})[:data]['items']
401
+ source_list = api_v3.call({operation: 'GET', subpath: 'source_shares', headers: {'Accept' => 'application/json'}})[:data]['items']
404
402
  case command_source
405
403
  when :list
406
- return {type: :object_list,data: source_list}
404
+ return {type: :object_list, data: source_list}
407
405
  else # :id or :name
408
406
  source_match_val = options.get_next_argument('source id or name')
409
407
  source_ids = source_list.select { |i| i[command_source.to_s].to_s.eql?(source_match_val) }
410
408
  if source_ids.empty?
411
- raise CliError,"No such Faspex source #{command_source}: #{source_match_val} in [#{source_list.map{|i| i[command_source.to_s]}.join(', ')}]"
409
+ raise CliError, "No such Faspex source #{command_source}: #{source_match_val} in [#{source_list.map{|i| i[command_source.to_s]}.join(', ')}]"
412
410
  end
413
411
  # get id and name
414
412
  source_name = source_ids.first['name']
415
- #source_id=source_ids.first['id']
416
- source_hash = options.get_option(:storage,is_type: :mandatory)
413
+ # source_id=source_ids.first['id']
414
+ source_hash = options.get_option(:storage, is_type: :mandatory)
417
415
  # check value of option
418
- raise CliError,'storage option must be a Hash' unless source_hash.is_a?(Hash)
419
- source_hash.each do |name,storage|
420
- raise CliError,"storage '#{name}' must be a Hash" unless storage.is_a?(Hash)
421
- [KEY_NODE,KEY_PATH].each do |key|
422
- raise CliError,"storage '#{name}' must have a '#{key}'" unless storage.has_key?(key)
416
+ raise CliError, 'storage option must be a Hash' unless source_hash.is_a?(Hash)
417
+ source_hash.each do |name, storage|
418
+ raise CliError, "storage '#{name}' must be a Hash" unless storage.is_a?(Hash)
419
+ [KEY_NODE, KEY_PATH].each do |key|
420
+ raise CliError, "storage '#{name}' must have a '#{key}'" unless storage.key?(key)
423
421
  end
424
422
  end
425
- if !source_hash.has_key?(source_name)
426
- raise CliError,"No such storage in config file: \"#{source_name}\" in [#{source_hash.keys.join(', ')}]"
423
+ if !source_hash.key?(source_name)
424
+ raise CliError, "No such storage in config file: \"#{source_name}\" in [#{source_hash.keys.join(', ')}]"
427
425
  end
428
426
  source_info = source_hash[source_name]
429
- Log.log.debug("source_info: #{source_info}")
427
+ Log.log.debug{"source_info: #{source_info}"}
430
428
  command_node = options.get_next_command(%i[info node])
431
429
  case command_node
432
430
  when :info
433
- return {data: source_info,type: :single_object}
431
+ return {data: source_info, type: :single_object}
434
432
  when :node
435
433
  node_config = ExtendedValue.instance.evaluate(source_info[KEY_NODE])
436
- raise CliError,"bad type for: \"#{source_info[KEY_NODE]}\"" unless node_config.is_a?(Hash)
437
- Log.log.debug("node=#{node_config}")
434
+ raise CliError, "bad type for: \"#{source_info[KEY_NODE]}\"" unless node_config.is_a?(Hash)
435
+ Log.log.debug{"node=#{node_config}"}
438
436
  api_node = Rest.new({
439
437
  base_url: node_config['url'],
440
438
  auth: {
441
439
  type: :basic,
442
440
  username: node_config['username'],
443
441
  password: node_config['password']}})
444
- command = options.get_next_command(Node::COMMON_ACTIONS)
445
- return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action(command,source_info[KEY_PATH])
442
+ command = options.get_next_command(Node::COMMANDS_FASPEX)
443
+ return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action(command, source_info[KEY_PATH])
446
444
  end
447
445
  end
448
446
  when :me
449
- my_info = api_v3.call({operation: 'GET',subpath: 'me',headers: {'Accept' => 'application/json'}})[:data]
447
+ my_info = api_v3.call({operation: 'GET', subpath: 'me', headers: {'Accept' => 'application/json'}})[:data]
450
448
  return {data: my_info, type: :single_object}
451
449
  when :dropbox
452
450
  command_pkg = options.get_next_command([:list])
453
451
  case command_pkg
454
452
  when :list
455
- dropbox_list = api_v3.call({operation: 'GET',subpath: 'dropboxes',headers: {'Accept' => 'application/json'}})[:data]
453
+ dropbox_list = api_v3.call({operation: 'GET', subpath: 'dropboxes', headers: {'Accept' => 'application/json'}})[:data]
456
454
  return {type: :object_list, data: dropbox_list['items'], fields: %w[name id description can_read can_write]}
457
455
  end
458
456
  when :v4
459
457
  command = options.get_next_command(%i[package dropbox dmembership workgroup wmembership user metadata_profile])
460
458
  case command
461
459
  when :dropbox
462
- return entity_action(api_v4,'admin/dropboxes',display_fields: %w[id e_wg_name e_wg_desc created_at])
460
+ return entity_action(api_v4, 'admin/dropboxes', display_fields: %w[id e_wg_name e_wg_desc created_at])
463
461
  when :dmembership
464
- return entity_action(api_v4,'dropbox_memberships')
462
+ return entity_action(api_v4, 'dropbox_memberships')
465
463
  when :workgroup
466
- return entity_action(api_v4,'admin/workgroups',display_fields: %w[id e_wg_name e_wg_desc created_at])
464
+ return entity_action(api_v4, 'admin/workgroups', display_fields: %w[id e_wg_name e_wg_desc created_at])
467
465
  when :wmembership
468
- return entity_action(api_v4,'workgroup_memberships')
466
+ return entity_action(api_v4, 'workgroup_memberships')
469
467
  when :user
470
- return entity_action(api_v4,'users',display_fields: %w[id name first_name last_name])
468
+ return entity_action(api_v4, 'users', display_fields: %w[id name first_name last_name])
471
469
  when :metadata_profile
472
- return entity_action(api_v4,'metadata_profiles')
470
+ return entity_action(api_v4, 'metadata_profiles')
473
471
  when :package
474
472
  pkg_box_type = options.get_next_command([:users])
475
473
  pkg_box_id = instance_identifier
476
- return entity_action(api_v4,"#{pkg_box_type}/#{pkg_box_id}/packages")
474
+ return entity_action(api_v4, "#{pkg_box_type}/#{pkg_box_id}/packages")
477
475
  end
478
476
  when :address_book
479
477
  result = api_v3.call(
480
478
  operation: 'GET',
481
479
  subpath: 'address-book',
482
480
  headers: {'Accept' => 'application/json'},
483
- url_params: {'format' => 'json','count' => 100_000}
481
+ url_params: {'format' => 'json', 'count' => 100_000}
484
482
  )[:data]
485
483
  self.format.display_status("users: #{result['itemsPerPage']}/#{result['totalResults']}, start:#{result['startIndex']}")
486
484
  users = result['entry']
@@ -491,15 +489,15 @@ module Aspera
491
489
  u['email'] = email['value'] unless email.nil?
492
490
  end
493
491
  if u['email'].nil?
494
- Log.log.warn("Skip user without email: #{u}")
492
+ Log.log.warn{"Skip user without email: #{u}"}
495
493
  next
496
494
  end
497
- u['first_name'],u['last_name'] = u['displayName'].split(' ',2)
495
+ u['first_name'], u['last_name'] = u['displayName'].split(' ', 2)
498
496
  u['x'] = true
499
497
  end
500
- return {type: :object_list,data: users}
498
+ return {type: :object_list, data: users}
501
499
  when :login_methods
502
- login_meths = api_v3.call({operation: 'GET',subpath: 'login/new',headers: {'Accept' => 'application/xrds+xml'}})[:http].body
500
+ login_meths = api_v3.call({operation: 'GET', subpath: 'login/new', headers: {'Accept' => 'application/xrds+xml'}})[:http].body
503
501
  login_methods = XmlSimple.xml_in(login_meths, {'ForceArray' => false})
504
502
  return {type: :object_list, data: login_methods['XRD']['Service']}
505
503
  end # command