aspera-cli 4.27.0 → 4.27.1
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +29 -0
- data/CONTRIBUTING.md +1 -7
- data/TODO.md +50 -0
- data/docs/README.md +708 -488
- data/lib/aspera/agent/base.rb +10 -2
- data/lib/aspera/agent/connect.rb +7 -7
- data/lib/aspera/agent/desktop.rb +3 -3
- data/lib/aspera/agent/direct.rb +48 -19
- data/lib/aspera/agent/factory.rb +3 -3
- data/lib/aspera/agent/httpgw.rb +55 -14
- data/lib/aspera/agent/node.rb +2 -2
- data/lib/aspera/agent/transferd.rb +12 -12
- data/lib/aspera/api/aoc.rb +28 -28
- data/lib/aspera/api/cos_node.rb +10 -9
- data/lib/aspera/api/faspex.rb +2 -2
- data/lib/aspera/api/httpgw.rb +20 -20
- data/lib/aspera/api/node.rb +31 -53
- data/lib/aspera/ascmd.rb +13 -13
- data/lib/aspera/ascp/installation.rb +43 -36
- data/lib/aspera/ascp/management.rb +6 -6
- data/lib/aspera/assert.rb +12 -13
- data/lib/aspera/cli/ascp_actions.rb +7 -7
- data/lib/aspera/cli/async_transfer_store.rb +49 -5
- data/lib/aspera/cli/bootstrapper.rb +9 -9
- data/lib/aspera/cli/command_registry.rb +1 -1
- data/lib/aspera/cli/command_spec.rb +6 -3
- data/lib/aspera/cli/context.rb +3 -3
- data/lib/aspera/cli/extended_value.rb +26 -26
- data/lib/aspera/cli/formatter.rb +76 -54
- data/lib/aspera/cli/gem_checker.rb +1 -1
- data/lib/aspera/cli/hints.rb +2 -2
- data/lib/aspera/cli/http.rb +22 -29
- data/lib/aspera/cli/mailer.rb +7 -7
- data/lib/aspera/cli/mcp_tool.rb +31 -4
- data/lib/aspera/cli/option_declarator.rb +77 -0
- data/lib/aspera/cli/options.schema.yaml +273 -3
- data/lib/aspera/cli/parser.rb +539 -280
- data/lib/aspera/cli/plugins/alee.rb +1 -1
- data/lib/aspera/cli/plugins/aoc.rb +297 -313
- data/lib/aspera/cli/plugins/ats.rb +25 -21
- data/lib/aspera/cli/plugins/base.rb +357 -186
- data/lib/aspera/cli/plugins/basic_auth.rb +0 -12
- data/lib/aspera/cli/plugins/config.rb +76 -73
- data/lib/aspera/cli/plugins/console.rb +8 -8
- data/lib/aspera/cli/plugins/cos.rb +4 -3
- data/lib/aspera/cli/plugins/factory.rb +2 -2
- data/lib/aspera/cli/plugins/faspex5.rb +259 -248
- data/lib/aspera/cli/plugins/faspio.rb +7 -2
- data/lib/aspera/cli/plugins/httpgw.rb +1 -1
- data/lib/aspera/cli/plugins/mcp.rb +11 -11
- data/lib/aspera/cli/plugins/node.rb +227 -283
- data/lib/aspera/cli/plugins/orchestrator.rb +23 -23
- data/lib/aspera/cli/plugins/preview.rb +61 -64
- data/lib/aspera/cli/plugins/server.rb +36 -31
- data/lib/aspera/cli/plugins/shares.rb +174 -135
- data/lib/aspera/cli/preset_actions.rb +39 -19
- data/lib/aspera/cli/preset_manager.rb +74 -32
- data/lib/aspera/cli/result.rb +18 -16
- data/lib/aspera/cli/runner.rb +75 -39
- data/lib/aspera/cli/secret_finder.rb +1 -1
- data/lib/aspera/cli/sync_actions.rb +36 -35
- data/lib/aspera/cli/terminal_formatter.rb +2 -2
- data/lib/aspera/cli/transfer_actions.rb +17 -10
- data/lib/aspera/cli/transfer_agent.rb +44 -44
- data/lib/aspera/cli/transfer_progress.rb +7 -7
- data/lib/aspera/cli/vault_manager.rb +34 -12
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cli/wizard.rb +17 -20
- data/lib/aspera/colors.rb +3 -3
- data/lib/aspera/command_line_builder.rb +16 -16
- data/lib/aspera/command_line_converter.rb +1 -1
- data/lib/aspera/coverage.rb +1 -2
- data/lib/aspera/data_repository.rb +1 -1
- data/lib/aspera/dot_container.rb +8 -8
- data/lib/aspera/environment.rb +12 -12
- data/lib/aspera/faspex_gw.rb +4 -4
- data/lib/aspera/faspex_postproc.rb +14 -9
- data/lib/aspera/graphql.rb +4 -2
- data/lib/aspera/hash_ext.rb +2 -2
- data/lib/aspera/json_rpc/client.rb +1 -1
- data/lib/aspera/keychain/base.rb +10 -3
- data/lib/aspera/keychain/encrypted_hash.rb +92 -17
- data/lib/aspera/keychain/factory.rb +17 -5
- data/lib/aspera/keychain/hashicorp_vault.rb +1 -1
- data/lib/aspera/keychain/macos_security.rb +23 -25
- data/lib/aspera/keychain/one_password_api.rb +86 -0
- data/lib/aspera/keychain/one_password_base.rb +34 -0
- data/lib/aspera/keychain/one_password_cli.rb +98 -0
- data/lib/aspera/link_header.rb +2 -2
- data/lib/aspera/log.rb +13 -13
- data/lib/aspera/markdown.rb +5 -5
- data/lib/aspera/nagios.rb +8 -8
- data/lib/aspera/node_simulator.rb +33 -27
- data/lib/aspera/oauth/base.rb +4 -5
- data/lib/aspera/oauth/boot.rb +3 -3
- data/lib/aspera/oauth/factory.rb +5 -5
- data/lib/aspera/oauth/jwt.rb +5 -7
- data/lib/aspera/oauth/web.rb +4 -4
- data/lib/aspera/persistency_action_once.rb +4 -4
- data/lib/aspera/persistency_folder.rb +8 -8
- data/lib/aspera/preview/file_types.rb +4 -4
- data/lib/aspera/preview/generator.rb +49 -46
- data/lib/aspera/preview/options.rb +3 -2
- data/lib/aspera/preview/terminal.rb +5 -5
- data/lib/aspera/preview/utils.rb +65 -18
- data/lib/aspera/products/connect.rb +2 -2
- data/lib/aspera/products/desktop.rb +1 -1
- data/lib/aspera/products/other.rb +2 -2
- data/lib/aspera/products/transferd.rb +3 -3
- data/lib/aspera/proxy_auto_config.rb +10 -10
- data/lib/aspera/rest.rb +149 -115
- data/lib/aspera/rest_error_analyzer.rb +3 -3
- data/lib/aspera/rest_list.rb +10 -9
- data/lib/aspera/schema/IBM Aspera Node API-4.4.6.yaml +6232 -0
- data/lib/aspera/schema/IBM Aspera faspio Gateway API-1.0.0.yaml +249 -0
- data/lib/aspera/schema/IBM_Aspera_Shares.yaml +4653 -0
- data/lib/aspera/schema/documentation.rb +17 -11
- data/lib/aspera/schema/reader.rb +78 -4
- data/lib/aspera/schema/registry.rb +26 -7
- data/lib/aspera/secret_hider.rb +5 -5
- data/lib/aspera/ssh.rb +64 -31
- data/lib/aspera/ssl.rb +3 -3
- data/lib/aspera/sync/database.rb +2 -2
- data/lib/aspera/sync/operations.rb +13 -13
- data/lib/aspera/temp_file_manager.rb +24 -4
- data/lib/aspera/transfer/faux_file.rb +2 -2
- data/lib/aspera/transfer/parameters.rb +15 -15
- data/lib/aspera/transfer/resumer.rb +9 -9
- data/lib/aspera/transfer/spec.rb +1 -1
- data/lib/aspera/uri_reader.rb +52 -15
- data/lib/aspera/web_auth.rb +6 -5
- data/lib/aspera/web_server_simple.rb +9 -9
- data/lib/aspera/yaml.rb +4 -4
- data.tar.gz.sig +0 -0
- metadata +10 -4
- metadata.gz.sig +0 -0
- data/lib/aspera/cli/plugins/faspex.rb +0 -576
- data/lib/aspera/transfer/uri.rb +0 -56
data/lib/aspera/log.rb
CHANGED
|
@@ -20,13 +20,13 @@ class Logger
|
|
|
20
20
|
|
|
21
21
|
# Add custom level to logger severity, below debug level
|
|
22
22
|
module Severity
|
|
23
|
-
1.upto(TRACE_MAX).each{ |level| const_set(:"TRACE#{level}", - level)}
|
|
23
|
+
1.upto(TRACE_MAX).each { |level| const_set(:"TRACE#{level}", - level) }
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
# Hash
|
|
27
27
|
# key [Integer] Log level (e.g. 0 for DEBUG)
|
|
28
28
|
# value [Symbol] Uppercase log level label (e.g. :DEBUG)
|
|
29
|
-
SEVERITY_LABEL = Severity.constants.to_h{ |name| [Severity.const_get(name), name]}
|
|
29
|
+
SEVERITY_LABEL = Severity.constants.to_h { |name| [Severity.const_get(name), name] }
|
|
30
30
|
|
|
31
31
|
# Override
|
|
32
32
|
# @param severity [Integer] Log severity as int
|
|
@@ -42,14 +42,14 @@ class Logger
|
|
|
42
42
|
def make_methods(str_level)
|
|
43
43
|
int_level = ::Logger.const_get(str_level.upcase)
|
|
44
44
|
method_base = str_level.downcase
|
|
45
|
-
define_method(method_base, ->(message = nil, &block){add(int_level, message, &block)})
|
|
46
|
-
define_method("#{method_base}?", ->{level <= int_level})
|
|
47
|
-
define_method("#{method_base}!", ->{self.level = int_level})
|
|
45
|
+
define_method(method_base, ->(message = nil, &block) { add(int_level, message, &block) })
|
|
46
|
+
define_method("#{method_base}?", -> { level <= int_level })
|
|
47
|
+
define_method("#{method_base}!", -> { self.level = int_level })
|
|
48
48
|
nil
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
# Declare methods for all levels
|
|
52
|
-
Logger::Severity.constants.each{ |severity| make_methods(severity)}
|
|
52
|
+
Logger::Severity.constants.each { |severity| make_methods(severity) }
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
# Restore warnings
|
|
@@ -68,7 +68,7 @@ module Aspera
|
|
|
68
68
|
LOG_TYPES = %i[stderr stdout syslog].freeze
|
|
69
69
|
|
|
70
70
|
# Levels are :trace2,:trace1,:debug,:info,:warn,:error,fatal,:unknown
|
|
71
|
-
LEVELS = Logger::Severity.constants.sort{ |a, b| Logger::Severity.const_get(a) <=> Logger::Severity.const_get(b)}.map{ |c| c.downcase.to_sym}.freeze
|
|
71
|
+
LEVELS = Logger::Severity.constants.sort { |a, b| Logger::Severity.const_get(a) <=> Logger::Severity.const_get(b) }.map { |c| c.downcase.to_sym }.freeze
|
|
72
72
|
|
|
73
73
|
# Class methods
|
|
74
74
|
class << self
|
|
@@ -100,7 +100,7 @@ module Aspera
|
|
|
100
100
|
JSON.pretty_generate(object) rescue PP.pp(object, +'')
|
|
101
101
|
when :ruby
|
|
102
102
|
PP.pp(object, +'')
|
|
103
|
-
else Aspera.error_unexpected_value(instance.dump_format){'dump format'}
|
|
103
|
+
else Aspera.error_unexpected_value(instance.dump_format) { 'dump format' }
|
|
104
104
|
end
|
|
105
105
|
"#{name.to_s.green}(#{instance.dump_format})#{object.class}=\n#{dump_text}"
|
|
106
106
|
end
|
|
@@ -119,7 +119,7 @@ module Aspera
|
|
|
119
119
|
# Returns the last 2 containers (module/class) and method caller
|
|
120
120
|
def caller_method
|
|
121
121
|
stack = caller
|
|
122
|
-
i = stack.rindex{ |line| line.include?('Logger')}
|
|
122
|
+
i = stack.rindex { |line| line.include?('Logger') }
|
|
123
123
|
frame = stack[i + 1] if i && stack[i + 1]
|
|
124
124
|
return '???' unless frame
|
|
125
125
|
# Extract the "Class::Module::Method" or "Class#method" part
|
|
@@ -166,7 +166,7 @@ module Aspera
|
|
|
166
166
|
# @return [nil]
|
|
167
167
|
def formatter=(formatter)
|
|
168
168
|
if formatter.is_a?(String)
|
|
169
|
-
Aspera.assert(FORMATTER_LAMBDAS.key?(formatter.to_sym), type: Error){"Unknown formatter #{formatter}, use one of: #{FORMATTERS.join(', ')}"}
|
|
169
|
+
Aspera.assert(FORMATTER_LAMBDAS.key?(formatter.to_sym), type: Error) { "Unknown formatter #{formatter}, use one of: #{FORMATTERS.join(', ')}" }
|
|
170
170
|
formatter = FORMATTER_LAMBDAS[formatter.to_sym]
|
|
171
171
|
elsif !formatter.respond_to?(:call) && !formatter.is_a?(Logger::Formatter)
|
|
172
172
|
raise Error, 'Formatter must be a String, a Logger::Formatter or a Proc'
|
|
@@ -210,7 +210,7 @@ module Aspera
|
|
|
210
210
|
end
|
|
211
211
|
# Use `local2` facility, like other Aspera components
|
|
212
212
|
@logger = Syslog::Logger.new(@program_name, Syslog::LOG_LOCAL2)
|
|
213
|
-
else Aspera.error_unexpected_value(new_log_type){"log type (#{LOG_TYPES.join(', ')})"}
|
|
213
|
+
else Aspera.error_unexpected_value(new_log_type) { "log type (#{LOG_TYPES.join(', ')})" }
|
|
214
214
|
end
|
|
215
215
|
@logger.level = current_severity_integer
|
|
216
216
|
@logger_type = new_log_type
|
|
@@ -247,13 +247,13 @@ module Aspera
|
|
|
247
247
|
[k, short_levl(k).apply(*v)]
|
|
248
248
|
end.freeze
|
|
249
249
|
|
|
250
|
-
DEFAULT_FORMATTER = ->(s, _d, _p, m){"#{LVL_COLOR[s]} #{m}\n"}
|
|
250
|
+
DEFAULT_FORMATTER = ->(s, _d, _p, m) { "#{LVL_COLOR[s]} #{m}\n" }
|
|
251
251
|
|
|
252
252
|
# pre-defined formatters
|
|
253
253
|
FORMATTER_LAMBDAS = {
|
|
254
254
|
standard: Logger::Formatter.new,
|
|
255
255
|
default: DEFAULT_FORMATTER,
|
|
256
|
-
caller: ->(s, _d, _p, m){"#{LVL_COLOR[s]} #{Log.caller_method}\n#{m}\n"}
|
|
256
|
+
caller: ->(s, _d, _p, m) { "#{LVL_COLOR[s]} #{Log.caller_method}\n#{m}\n" }
|
|
257
257
|
}.freeze
|
|
258
258
|
|
|
259
259
|
FORMATTERS = FORMATTER_LAMBDAS.keys
|
data/lib/aspera/markdown.rb
CHANGED
|
@@ -80,12 +80,12 @@ module Aspera
|
|
|
80
80
|
def table(table)
|
|
81
81
|
# get max width of each columns
|
|
82
82
|
col_widths = table.transpose.map do |col|
|
|
83
|
-
[col.flat_map{ |c| c.to_s.delete('`').split(HTML_BREAK).map(&:size)}.max, COL_WIDTH].min
|
|
83
|
+
[col.flat_map { |c| c.to_s.delete('`').split(HTML_BREAK).map(&:size) }.max, COL_WIDTH].min
|
|
84
84
|
end
|
|
85
85
|
headings = table.shift
|
|
86
|
-
table.unshift(col_widths.map{ |col_width| '-' * col_width})
|
|
86
|
+
table.unshift(col_widths.map { |col_width| '-' * col_width })
|
|
87
87
|
table.unshift(headings)
|
|
88
|
-
lines = table.map{ |line| "| #{line.map{ |i| i.to_s.gsub('\\', '\\\\').gsub('|', '\|')}.join(' | ')} |\n"}
|
|
88
|
+
lines = table.map { |line| "| #{line.map { |i| i.to_s.gsub('\\', '\\\\').gsub('|', '\|') }.join(' | ')} |\n" }
|
|
89
89
|
lines[1] = lines[1].tr(' ', '-')
|
|
90
90
|
return lines.join.chomp
|
|
91
91
|
end
|
|
@@ -94,7 +94,7 @@ module Aspera
|
|
|
94
94
|
# @param items [Array<String>] list of items
|
|
95
95
|
# @return [String] markdown unordered list
|
|
96
96
|
def list(items)
|
|
97
|
-
items.map{ |i| "- #{i}"}.join("\n")
|
|
97
|
+
items.map { |i| "- #{i}" }.join("\n")
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
# Generate a markdown heading
|
|
@@ -110,7 +110,7 @@ module Aspera
|
|
|
110
110
|
# @param type [String] admonition type: NOTE, CAUTION, WARNING, IMPORTANT, TIP, INFO
|
|
111
111
|
# @return [String] markdown admonition block
|
|
112
112
|
def admonition(lines, type: 'INFO')
|
|
113
|
-
"> [!#{type}]\n#{lines.map{ |l| "> #{l}"}.join("\n")}\n\n"
|
|
113
|
+
"> [!#{type}]\n#{lines.map { |l| "> #{l}" }.join("\n")}\n\n"
|
|
114
114
|
end
|
|
115
115
|
|
|
116
116
|
# Generate a fenced code block
|
data/lib/aspera/nagios.rb
CHANGED
|
@@ -17,7 +17,7 @@ module Aspera
|
|
|
17
17
|
# add methods to add nagios error levels, each take component name and message
|
|
18
18
|
LEVELS.each_index do |code|
|
|
19
19
|
name = "#{ADD_PREFIX}#{LEVELS[code]}".to_sym
|
|
20
|
-
define_method(name){ |comp, msg| @data.push({code: code, comp: comp, msg: msg})}
|
|
20
|
+
define_method(name) { |comp, msg| @data.push({code: code, comp: comp, msg: msg}) }
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
class << self
|
|
@@ -26,18 +26,18 @@ module Aspera
|
|
|
26
26
|
Aspera.assert_type(data, Array)
|
|
27
27
|
Aspera.assert(!data.empty?, 'data is empty')
|
|
28
28
|
%w[status component message].each do |c|
|
|
29
|
-
Aspera.assert(data.first.key?(c)){"result must have #{c}"}
|
|
29
|
+
Aspera.assert(data.first.key?(c)) { "result must have #{c}" }
|
|
30
30
|
end
|
|
31
|
-
res_errors = data.reject{ |s| s['status'].eql?('ok')}
|
|
31
|
+
res_errors = data.reject { |s| s['status'].eql?('ok') }
|
|
32
32
|
# keep only errors in case of problem, other ok are assumed so
|
|
33
33
|
data = res_errors unless res_errors.empty?
|
|
34
34
|
# first is most critical
|
|
35
|
-
data.sort!{ |a, b| LEVELS.index(a['status'].to_sym) <=> LEVELS.index(b['status'].to_sym)}
|
|
35
|
+
data.sort! { |a, b| LEVELS.index(a['status'].to_sym) <=> LEVELS.index(b['status'].to_sym) }
|
|
36
36
|
# build message: if multiple components: concatenate
|
|
37
37
|
# message = data.map{|i|"#{i['component']}:#{i['message']}"}.join(', ').gsub("\n",' ')
|
|
38
38
|
message = data
|
|
39
|
-
.group_by{ |d| d['component']}
|
|
40
|
-
.map{ |comp, items| "#{comp}:#{items.map{ |d| d['message']}.join(',')}"}
|
|
39
|
+
.group_by { |d| d['component'] }
|
|
40
|
+
.map { |comp, items| "#{comp}:#{items.map { |d| d['message'] }.join(',')}" }
|
|
41
41
|
.join(', ')
|
|
42
42
|
.tr("\n", ' ')
|
|
43
43
|
status = data.first['status'].upcase
|
|
@@ -60,7 +60,7 @@ module Aspera
|
|
|
60
60
|
remote_time = Time.parse(remote_date)
|
|
61
61
|
diff_time = (remote_time - Time.now).abs
|
|
62
62
|
diff_rounded = diff_time.round(-2)
|
|
63
|
-
Log.log.debug{"DATE: #{remote_date} #{remote_time} diff=#{diff_rounded}"}
|
|
63
|
+
Log.log.debug { "DATE: #{remote_date} #{remote_time} diff=#{diff_rounded}" }
|
|
64
64
|
msg = "offset #{diff_rounded} sec"
|
|
65
65
|
if diff_time >= DATE_CRIT_OFFSET
|
|
66
66
|
add_critical(component, msg)
|
|
@@ -80,7 +80,7 @@ module Aspera
|
|
|
80
80
|
# @return [Array] of Hash
|
|
81
81
|
def status_list
|
|
82
82
|
Aspera.assert(!@data.empty?, 'missing result')
|
|
83
|
-
@data.map{ |i| {'status' => LEVELS[i[:code]].to_s, 'component' => i[:comp], 'message' => i[:msg]}}
|
|
83
|
+
@data.map { |i| {'status' => LEVELS[i[:code]].to_s, 'component' => i[:comp], 'message' => i[:msg]} }
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
end
|
|
@@ -10,7 +10,7 @@ require 'json'
|
|
|
10
10
|
module Aspera
|
|
11
11
|
class NodeSimulator
|
|
12
12
|
def initialize
|
|
13
|
-
@agent = Agent::Direct.new(management_cb: ->(event){process_event(event)})
|
|
13
|
+
@agent = Agent::Direct.new(management_cb: ->(event) { process_event(event) })
|
|
14
14
|
@sessions = {}
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -19,7 +19,7 @@ module Aspera
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def all_sessions
|
|
22
|
-
@agent.sessions.map{ |session| session[:job_id]}.uniq.each.map{ |job_id| job_to_transfer(job_id)}
|
|
22
|
+
@agent.sessions.map { |session| session[:job_id] }.uniq.each.map { |job_id| job_to_transfer(job_id) }
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
# status: ('waiting', 'partially_completed', 'unknown', 'waiting(read error)',] 'running', 'completed', 'failed'
|
|
@@ -131,27 +131,27 @@ module Aspera
|
|
|
131
131
|
def process_event(event)
|
|
132
132
|
# Code duplicated on purpose, as implementation goes, blocks will be replaced
|
|
133
133
|
case event['Type']
|
|
134
|
-
when 'NOP' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
134
|
+
when 'NOP' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
135
135
|
# rubocop:disable Lint/DuplicateBranch
|
|
136
|
-
when 'START' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
137
|
-
when 'QUERY' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
138
|
-
when 'QUERYRSP' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
139
|
-
when 'STATS' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
140
|
-
when 'STOP' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
141
|
-
when 'ERROR' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
142
|
-
when 'CANCEL' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
143
|
-
when 'DONE' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
144
|
-
when 'RATE' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
145
|
-
when 'FILEERROR' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
146
|
-
when 'SESSION' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
147
|
-
when 'NOTIFICATION' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
148
|
-
when 'INIT' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
149
|
-
when 'VLINK' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
150
|
-
when 'PUT' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
151
|
-
when 'WRITE' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
152
|
-
when 'CLOSE' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
153
|
-
when 'SKIP' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
154
|
-
when 'ARGSTOP' then Aspera.Log.debug{"event not managed: #{event['Type']}"}
|
|
136
|
+
when 'START' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
137
|
+
when 'QUERY' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
138
|
+
when 'QUERYRSP' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
139
|
+
when 'STATS' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
140
|
+
when 'STOP' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
141
|
+
when 'ERROR' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
142
|
+
when 'CANCEL' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
143
|
+
when 'DONE' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
144
|
+
when 'RATE' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
145
|
+
when 'FILEERROR' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
146
|
+
when 'SESSION' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
147
|
+
when 'NOTIFICATION' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
148
|
+
when 'INIT' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
149
|
+
when 'VLINK' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
150
|
+
when 'PUT' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
151
|
+
when 'WRITE' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
152
|
+
when 'CLOSE' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
153
|
+
when 'SKIP' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
154
|
+
when 'ARGSTOP' then Aspera.Log.debug { "event not managed: #{event['Type']}" }
|
|
155
155
|
# rubocop:enable Lint/DuplicateBranch
|
|
156
156
|
else Aspera.error_unreachable_line
|
|
157
157
|
end
|
|
@@ -164,19 +164,25 @@ module Aspera
|
|
|
164
164
|
PATH_TRANSFERS = '/ops/transfers'
|
|
165
165
|
PATH_ONE_TRANSFER = %r{/ops/transfers/(.+)$}
|
|
166
166
|
PATH_BROWSE = '/files/browse'
|
|
167
|
-
# @param
|
|
168
|
-
# @param
|
|
167
|
+
# @param credentials [Hash]
|
|
168
|
+
# @param simulator [NodeSimulator]
|
|
169
169
|
def initialize(server, credentials, simulator)
|
|
170
170
|
super(server)
|
|
171
171
|
@credentials = credentials
|
|
172
172
|
@simulator = simulator
|
|
173
|
+
# Resolve once at startup; default to current working directory
|
|
174
|
+
@browse_root = File.realpath(credentials[:browse_root] || Dir.pwd)
|
|
173
175
|
end
|
|
174
176
|
|
|
175
177
|
require 'json'
|
|
176
178
|
require 'time'
|
|
177
179
|
|
|
178
180
|
def folder_to_structure(folder_path)
|
|
179
|
-
|
|
181
|
+
# Resolve and confine to browse_root (prevents path traversal via client-supplied path)
|
|
182
|
+
resolved = File.realpath(folder_path)
|
|
183
|
+
Aspera.assert(resolved.start_with?("#{@browse_root}/") || resolved.eql?(@browse_root)) { 'Browse path traversal attempt detected' }
|
|
184
|
+
Aspera.assert(Dir.exist?(resolved)) { "Path does not exist or is not a directory: #{resolved}" }
|
|
185
|
+
folder_path = resolved
|
|
180
186
|
|
|
181
187
|
# Build self structure
|
|
182
188
|
folder_stat = File.stat(folder_path)
|
|
@@ -242,7 +248,7 @@ module Aspera
|
|
|
242
248
|
when PATH_BROWSE
|
|
243
249
|
req = JSON.parse(request.body)
|
|
244
250
|
# req['count']
|
|
245
|
-
set_json_response(request, response, folder_to_structure(req['path']))
|
|
251
|
+
set_json_response(request, response, folder_to_structure(req['path'] || @browse_root))
|
|
246
252
|
else
|
|
247
253
|
set_json_response(request, response, [{error: 'Bad request'}], code: 400)
|
|
248
254
|
end
|
|
@@ -332,7 +338,7 @@ module Aspera
|
|
|
332
338
|
response.status = code
|
|
333
339
|
response['Content-Type'] = Mime::JSON
|
|
334
340
|
response.body = json.to_json
|
|
335
|
-
Log.log.trace1{Log.obj_dump("response for #{request.request_method} #{request.path}", json)}
|
|
341
|
+
Log.log.trace1 { Log.obj_dump("response for #{request.request_method} #{request.path}", json) }
|
|
336
342
|
end
|
|
337
343
|
end
|
|
338
344
|
end
|
data/lib/aspera/oauth/base.rb
CHANGED
|
@@ -51,7 +51,7 @@ module Aspera
|
|
|
51
51
|
# @return [Net::HTTPResponse] raw HTTP response with token
|
|
52
52
|
# @raise [RestCallError] if not 2XX code
|
|
53
53
|
def create_token_call(creation_params)
|
|
54
|
-
Log.log.debug{'Generating a new token'.bg_green}
|
|
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
56
|
return @api.create(@path_token, creation_params, content_type: Mime::WWW, ret: :resp)
|
|
57
57
|
end
|
|
@@ -87,7 +87,7 @@ module Aspera
|
|
|
87
87
|
# `direct` agent is equipped with refresh code
|
|
88
88
|
# an API was already called, but failed, we need to regenerate or refresh
|
|
89
89
|
if refresh || token_info[:expired]
|
|
90
|
-
Log.log.trace1{"refresh: #{refresh} expired: #{token_info[:expired]}"}
|
|
90
|
+
Log.log.trace1 { "refresh: #{refresh} expired: #{token_info[:expired]}" }
|
|
91
91
|
refresh_token = nil
|
|
92
92
|
if token_data.key?('refresh_token') && !token_data['refresh_token'].eql?('not_supported')
|
|
93
93
|
# save possible refresh token, before deleting the cache
|
|
@@ -99,7 +99,6 @@ module Aspera
|
|
|
99
99
|
# lets try the existing refresh token
|
|
100
100
|
# NOTE: AoC admin token has no refresh, and lives by default 1800secs
|
|
101
101
|
if !refresh_token.nil?
|
|
102
|
-
Log.log.debug{"refresh token=[#{refresh_token}]"}
|
|
103
102
|
begin
|
|
104
103
|
http = create_token_call(base_params(add_secret: true).merge(grant_type: 'refresh_token', refresh_token: refresh_token))
|
|
105
104
|
# Save only if success
|
|
@@ -108,7 +107,7 @@ module Aspera
|
|
|
108
107
|
Factory.instance.persist_mgr.put(@token_cache_id, json_data)
|
|
109
108
|
rescue StandardError => e
|
|
110
109
|
# Refresh token can fail.
|
|
111
|
-
Log.log.warn{"Refresh failed: #{e}"}
|
|
110
|
+
Log.log.warn { "Refresh failed: #{e}" }
|
|
112
111
|
end
|
|
113
112
|
end
|
|
114
113
|
end
|
|
@@ -122,7 +121,7 @@ module Aspera
|
|
|
122
121
|
token_data = JSON.parse(json_data)
|
|
123
122
|
Factory.instance.persist_mgr.put(@token_cache_id, json_data)
|
|
124
123
|
end
|
|
125
|
-
Aspera.assert(token_data.key?(@token_field)){"API error: No such field in answer: #{@token_field}"} unless token_data.nil?
|
|
124
|
+
Aspera.assert(token_data.key?(@token_field)) { "API error: No such field in answer: #{@token_field}" } unless token_data.nil?
|
|
126
125
|
# ok we shall have a token here
|
|
127
126
|
return token_data[@token_field]
|
|
128
127
|
end
|
data/lib/aspera/oauth/boot.rb
CHANGED
|
@@ -19,13 +19,13 @@ module Aspera
|
|
|
19
19
|
Aspera.assert(username, 'Provide --password (cookie) on first use, or --username for cache lookup', type: ParameterError)
|
|
20
20
|
super(**base_params, cache_ids: [username])
|
|
21
21
|
else
|
|
22
|
-
cookies = cookie.split('; ').map{ |p| p.split('=', 2)}.to_h
|
|
22
|
+
cookies = cookie.split('; ').map { |p| p.split('=', 2) }.to_h
|
|
23
23
|
Aspera.assert(cookies.key?('aoc.token'), '--password cookie does not contain aoc.token', type: ParameterError)
|
|
24
24
|
token = cookies['aoc.token']
|
|
25
25
|
decoded = Factory.instance.decode_token(token)
|
|
26
|
-
Aspera.assert_type(decoded, Hash){'Boot: token is not a decodable JWT'}
|
|
26
|
+
Aspera.assert_type(decoded, Hash) { 'Boot: token is not a decodable JWT' }
|
|
27
27
|
sub = decoded['sub']
|
|
28
|
-
Aspera.assert(username.nil? || username.eql?(sub)){"Boot: --username #{username} does not match token subject #{sub}"}
|
|
28
|
+
Aspera.assert(username.nil? || username.eql?(sub)) { "Boot: --username #{username} does not match token subject #{sub}" }
|
|
29
29
|
super(**base_params, cache_ids: [sub])
|
|
30
30
|
token_data = {Factory::TOKEN_FIELD => token}
|
|
31
31
|
token_data['refresh_token'] = cookies['aoc.refresh'] if cookies.key?('aoc.refresh')
|
data/lib/aspera/oauth/factory.rb
CHANGED
|
@@ -41,7 +41,7 @@ module Aspera
|
|
|
41
41
|
# @param authorization [String] The authorization header value
|
|
42
42
|
# @return [String] The bearer token without the scheme prefix
|
|
43
43
|
def bearer_token(authorization)
|
|
44
|
-
Aspera.assert(bearer_auth?(authorization)){'not a bearer token, wrong prefix scheme'}
|
|
44
|
+
Aspera.assert(bearer_auth?(authorization)) { 'not a bearer token, wrong prefix scheme' }
|
|
45
45
|
return authorization.delete_prefix(SPACE_BEARER_AUTH_SCHEME)
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -178,7 +178,7 @@ module Aspera
|
|
|
178
178
|
def register_token_creator(creator_class)
|
|
179
179
|
Aspera.assert_type(creator_class, Class)
|
|
180
180
|
id = Factory.class_to_id(creator_class)
|
|
181
|
-
Log.log.debug{"registering creator for #{id}"}
|
|
181
|
+
Log.log.debug { "registering creator for #{id}" }
|
|
182
182
|
@token_type_classes[id] = creator_class
|
|
183
183
|
nil
|
|
184
184
|
end
|
|
@@ -189,12 +189,12 @@ module Aspera
|
|
|
189
189
|
def create(**parameters)
|
|
190
190
|
Aspera.assert_type(parameters, Hash)
|
|
191
191
|
id = parameters[:grant_method]
|
|
192
|
-
Aspera.assert(@token_type_classes.key?(id)){"token grant method unknown: '#{id}'"}
|
|
193
|
-
create_parameters = parameters.reject{ |k, _v| k.eql?(:grant_method)}
|
|
192
|
+
Aspera.assert(@token_type_classes.key?(id)) { "token grant method unknown: '#{id}'" }
|
|
193
|
+
create_parameters = parameters.reject { |k, _v| k.eql?(:grant_method) }
|
|
194
194
|
@token_type_classes[id].new(**create_parameters)
|
|
195
195
|
end
|
|
196
196
|
end
|
|
197
197
|
# JSON Web Signature (JWS) compact serialization: https://datatracker.ietf.org/doc/html/rfc7515
|
|
198
|
-
Factory.instance.register_decoder(lambda{ |token| parts = token.split('.'); Aspera.assert_values(parts.length, [3]){'JWS token parts'}; JSON.parse(Base64.decode64(parts[1]))}) # rubocop:disable Style/Semicolon
|
|
198
|
+
Factory.instance.register_decoder(lambda { |token| parts = token.split('.'); Aspera.assert_values(parts.length, [3]) { 'JWS token parts' }; JSON.parse(Base64.decode64(parts[1])) }) # rubocop:disable Style/Semicolon
|
|
199
199
|
end
|
|
200
200
|
end
|
data/lib/aspera/oauth/jwt.rb
CHANGED
|
@@ -36,10 +36,10 @@ module Aspera
|
|
|
36
36
|
cache_ids: [],
|
|
37
37
|
**base_params
|
|
38
38
|
)
|
|
39
|
-
Aspera.assert_type(private_key_obj, OpenSSL::PKey::RSA){'private_key_obj'}
|
|
40
|
-
Aspera.assert_type(payload, Hash){'payload'}
|
|
41
|
-
Aspera.assert_type(headers, Hash){'headers'}
|
|
42
|
-
Aspera.assert_type(cache_ids, Array){'cache ids'}
|
|
39
|
+
Aspera.assert_type(private_key_obj, OpenSSL::PKey::RSA) { 'private_key_obj' }
|
|
40
|
+
Aspera.assert_type(payload, Hash) { 'payload' }
|
|
41
|
+
Aspera.assert_type(headers, Hash) { 'headers' }
|
|
42
|
+
Aspera.assert_type(cache_ids, Array) { 'cache ids' }
|
|
43
43
|
new_cache_ids = cache_ids.clone.push(payload[:sub])
|
|
44
44
|
super(**base_params, cache_ids: new_cache_ids)
|
|
45
45
|
@private_key_obj = private_key_obj
|
|
@@ -50,7 +50,7 @@ module Aspera
|
|
|
50
50
|
def create_token
|
|
51
51
|
require 'jwt'
|
|
52
52
|
seconds_since_epoch = Time.now.to_i
|
|
53
|
-
Log.log.debug{"seconds_since_epoch=#{seconds_since_epoch}"}
|
|
53
|
+
Log.log.debug { "seconds_since_epoch=#{seconds_since_epoch}" }
|
|
54
54
|
jwt_payload = {
|
|
55
55
|
exp: seconds_since_epoch + OAuth::Factory.instance.parameters[:jwt_expiry_offset_sec], # expiration time
|
|
56
56
|
nbf: seconds_since_epoch - OAuth::Factory.instance.parameters[:jwt_accepted_offset_sec], # not before
|
|
@@ -58,9 +58,7 @@ module Aspera
|
|
|
58
58
|
jti: SecureRandom.uuid # JWT id
|
|
59
59
|
}.merge(@additional_payload)
|
|
60
60
|
Log.dump(:jwt_payload, jwt_payload)
|
|
61
|
-
Log.log.debug{"private=[#{@private_key_obj}]"}
|
|
62
61
|
assertion = JWT.encode(jwt_payload, @private_key_obj, 'RS256', @headers)
|
|
63
|
-
Log.log.debug{"assertion=[#{assertion}]"}
|
|
64
62
|
return create_token_call(base_params.merge(grant_type: GRANT_TYPE, assertion: assertion))
|
|
65
63
|
end
|
|
66
64
|
end
|
data/lib/aspera/oauth/web.rb
CHANGED
|
@@ -22,9 +22,9 @@ module Aspera
|
|
|
22
22
|
@redirect_uri = redirect_uri
|
|
23
23
|
@path_authorize = path_authorize
|
|
24
24
|
uri = URI.parse(@redirect_uri)
|
|
25
|
-
Aspera.assert_values(uri.scheme, %w[http https]){'redirect_uri scheme must be http or https'}
|
|
25
|
+
Aspera.assert_values(uri.scheme, %w[http https]) { 'redirect_uri scheme must be http or https' }
|
|
26
26
|
Aspera.assert(!uri.port.nil?, 'redirect_uri must have a port')
|
|
27
|
-
|
|
27
|
+
Aspera.assert(%w[127.0.0.1 ::1 localhost].include?(uri.host)) { 'redirect_uri host must be localhost or loopback address' }
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def create_token
|
|
@@ -35,14 +35,14 @@ module Aspera
|
|
|
35
35
|
base_params.merge(response_type: 'code', redirect_uri: @redirect_uri, state: random_state)
|
|
36
36
|
)
|
|
37
37
|
# here, we need a human to authorize on a web page
|
|
38
|
-
Log.log.debug{"login_page_url=#{login_page_url}"}
|
|
38
|
+
Log.log.debug { "login_page_url=#{login_page_url}" }
|
|
39
39
|
# start a web server to receive request code
|
|
40
40
|
web_server = WebAuth.new(@redirect_uri, self.class.additional_info)
|
|
41
41
|
# start browser on login page
|
|
42
42
|
Environment.instance.open_uri(login_page_url)
|
|
43
43
|
# wait for code in request
|
|
44
44
|
received_params = web_server.received_request
|
|
45
|
-
Aspera.assert(random_state.eql?(received_params['state'])){'wrong received state'}
|
|
45
|
+
Aspera.assert(random_state.eql?(received_params['state'])) { 'wrong received state' }
|
|
46
46
|
# exchange code for token
|
|
47
47
|
return create_token_call(base_params(add_secret: true).merge(
|
|
48
48
|
grant_type: 'authorization_code',
|
|
@@ -8,9 +8,9 @@ module Aspera
|
|
|
8
8
|
# Persist data on file system
|
|
9
9
|
class PersistencyActionOnce
|
|
10
10
|
DELETE_DEFAULT = lambda(&:empty?)
|
|
11
|
-
PARSE_DEFAULT = lambda{ |t| JSON.parse(t)}
|
|
12
|
-
FORMAT_DEFAULT = lambda{ |h| JSON.generate(h)}
|
|
13
|
-
MERGE_DEFAULT = lambda{ |current, file| current.concat(file).uniq rescue current}
|
|
11
|
+
PARSE_DEFAULT = lambda { |t| JSON.parse(t) }
|
|
12
|
+
FORMAT_DEFAULT = lambda { |h| JSON.generate(h) }
|
|
13
|
+
MERGE_DEFAULT = lambda { |current, file| current.concat(file).uniq rescue current }
|
|
14
14
|
MANAGER_METHODS = %i[get put delete]
|
|
15
15
|
private_constant :DELETE_DEFAULT, :PARSE_DEFAULT, :FORMAT_DEFAULT, :MERGE_DEFAULT, :MANAGER_METHODS
|
|
16
16
|
|
|
@@ -22,7 +22,7 @@ module Aspera
|
|
|
22
22
|
# @param format [Proc] Optional dump method (default to JSON)
|
|
23
23
|
# @param merge [Proc] Optional merge data from file to current data
|
|
24
24
|
def initialize(manager:, data:, id:, delete: DELETE_DEFAULT, parse: PARSE_DEFAULT, format: FORMAT_DEFAULT, merge: MERGE_DEFAULT)
|
|
25
|
-
Aspera.assert(MANAGER_METHODS.all?{ |i| manager.respond_to?(i)}){"Manager must answer to #{MANAGER_METHODS}"}
|
|
25
|
+
Aspera.assert(MANAGER_METHODS.all? { |i| manager.respond_to?(i) }) { "Manager must answer to #{MANAGER_METHODS}" }
|
|
26
26
|
Aspera.assert(!data.nil?, 'data must not be nil')
|
|
27
27
|
Aspera.assert_type(id, String)
|
|
28
28
|
Aspera.assert(!id.empty?, 'id must not be empty')
|
|
@@ -15,19 +15,19 @@ module Aspera
|
|
|
15
15
|
def initialize(folder)
|
|
16
16
|
@cache = {}
|
|
17
17
|
@folder = folder
|
|
18
|
-
Log.log.debug{"persistency folder: #{@folder}"}
|
|
18
|
+
Log.log.debug { "persistency folder: #{@folder}" }
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
# Get value of persisted item
|
|
22
22
|
# @param object_id [String] Identifier of persisted item
|
|
23
23
|
# @return [String, nil] Persisted value, or nil if not found
|
|
24
24
|
def get(object_id)
|
|
25
|
-
Log.log.debug{"persistency get: #{object_id}"}
|
|
25
|
+
Log.log.debug { "persistency get: #{object_id}" }
|
|
26
26
|
if @cache.key?(object_id)
|
|
27
27
|
Log.log.debug('got from memory cache')
|
|
28
28
|
else
|
|
29
29
|
persist_filepath = id_to_filepath(object_id)
|
|
30
|
-
Log.log.debug{"persistency = #{persist_filepath}"}
|
|
30
|
+
Log.log.debug { "persistency = #{persist_filepath}" }
|
|
31
31
|
if File.exist?(persist_filepath)
|
|
32
32
|
Log.log.debug('got from file cache')
|
|
33
33
|
@cache[object_id] = File.read(persist_filepath)
|
|
@@ -43,7 +43,7 @@ module Aspera
|
|
|
43
43
|
def put(object_id, value)
|
|
44
44
|
Aspera.assert_type(value, String)
|
|
45
45
|
persist_filepath = id_to_filepath(object_id)
|
|
46
|
-
Log.log.debug{"persistency saving: #{persist_filepath}"}
|
|
46
|
+
Log.log.debug { "persistency saving: #{persist_filepath}" }
|
|
47
47
|
FileUtils.rm_f(persist_filepath)
|
|
48
48
|
File.write(persist_filepath, value)
|
|
49
49
|
Environment.restrict_file_access(persist_filepath)
|
|
@@ -55,7 +55,7 @@ module Aspera
|
|
|
55
55
|
# @param object_id [String] Identifier of persisted item
|
|
56
56
|
def delete(object_id)
|
|
57
57
|
persist_filepath = id_to_filepath(object_id)
|
|
58
|
-
Log.log.debug{"persistency deleting: #{persist_filepath}"}
|
|
58
|
+
Log.log.debug { "persistency deleting: #{persist_filepath}" }
|
|
59
59
|
FileUtils.rm_f(persist_filepath)
|
|
60
60
|
@cache.delete(object_id)
|
|
61
61
|
end
|
|
@@ -68,11 +68,11 @@ module Aspera
|
|
|
68
68
|
garbage_files = current_files(persist_category)
|
|
69
69
|
if !max_age_seconds.nil?
|
|
70
70
|
current_time = Time.now
|
|
71
|
-
garbage_files.select!{ |filepath| (current_time - File.stat(filepath).mtime).to_i > max_age_seconds}
|
|
71
|
+
garbage_files.select! { |filepath| (current_time - File.stat(filepath).mtime).to_i > max_age_seconds }
|
|
72
72
|
end
|
|
73
73
|
garbage_files.each do |filepath|
|
|
74
74
|
File.delete(filepath)
|
|
75
|
-
Log.log.debug{"persistency deleted expired: #{filepath}"}
|
|
75
|
+
Log.log.debug { "persistency deleted expired: #{filepath}" }
|
|
76
76
|
end
|
|
77
77
|
@cache.clear
|
|
78
78
|
return garbage_files
|
|
@@ -86,7 +86,7 @@ module Aspera
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
def current_items(persist_category)
|
|
89
|
-
current_files(persist_category).to_h{ |i| [File.basename(i, FILE_SUFFIX), File.read(i)]}
|
|
89
|
+
current_files(persist_category).to_h { |i| [File.basename(i, FILE_SUFFIX), File.read(i)] }
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
private
|
|
@@ -81,15 +81,15 @@ module Aspera
|
|
|
81
81
|
# @return [Symbol] file type, one of enum CONVERSION_TYPES
|
|
82
82
|
# @raise [RuntimeError] if no conversion type found
|
|
83
83
|
def conversion_type(filepath, mimetype)
|
|
84
|
-
Log.log.debug{"conversion_type(#{filepath},mime=#{mimetype},magic=#{@use_mimemagic})"}
|
|
84
|
+
Log.log.debug { "conversion_type(#{filepath},mime=#{mimetype},magic=#{@use_mimemagic})" }
|
|
85
85
|
# Default type or empty means no type
|
|
86
86
|
mimetype = TYPE_NOT_FOUND if mimetype.nil? || (mimetype.is_a?(String) && mimetype.empty?)
|
|
87
87
|
mimetype = Marcel::MimeType.for(Pathname.new(filepath), name: File.basename(filepath), declared_type: mimetype)
|
|
88
88
|
mimetype = 'text/plain' if mimetype.eql?(TYPE_NOT_FOUND) && ascii_text_file?(filepath)
|
|
89
|
-
Aspera.assert(!mimetype.eql?(TYPE_NOT_FOUND)){"no MIME type found for #{File.basename(filepath)}"}
|
|
89
|
+
Aspera.assert(!mimetype.eql?(TYPE_NOT_FOUND)) { "no MIME type found for #{File.basename(filepath)}" }
|
|
90
90
|
conversion_type = mime_to_type(mimetype)
|
|
91
|
-
Aspera.assert(!conversion_type.nil?){"no conversion type found for #{File.basename(filepath)}"}
|
|
92
|
-
Log.log.trace1{"conversion_type(#{File.basename(filepath)}): #{conversion_type.class.name} [#{conversion_type}]"}
|
|
91
|
+
Aspera.assert(!conversion_type.nil?) { "no conversion type found for #{File.basename(filepath)}" }
|
|
92
|
+
Log.log.trace1 { "conversion_type(#{File.basename(filepath)}): #{conversion_type.class.name} [#{conversion_type}]" }
|
|
93
93
|
return conversion_type
|
|
94
94
|
end
|
|
95
95
|
|