aspera-cli 4.25.2 → 4.25.3

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.
@@ -94,7 +94,7 @@ module Aspera
94
94
 
95
95
  def initialize(**_)
96
96
  super
97
- options.declare(:box, "Package inbox, either shared inbox name or one of: #{Api::Faspex::API_LIST_MAILBOX_TYPES.join(', ')} or #{SpecialValues::ALL}", default: 'inbox')
97
+ options.declare(:box, "Package inbox, either shared inbox name or one of: #{Api::Faspex::API_LIST_MAILBOX_TYPES.join(', ')} or #{SpecialValues::ALL}", default: 'inbox_all')
98
98
  options.declare(:shared_folder, 'Send package with files from shared folder')
99
99
  options.declare(:group_type, 'Type of shared box', allowed: %i[shared_inboxes workgroups], default: :shared_inboxes)
100
100
  options.parse_options!
@@ -102,7 +102,7 @@ module Aspera
102
102
 
103
103
  def set_api
104
104
  # create an API object with the same options, but with a different subpath
105
- @api_v5 = new_with_options(Api::Faspex)
105
+ @api_v5 = Api::Faspex.new(**Oauth.args_from_options(options))
106
106
  # in case user wants to use HTTPGW tell transfer agent how to get address
107
107
  transfer.httpgw_url_cb = lambda{@api_v5.read('account')['gateway_url']}
108
108
  end
@@ -118,7 +118,7 @@ module Aspera
118
118
  recipient_types = [recipient_types] unless recipient_types.is_a?(Array)
119
119
  end
120
120
  parameters['recipients'].map! do |recipient_data|
121
- # if just a string, make a general lookup and build expected name/type hash
121
+ # If just a string, make a general lookup and build expected name/type hash
122
122
  if recipient_data.is_a?(String)
123
123
  matched = @api_v5.lookup_by_name('contacts', recipient_data, query: Rest.php_style({context: 'packages', type: recipient_types}))
124
124
  recipient_data = {
@@ -174,8 +174,8 @@ module Aspera
174
174
  # list all packages with optional filter
175
175
  def list_packages_with_filter(query: {})
176
176
  filter = options.get_next_argument('filter', mandatory: false, validation: Proc, default: ->(_x){true})
177
- # translate box name to API prefix (with ending slash)
178
177
  box = options.get_option(:box)
178
+ # Translate box name to API prefix (with ending slash)
179
179
  entity =
180
180
  case box
181
181
  when SpecialValues::ALL then 'packages' # only admin can list all packages globally
@@ -236,17 +236,12 @@ module Aspera
236
236
  rescue Cli::BadArgument
237
237
  # paths is optional
238
238
  end
239
+ box = options.get_option(:box)
239
240
  download_params = {
240
- type: 'received',
241
+ type: Api::Faspex.box_type(box),
241
242
  transfer_type: Api::Faspex::TRANSFER_CONNECT
242
243
  }
243
- box = options.get_option(:box)
244
- case box
245
- when /outbox/ then download_params[:type] = 'sent'
246
- when *Api::Faspex::API_LIST_MAILBOX_TYPES then nil # nothing to do
247
- else # shared inbox / workgroup
248
- download_params[:recipient_workgroup_id] = lookup_entity_by_field(api: @api_v5, entity: options.get_option(:group_type), value: box)['id']
249
- end
244
+ download_params[:recipient_workgroup_id] = lookup_entity_by_field(api: @api_v5, entity: options.get_option(:group_type), value: box)['id'] if !Api::Faspex::API_LIST_MAILBOX_TYPES.include?(box) && box != SpecialValues::ALL
250
245
  packages.each do |package|
251
246
  pkg_id = package['id']
252
247
  formatter.display_status("Receiving package #{pkg_id}")
@@ -255,9 +250,9 @@ module Aspera
255
250
  operation: 'POST',
256
251
  subpath: "packages/#{pkg_id}/transfer_spec/download",
257
252
  query: download_params,
258
- content_type: Rest::MIME_JSON,
253
+ content_type: Mime::JSON,
259
254
  body: param_file_list,
260
- headers: {'Accept' => Rest::MIME_JSON}
255
+ headers: {'Accept' => Mime::JSON}
261
256
  )
262
257
  # delete flag for Connect Client
263
258
  transfer_spec.delete('authentication')
@@ -272,6 +267,56 @@ module Aspera
272
267
  return Main.result_transfer_multiple(result_transfer)
273
268
  end
274
269
 
270
+ def package_send
271
+ parameters = value_create_modify(command: :send)
272
+ # autofill recipient for public url
273
+ if @api_v5.pub_link_context&.key?('recipient_type') && !parameters.key?('recipients')
274
+ parameters['recipients'] = [{
275
+ name: @api_v5.pub_link_context['name'],
276
+ recipient_type: @api_v5.pub_link_context['recipient_type']
277
+ }]
278
+ end
279
+ normalize_recipients(parameters)
280
+ # User specified content prot in tspec, but faspex requires in package creation
281
+ # `transfer_spec/upload` will set `content_protection`
282
+ if transfer.user_transfer_spec['content_protection'] && !parameters.key?('ear_enabled')
283
+ transfer.user_transfer_spec.delete('content_protection')
284
+ parameters['ear_enabled'] = true
285
+ end
286
+ package = @api_v5.create('packages', parameters)
287
+ shared_folder = options.get_option(:shared_folder)
288
+ if shared_folder.nil?
289
+ # send from local files
290
+ transfer_spec = @api_v5.create(
291
+ "packages/#{package['id']}/transfer_spec/upload",
292
+ {paths: transfer.source_list},
293
+ query: {transfer_type: Api::Faspex::TRANSFER_CONNECT}
294
+ )
295
+ # well, we asked a TS for connect, but we actually want a generic one
296
+ transfer_spec.delete('authentication')
297
+ return Main.result_transfer(transfer.start(transfer_spec))
298
+ else
299
+ # send from remote shared folder
300
+ if (m = Base.percent_selector(shared_folder))
301
+ shared_folder = lookup_entity_by_field(
302
+ api: @api_v5,
303
+ entity: 'shared_folders',
304
+ field: m[:field],
305
+ value: m[:value]
306
+ )['id']
307
+ end
308
+ transfer_request = {shared_folder_id: shared_folder, paths: transfer.source_list}
309
+ # start remote transfer and get first status
310
+ result = @api_v5.create("packages/#{package['id']}/remote_transfer", transfer_request)
311
+ result['id'] = package['id']
312
+ unless result['status'].eql?('completed')
313
+ formatter.display_status("Package #{package['id']}")
314
+ result = wait_package_status(package['id'])
315
+ end
316
+ return Main.result_single_object(result)
317
+ end
318
+ end
319
+
275
320
  # Browse a folder
276
321
  # @param browse_endpoint [String] the endpoint to browse
277
322
  def browse_folder(browse_endpoint)
@@ -300,9 +345,9 @@ module Aspera
300
345
  operation: 'POST',
301
346
  subpath: browse_endpoint,
302
347
  query: query,
303
- content_type: Rest::MIME_JSON,
348
+ content_type: Mime::JSON,
304
349
  body: {'path' => path, 'filters' => filters},
305
- headers: {'Accept' => Rest::MIME_JSON},
350
+ headers: {'Accept' => Mime::JSON},
306
351
  ret: :both
307
352
  )
308
353
  all_items.concat(data['items'])
@@ -339,12 +384,7 @@ module Aspera
339
384
  when :show
340
385
  return Main.result_single_object(@api_v5.read("packages/#{package_id}"))
341
386
  when :browse
342
- location = case options.get_option(:box)
343
- when 'inbox' then 'received'
344
- when 'outbox' then 'sent'
345
- else raise BadArgument, 'Browse only available for inbox and outbox'
346
- end
347
- return browse_folder("packages/#{package_id}/files/#{location}")
387
+ return browse_folder("packages/#{package_id}/files/#{Api::Faspex.box_type(options.get_option(:box))}")
348
388
  when :status
349
389
  status_list = options.get_next_argument('list of states, or nothing', mandatory: false, validation: Array)
350
390
  status = wait_package_status(package_id, status_list: status_list)
@@ -357,64 +397,21 @@ module Aspera
357
397
  @api_v5.call(
358
398
  operation: 'DELETE',
359
399
  subpath: 'packages',
360
- content_type: Rest::MIME_JSON,
400
+ content_type: Mime::JSON,
361
401
  body: {ids: ids},
362
- headers: {'Accept' => Rest::MIME_JSON}
402
+ headers: {'Accept' => Mime::JSON}
363
403
  )
364
404
  return Main.result_status('Package(s) deleted')
365
405
  when :receive
366
406
  return package_receive(package_id)
367
407
  when :send
368
- parameters = value_create_modify(command: command)
369
- # autofill recipient for public url
370
- if @api_v5.pub_link_context&.key?('recipient_type') && !parameters.key?('recipients')
371
- parameters['recipients'] = [{
372
- name: @api_v5.pub_link_context['name'],
373
- recipient_type: @api_v5.pub_link_context['recipient_type']
374
- }]
375
- end
376
- normalize_recipients(parameters)
377
- # User specified content prot in tspec, but faspex requires in package creation
378
- # `transfer_spec/upload` will set `content_protection`
379
- if transfer.user_transfer_spec['content_protection'] && !parameters.key?('ear_enabled')
380
- transfer.user_transfer_spec.delete('content_protection')
381
- parameters['ear_enabled'] = true
382
- end
383
- package = @api_v5.create('packages', parameters)
384
- shared_folder = options.get_option(:shared_folder)
385
- if shared_folder.nil?
386
- # send from local files
387
- transfer_spec = @api_v5.create(
388
- "packages/#{package['id']}/transfer_spec/upload",
389
- {paths: transfer.source_list},
390
- query: {transfer_type: Api::Faspex::TRANSFER_CONNECT}
391
- )
392
- # well, we asked a TS for connect, but we actually want a generic one
393
- transfer_spec.delete('authentication')
394
- return Main.result_transfer(transfer.start(transfer_spec))
395
- else
396
- # send from remote shared folder
397
- if (m = Base.percent_selector(shared_folder))
398
- shared_folder = lookup_entity_by_field(
399
- api: @api_v5,
400
- entity: 'shared_folders',
401
- field: m[:field],
402
- value: m[:value]
403
- )['id']
404
- end
405
- transfer_request = {shared_folder_id: shared_folder, paths: transfer.source_list}
406
- # start remote transfer and get first status
407
- result = @api_v5.create("packages/#{package['id']}/remote_transfer", transfer_request)
408
- result['id'] = package['id']
409
- unless result['status'].eql?('completed')
410
- formatter.display_status("Package #{package['id']}")
411
- result = wait_package_status(package['id'])
412
- end
413
- return Main.result_single_object(result)
414
- end
408
+ return package_send
415
409
  when :list
416
410
  list, total = list_packages_with_filter
417
- return Main.result_object_list(list, total: total, fields: %w[id title release_date total_bytes total_files created_time state])
411
+ fields = %w[id title status sender.name recipients.0.name release_date total_bytes total_files]
412
+ fields.delete('recipients.0.name') if %w[inbox inbox_history].include?(options.get_option(:box))
413
+ fields.delete('sender.name') if %w[outbox outbox_history].include?(options.get_option(:box))
414
+ return Main.result_object_list(list, total: total, fields: fields)
418
415
  end
419
416
  end
420
417
 
@@ -687,7 +684,7 @@ module Aspera
687
684
  @api_v5.create(invitation_endpoint, params)
688
685
  end
689
686
  when :resend
690
- @api_v5.create("#{invitation_endpoint}/#{instance_identifier}/resend")
687
+ @api_v5.create("#{invitation_endpoint}/#{instance_identifier}/resend", nil)
691
688
  return Main.result_status('Invitation resent')
692
689
  else
693
690
  return entity_execute(
@@ -450,7 +450,7 @@ module Aspera
450
450
  @api_node.call(
451
451
  operation: 'POST',
452
452
  subpath: 'services/soap/Transfer-201210',
453
- content_type: Rest::MIME_TEXT,
453
+ content_type: Mime::TEXT,
454
454
  body: CENTRAL_SOAP_API_TEST,
455
455
  headers: {'Content-Type' => 'text/xml;charset=UTF-8', 'SOAPAction' => 'FASPSessionNET-200911#GetSessionInfo'},
456
456
  ret: :resp
@@ -471,9 +471,7 @@ module Aspera
471
471
  return Main.result_single_object(nd_info)
472
472
  when :license
473
473
  # requires: asnodeadmin -mu <node user> --acl-add=internal --internal
474
- node_license = @api_node.read('license')
475
- Log.log.error('server must have: asnodeadmin -mu <node user> --acl-add=internal --internal') if node_license['failure'].is_a?(String) && node_license['failure'].include?('ACL')
476
- return Main.result_single_object(node_license)
474
+ return Main.result_single_object(@api_node.read('license'))
477
475
  when :api_details
478
476
  return Main.result_single_object({base_url: @api_node.base_url}.merge(@api_node.params))
479
477
  end
@@ -837,7 +835,7 @@ module Aspera
837
835
  @api_node.call(
838
836
  operation: 'POST',
839
837
  subpath: "asyncs/#{asyncs_id}/#{sync_command}",
840
- content_type: Rest::MIME_TEXT,
838
+ content_type: Mime::TEXT,
841
839
  body: '',
842
840
  ret: :resp
843
841
  ).body
@@ -7,9 +7,33 @@ module Aspera
7
7
  module Plugins
8
8
  # base class for applications supporting OAuth 2.0 authentication
9
9
  class Oauth < BasicAuth
10
- # OAuth methods supported
10
+ class << self
11
+ # Get command line options specified by `AUTH_OPTIONS` and `defaults.keys` (value is default).
12
+ # Adds those not nil to the `kwargs`.
13
+ # Instantiate the provided `klass` with those `kwargs`.
14
+ # `defaults` can specify a default value (not `nil`)
15
+ # @param options [Cli::Manager] Object to get command line options.
16
+ # @param kwargs [Hash] Object creation arguments
17
+ # @param defaults [Hash] Additional options, key=symbol, value=default value or nil
18
+ # @return [Object] instance of `klass`
19
+ # @raise [Cli::Error] if a required option is missing
20
+ def args_from_options(options, defaults: nil, **kwargs)
21
+ defaults ||= {}
22
+ (AUTH_OPTIONS + defaults.keys).each_with_object(kwargs) do |i, m|
23
+ v = options.get_option(i)
24
+ m[i] = v unless v.nil?
25
+ m[i] = defaults[i] if m[i].nil? && !defaults[i].nil?
26
+ end
27
+ rescue ::ArgumentError => e
28
+ if (m = e.message.match(/missing keyword: :(.*)$/))
29
+ raise Cli::Error, "Missing option: #{m[1]}"
30
+ end
31
+ raise
32
+ end
33
+ end
34
+ # OAuth methods supported (web, jwt)
11
35
  AUTH_TYPES = %i[web jwt boot].freeze
12
- # Options used for authentication
36
+ # Options used for authentication (url, auth, client_id, etc...)
13
37
  AUTH_OPTIONS = %i[url auth client_id client_secret redirect_uri private_key passphrase username password].freeze
14
38
  def initialize(**_)
15
39
  super
@@ -20,29 +44,6 @@ module Aspera
20
44
  options.declare(:private_key, 'OAuth (JWT) RSA private key PEM value (prefix file path with @file:)')
21
45
  options.declare(:passphrase, 'OAuth (JWT) RSA private key passphrase')
22
46
  end
23
-
24
- # Get command line options specified by `AUTH_OPTIONS` and `option.keys` (value is default).
25
- # Adds those not nil to the `kwargs`.
26
- # Instantiate the provided `klass` with those kwargs.
27
- # `option` can specify a default value (not `nil`)
28
- # @param klass [Class] API object to create
29
- # @param kwargs [Hash] The fixed keyword arguments for creation
30
- # @param option [Hash] Additional options, key=symbol, value:default value or nil
31
- # @return [Object] instance of `klass`
32
- # @raise [Cli::Error] if a required option is missing
33
- def new_with_options(klass, kwargs: {}, option: {})
34
- klass.new(**
35
- (AUTH_OPTIONS + option.keys).each_with_object(kwargs) do |i, m|
36
- v = options.get_option(i)
37
- m[i] = v unless v.nil?
38
- m[i] = option[i] unless !m[i].nil? || option[i].nil?
39
- end)
40
- rescue ::ArgumentError => e
41
- if (m = e.message.match(/missing keyword: :(.*)$/))
42
- raise Cli::Error, "Missing option: #{m[1]}"
43
- end
44
- raise
45
- end
46
47
  end
47
48
  end
48
49
  end
@@ -90,8 +90,8 @@ module Aspera
90
90
  Aspera::Preview::Options::DESCRIPTIONS.each do |opt|
91
91
  values = if opt.key?(:values)
92
92
  opt[:values]
93
- elsif Cli::Manager::BOOLEAN_SIMPLE.include?(opt[:default])
94
- Allowed::TYPES_BOOLEAN
93
+ elsif BoolValue.symbol?(opt[:default])
94
+ BoolValue::TYPES
95
95
  end
96
96
  options.declare(opt[:name], opt[:description].capitalize, allowed: values, handler: {o: @gen_options, m: opt[:name]}, default: opt[:default])
97
97
  end
@@ -109,7 +109,7 @@ module Aspera
109
109
  # /files/id/files is normally cached in Redis, but we can discard the cache
110
110
  # but /files/id is not cached
111
111
  def get_folder_entries(file_id, request_args = nil)
112
- headers = {'Accept' => Rest::MIME_JSON}
112
+ headers = {'Accept' => Mime::JSON}
113
113
  headers['X-Aspera-Cache-Control'] = 'no-cache' if @option_folder_reset_cache.eql?(:header)
114
114
  return @api_node.read("files/#{file_id}/files", request_args, headers: headers)
115
115
  end
@@ -17,20 +17,21 @@ module Aspera
17
17
  # @return [Hash] with version, ping, api
18
18
  def health_check(url)
19
19
  result = {}
20
+ # Get version from main page
20
21
  result[:version] =
21
22
  begin
22
23
  version = nil
23
24
  login_page = Rest
24
25
  .new(base_url: url, redirect_max: 2)
25
26
  .read('', headers: {'Accept'=>'text/html'})
27
+ raise 'not Shares' unless login_page.include?('aspera-Shares')
26
28
  if (m = login_page.match(/\(v([0-9a-f\.]+)\)/))
27
29
  version = m[1]
28
30
  if (m = login_page.match(/Patch level ([0-9]+)/))
29
- version = "#{result[:version]} #{m[0]}"
31
+ version = "#{version} #{m[0]}"
30
32
  end
31
33
  end
32
- raise 'no version' if version.nil?
33
- version
34
+ version.nil? ? 'no version' : version
34
35
  rescue => e
35
36
  e
36
37
  end
@@ -45,10 +46,15 @@ module Aspera
45
46
  end
46
47
  result[:api] =
47
48
  begin
48
- resp = Rest.new(base_url: url, redirect_max: 1).read("#{NODE_API_PATH}/app", exception: false, ret: :resp)
49
+ data, resp = Rest
50
+ .new(base_url: "#{url}/#{NODE_API_PATH}", redirect_max: 1)
51
+ .read('info', exception: false, ret: :both)
49
52
  # shall fail: shares requires auth, but we check error message
50
- raise 'not found' unless resp.code.to_s.eql?('401') && resp.body.eql?('{"error":{"user_message":"API user authentication failed"}}')
51
- 'available'
53
+ if resp.code.to_s.eql?('401') && data&.dig('error', 'user_message')&.include?('authentication failed')
54
+ 'available'
55
+ else
56
+ raise "not found (#{resp.code})"
57
+ end
52
58
  rescue => e
53
59
  e
54
60
  end
@@ -88,7 +94,7 @@ module Aspera
88
94
  SAML_IMPORT_MANDATORY = %w[id name_id].freeze
89
95
  SAML_IMPORT_ALLOWED = %w[email given_name surname].concat(SAML_IMPORT_MANDATORY).freeze
90
96
 
91
- ACTIONS = %i[health files admin].freeze
97
+ ACTIONS = %i[health info files admin].freeze
92
98
  # common to users and groups
93
99
  USR_GRP_SETTINGS = %i[transfer_settings app_authorizations share_permissions].freeze
94
100
 
@@ -111,6 +117,8 @@ module Aspera
111
117
  nagios.add_critical('API', health[:api].to_s)
112
118
  end
113
119
  Main.result_object_list(nagios.status_list)
120
+ when :info
121
+ return Main.result_single_object(basic_auth_api(NODE_API_PATH).read('info', headers: {'Content-Type'=>'application/json'}))
114
122
  when :files
115
123
  api_shares_node = basic_auth_api(NODE_API_PATH)
116
124
  repo_command = options.get_next_command(Node::COMMANDS_SHARES)
@@ -4,6 +4,6 @@ module Aspera
4
4
  module Cli
5
5
  # For beta add extension : .beta1
6
6
  # For dev version add extension : .pre
7
- VERSION = '4.25.2'
7
+ VERSION = '4.25.3'
8
8
  end
9
9
  end
data/lib/aspera/colors.rb CHANGED
@@ -58,6 +58,13 @@ class String
58
58
  end
59
59
  end
60
60
 
61
+ # Applies the provided list of string decoration (colors).
62
+ # @param colors [Array<Symbol>] List of decorations.
63
+ # @return [String] Enhanced String.
64
+ def apply(*colors)
65
+ colors.reduce(self){ |s, c| s.public_send(c)}
66
+ end
67
+
61
68
  # Transform capitalized to snake case
62
69
  def capital_to_snake
63
70
  return gsub(/([a-z\d])([A-Z])/, '\1_\2')
@@ -52,9 +52,9 @@ module Aspera
52
52
  operation: 'POST',
53
53
  subpath: "packages/#{package['id']}/transfer_spec/upload",
54
54
  query: {transfer_type: Api::Faspex::TRANSFER_CONNECT},
55
- content_type: Rest::MIME_JSON,
55
+ content_type: Mime::JSON,
56
56
  body: {paths: [{'destination'=>'/'}]},
57
- headers: {'Accept' => Rest::MIME_JSON}
57
+ headers: {'Accept' => Mime::JSON}
58
58
  )
59
59
  transfer_spec.delete('authentication')
60
60
  # but we place it in a Faspex package creation response
@@ -82,18 +82,18 @@ module Aspera
82
82
  end
83
83
  Log.log.debug{"faspex_package_create_result=#{faspex_package_create_result}"}
84
84
  response.status = 200
85
- response.content_type = Rest::MIME_JSON
85
+ response.content_type = Mime::JSON
86
86
  response.body = JSON.generate(faspex_package_create_result)
87
87
  rescue => e
88
88
  response.status = 500
89
- response['Content-Type'] = Rest::MIME_JSON
89
+ response['Content-Type'] = Mime::JSON
90
90
  response.body = {error: e.message, stacktrace: e.backtrace}.to_json
91
91
  Log.log.error(e.message)
92
92
  Log.log.debug{e.backtrace.join("\n")}
93
93
  end
94
94
  else
95
95
  response.status = 400
96
- response['Content-Type'] = Rest::MIME_JSON
96
+ response['Content-Type'] = Mime::JSON
97
97
  response.body = {error: 'Unsupported endpoint'}.to_json
98
98
  end
99
99
  end
@@ -32,13 +32,13 @@ module Aspera
32
32
  # Only accept requests on the root
33
33
  if !request.path.start_with?(@parameters[:root])
34
34
  response.status = 400
35
- response['Content-Type'] = Rest::MIME_JSON
35
+ response['Content-Type'] = Mime::JSON
36
36
  response.body = {status: 'error', message: 'Request outside domain'}.to_json
37
37
  return
38
38
  end
39
39
  if request.body.nil?
40
40
  response.status = 400
41
- response['Content-Type'] = Rest::MIME_JSON
41
+ response['Content-Type'] = Mime::JSON
42
42
  response.body = {status: 'error', message: 'Empty request'}.to_json
43
43
  return
44
44
  end
@@ -65,7 +65,7 @@ module Aspera
65
65
  raise "script #{script_path} failed with code #{process_status.exitstatus}" if !process_status.success? && @parameters[:fail_on_error]
66
66
  end
67
67
  response.status = 200
68
- response.content_type = Rest::MIME_JSON
68
+ response.content_type = Mime::JSON
69
69
  response.body = JSON.generate({status: 'success', script: script_path, exit_code: process_status.exitstatus})
70
70
  Log.log.debug{'Script executed successfully'}
71
71
  rescue => e
@@ -76,7 +76,7 @@ module Aspera
76
76
  Log.log.error("Killed process: #{post_proc_pid}")
77
77
  end
78
78
  response.status = 500
79
- response['Content-Type'] = Rest::MIME_JSON
79
+ response['Content-Type'] = Mime::JSON
80
80
  response.body = {status: 'error', script: script_path, message: e.message}.to_json
81
81
  end
82
82
  end
data/lib/aspera/log.rb CHANGED
@@ -65,11 +65,8 @@ module Aspera
65
65
 
66
66
  # Class methods
67
67
  class << self
68
- # Applies the provided list of string decoration (colors) to the value.
69
- # @param value [String] Value to enhance.
70
- # @param colors [Array(Symbol)] List of decorations
71
- def apply_colors(value, colors)
72
- colors.inject(value){ |s, c| s.send(c)}
68
+ def short_levl(level)
69
+ "#{level[0, 3]}#{level[-1]}"
73
70
  end
74
71
 
75
72
  # Get the logger object of singleton
@@ -154,8 +151,8 @@ module Aspera
154
151
 
155
152
  def formatter=(formatter)
156
153
  if formatter.is_a?(String)
157
- raise Error, "Unknown formatter #{formatter}, use one of: #{FORMATTERS.keys.join(', ')}" unless FORMATTERS.key?(formatter.to_sym)
158
- formatter = FORMATTERS[formatter.to_sym]
154
+ raise Error, "Unknown formatter #{formatter}, use one of: #{FORMATTERS.join(', ')}" unless FORMATTER_LAMBDAS.key?(formatter.to_sym)
155
+ formatter = FORMATTER_LAMBDAS[formatter.to_sym]
159
156
  elsif !formatter.respond_to?(:call) && !formatter.is_a?(Logger::Formatter)
160
157
  raise Error, 'Formatter must be a String, a Logger::Formatter or a Proc'
161
158
  end
@@ -226,18 +223,22 @@ module Aspera
226
223
  UNKNOWN: %i{blink}
227
224
  }.freeze
228
225
 
229
- # Short levels with color
230
- LVL_COLOR = LVL_DECO.map{ |k, v| [k, apply_colors("#{k[..2]}#{k[-1]}", v)]}.to_h.freeze
226
+ # Short (4-letters) levels with color
227
+ LVL_COLOR = LVL_DECO.to_h do |k, v|
228
+ [k, short_levl(k).apply(*v)]
229
+ end.freeze
231
230
 
232
231
  DEFAULT_FORMATTER = ->(s, _d, _p, m){"#{LVL_COLOR[s]} #{m}\n"}
233
232
 
234
233
  # pre-defined formatters
235
- FORMATTERS = {
234
+ FORMATTER_LAMBDAS = {
236
235
  standard: Logger::Formatter.new,
237
236
  default: DEFAULT_FORMATTER,
238
237
  caller: ->(s, _d, _p, m){"#{LVL_COLOR[s]} #{Log.caller_method}\n#{m}\n"}
239
238
  }.freeze
240
239
 
241
- private_constant :LVL_DECO, :LVL_COLOR, :DEFAULT_FORMATTER, :FORMATTERS
240
+ FORMATTERS = FORMATTER_LAMBDAS.keys
241
+
242
+ private_constant :LVL_DECO, :DEFAULT_FORMATTER, :FORMATTER_LAMBDAS
242
243
  end
243
244
  end
@@ -40,6 +40,11 @@ module Aspera
40
40
  "```#{type}\n#{lines.join("\n")}\n```\n\n"
41
41
  end
42
42
 
43
+ # inline code
44
+ def icode(text)
45
+ "`#{text}`"
46
+ end
47
+
43
48
  def paragraph(text)
44
49
  "#{text}\n\n"
45
50
  end
@@ -328,7 +328,7 @@ module Aspera
328
328
 
329
329
  def set_json_response(request, response, json, code: 200)
330
330
  response.status = code
331
- response['Content-Type'] = Rest::MIME_JSON
331
+ response['Content-Type'] = Mime::JSON
332
332
  response.body = json.to_json
333
333
  Log.log.trace1{Log.obj_dump("response for #{request.request_method} #{request.path}", json)}
334
334
  end
@@ -53,7 +53,7 @@ module Aspera
53
53
  def create_token_call(creation_params)
54
54
  Log.log.debug{'Generating a new token'.bg_green}
55
55
  return @api.create(@path_token, nil, query: creation_params, ret: :resp) if @use_query
56
- return @api.create(@path_token, creation_params, content_type: Rest::MIME_WWW, ret: :resp)
56
+ return @api.create(@path_token, creation_params, content_type: Mime::WWW, ret: :resp)
57
57
  end
58
58
 
59
59
  # Create base parameters for token creation calls
@@ -24,9 +24,9 @@ module Aspera
24
24
  operation: 'POST',
25
25
  subpath: path_token,
26
26
  query: @query.merge(scope: params[:scope]), # scope is here because it may change over time (node)
27
- content_type: Rest::MIME_JSON,
27
+ content_type: Mime::JSON,
28
28
  body: @body,
29
- headers: {'Accept' => Rest::MIME_JSON},
29
+ headers: {'Accept' => Mime::JSON},
30
30
  ret: :resp
31
31
  )
32
32
  end