aspera-cli 4.0.0.pre3 → 4.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +695 -205
- data/bin/dascli +13 -0
- data/docs/README.erb.md +615 -157
- data/docs/test_env.conf +23 -5
- data/docs/transfer_spec.html +1 -1
- data/examples/aoc.rb +14 -3
- data/examples/faspex4.rb +78 -0
- data/lib/aspera/aoc.rb +87 -108
- data/lib/aspera/cli/formater.rb +2 -0
- data/lib/aspera/cli/main.rb +46 -34
- data/lib/aspera/cli/plugin.rb +9 -4
- data/lib/aspera/cli/plugins/alee.rb +1 -1
- data/lib/aspera/cli/plugins/aoc.rb +207 -182
- data/lib/aspera/cli/plugins/ats.rb +2 -2
- data/lib/aspera/cli/plugins/config.rb +173 -117
- data/lib/aspera/cli/plugins/console.rb +2 -2
- data/lib/aspera/cli/plugins/faspex.rb +51 -36
- data/lib/aspera/cli/plugins/faspex5.rb +82 -41
- data/lib/aspera/cli/plugins/node.rb +3 -3
- data/lib/aspera/cli/plugins/preview.rb +35 -25
- data/lib/aspera/cli/plugins/server.rb +23 -8
- data/lib/aspera/cli/transfer_agent.rb +7 -6
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/cos_node.rb +33 -28
- data/lib/aspera/environment.rb +2 -2
- data/lib/aspera/fasp/connect.rb +28 -21
- data/lib/aspera/fasp/http_gw.rb +140 -28
- data/lib/aspera/fasp/installation.rb +101 -53
- data/lib/aspera/fasp/local.rb +88 -45
- data/lib/aspera/fasp/manager.rb +15 -0
- data/lib/aspera/fasp/node.rb +4 -4
- data/lib/aspera/fasp/parameters.rb +6 -18
- data/lib/aspera/fasp/resume_policy.rb +13 -12
- data/lib/aspera/log.rb +1 -1
- data/lib/aspera/node.rb +61 -1
- data/lib/aspera/oauth.rb +49 -46
- data/lib/aspera/persistency_folder.rb +9 -4
- data/lib/aspera/preview/file_types.rb +53 -21
- data/lib/aspera/preview/generator.rb +3 -3
- data/lib/aspera/rest.rb +29 -18
- data/lib/aspera/secrets.rb +20 -0
- data/lib/aspera/temp_file_manager.rb +19 -0
- data/lib/aspera/web_auth.rb +105 -0
- metadata +42 -22
data/lib/aspera/fasp/manager.rb
CHANGED
@@ -45,6 +45,18 @@ module Aspera
|
|
45
45
|
end
|
46
46
|
end # notify_listeners
|
47
47
|
|
48
|
+
def notify_begin(id,size)
|
49
|
+
notify_listeners('emulated',{LISTENER_SESSION_ID_B=>id,'Type'=>'NOTIFICATION','PreTransferBytes'=>size})
|
50
|
+
end
|
51
|
+
|
52
|
+
def notify_progress(id,size)
|
53
|
+
notify_listeners('emulated',{LISTENER_SESSION_ID_B=>id,'Type'=>'STATS','Bytescont'=>size})
|
54
|
+
end
|
55
|
+
|
56
|
+
def notify_end(id)
|
57
|
+
notify_listeners('emulated',{LISTENER_SESSION_ID_B=>id,'Type'=>'DONE'})
|
58
|
+
end
|
59
|
+
|
48
60
|
public
|
49
61
|
LISTENER_SESSION_ID_B='ListenerSessionId'
|
50
62
|
LISTENER_SESSION_ID_S='listener_session_id'
|
@@ -60,6 +72,9 @@ module Aspera
|
|
60
72
|
# start_transfer(transfer_spec,options) : start and wait for completion
|
61
73
|
# wait_for_transfers_completion : wait for termination of all transfers, @return list of : :success or error message
|
62
74
|
# optional: shutdown
|
75
|
+
|
76
|
+
# This checks the validity of the value returned by wait_for_transfers_completion
|
77
|
+
# it must be a list of :success or exception
|
63
78
|
def self.validate_status_list(statuses)
|
64
79
|
raise "internal error: bad statuses type: #{statuses.class}" unless statuses.is_a?(Array)
|
65
80
|
raise "internal error: bad statuses content: #{statuses}" unless statuses.select{|i|!i.eql?(:success) and !i.is_a?(StandardError)}.empty?
|
data/lib/aspera/fasp/node.rb
CHANGED
@@ -55,7 +55,7 @@ module Aspera
|
|
55
55
|
trdata=node_api_.read("ops/transfers/#{@transfer_id}")[:data] || {"status"=>"unknown"} rescue {"status"=>"waiting(read error)"}
|
56
56
|
case trdata['status']
|
57
57
|
when 'completed'
|
58
|
-
|
58
|
+
notify_end(@transfer_id)
|
59
59
|
break
|
60
60
|
when 'waiting','partially_completed','unknown','waiting(read error)'
|
61
61
|
if spinner.nil?
|
@@ -69,10 +69,10 @@ module Aspera
|
|
69
69
|
#puts "running: sessions:#{trdata["sessions"].length}, #{trdata["sessions"].map{|i| i['bytes_transferred']}.join(',')}"
|
70
70
|
if !started and trdata['precalc'].is_a?(Hash) and
|
71
71
|
trdata['precalc']['status'].eql?('ready')
|
72
|
-
|
72
|
+
notify_begin(@transfer_id,trdata['precalc']['bytes_expected'])
|
73
73
|
started=true
|
74
74
|
else
|
75
|
-
|
75
|
+
notify_progress(@transfer_id,trdata['bytes_transferred'])
|
76
76
|
end
|
77
77
|
else
|
78
78
|
Log.log.warn("trdata -> #{trdata}")
|
@@ -81,7 +81,7 @@ module Aspera
|
|
81
81
|
sleep 1
|
82
82
|
end
|
83
83
|
#TODO get status of sessions
|
84
|
-
return []
|
84
|
+
return []
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
@@ -16,10 +16,6 @@ module Aspera
|
|
16
16
|
# because of garbage collection takes any file there
|
17
17
|
# this could be refined, as , for instance, on macos, temp folder is already user specific
|
18
18
|
@@file_list_folder=TempFileManager.instance.new_file_path_global('asession_filelists')
|
19
|
-
SEC_IN_DAY=86400
|
20
|
-
# assume no transfer last longer than this
|
21
|
-
# (garbage collect file list which were not deleted after transfer)
|
22
|
-
FILE_LIST_AGE_MAX_SEC=5*SEC_IN_DAY
|
23
19
|
PARAM_DEFINITION={
|
24
20
|
# parameters with env vars
|
25
21
|
'remote_password' => { :type => :envvar, :variable=>'ASPERA_SCP_PASS'},
|
@@ -63,7 +59,7 @@ module Aspera
|
|
63
59
|
'exclude_older_than' => { :type => :opt_with_arg, :accepted_types=>Integer},
|
64
60
|
'preserve_acls' => { :type => :opt_with_arg, :accepted_types=>String},
|
65
61
|
'move_after_transfer' => { :type => :opt_with_arg, :accepted_types=>String},
|
66
|
-
'multi_session_threshold' => { :type => :opt_with_arg, :accepted_types=>
|
62
|
+
'multi_session_threshold' => { :type => :opt_with_arg, :accepted_types=>Integer},
|
67
63
|
# non standard parameters
|
68
64
|
'EX_fasp_proxy_url' => { :type => :opt_with_arg, :option_switch=>'--proxy',:accepted_types=>String},
|
69
65
|
'EX_http_proxy_url' => { :type => :opt_with_arg, :option_switch=>'-x',:accepted_types=>String},
|
@@ -82,11 +78,12 @@ module Aspera
|
|
82
78
|
'lock_rate_policy' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
|
83
79
|
'lock_min_rate' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
|
84
80
|
'lock_target_rate' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
|
85
|
-
|
81
|
+
'authentication' => { :type => :ignore, :accepted_types=>String}, # value = token
|
86
82
|
'https_fallback_port' => { :type => :ignore, :accepted_types=>Integer}, # same as http fallback, option -t ?
|
87
83
|
'content_protection' => { :type => :ignore, :accepted_types=>String},
|
88
84
|
'cipher_allowed' => { :type => :ignore, :accepted_types=>String},
|
89
85
|
'multi_session' => { :type => :ignore, :accepted_types=>Integer}, # managed
|
86
|
+
'obfuscate_file_names' => { :type => :ignore, :accepted_types=>Aspera::CommandLineBuilder::BOOLEAN_CLASSES},
|
90
87
|
# optional tags ( additional option to generate: {:space=>' ',:object_nl=>' ',:space_before=>'+',:array_nl=>'1'} )
|
91
88
|
'tags' => { :type => :opt_with_arg, :option_switch=>'--tags64',:accepted_types=>Hash,:encode=>lambda{|tags|Base64.strict_encode64(JSON.generate(tags))}},
|
92
89
|
# special processing @builder.process_param( called individually
|
@@ -100,7 +97,7 @@ module Aspera
|
|
100
97
|
'wss_port' => { :type => :defer, :accepted_types=>Integer},
|
101
98
|
}
|
102
99
|
|
103
|
-
private_constant :
|
100
|
+
private_constant :PARAM_DEFINITION
|
104
101
|
|
105
102
|
def initialize(job_spec,options)
|
106
103
|
@job_spec=job_spec
|
@@ -207,18 +204,9 @@ module Aspera
|
|
207
204
|
# temp file list files are created here
|
208
205
|
def self.file_list_folder=(v)
|
209
206
|
@@file_list_folder=v
|
210
|
-
|
207
|
+
if !@@file_list_folder.nil?
|
211
208
|
FileUtils.mkdir_p(@@file_list_folder)
|
212
|
-
|
213
|
-
Dir.entries(@@file_list_folder).each do |name|
|
214
|
-
file_path=File.join(@@file_list_folder,name)
|
215
|
-
age_sec=(Time.now - File.stat(file_path).mtime).to_i
|
216
|
-
# check age of file, delete too old
|
217
|
-
if File.file?(file_path) and age_sec > FILE_LIST_AGE_MAX_SEC
|
218
|
-
Log.log.debug("garbage collecting #{name}")
|
219
|
-
File.delete(file_path)
|
220
|
-
end
|
221
|
-
end
|
209
|
+
TempFileManager.instance.cleanup_expired(@@file_list_folder)
|
222
210
|
end
|
223
211
|
end
|
224
212
|
|
@@ -14,17 +14,21 @@ module Aspera
|
|
14
14
|
:sleep_max => 60
|
15
15
|
}
|
16
16
|
|
17
|
-
|
17
|
+
# @param params see DEFAULTS
|
18
|
+
def initialize(params=nil)
|
18
19
|
@parameters=DEFAULTS.clone
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
if !params.nil?
|
21
|
+
raise "expecting Hash (or nil), but have #{params.class}" unless params.is_a?(Hash)
|
22
|
+
params.each do |k,v|
|
23
|
+
if DEFAULTS.has_key?(k)
|
24
|
+
raise "#{k} must be Integer" unless v.is_a?(Integer)
|
25
|
+
@parameters[k]=v
|
26
|
+
else
|
27
|
+
raise "unknown resume parameter: #{k}, expect one of #{DEFAULTS.keys.map{|i|i.to_s}.join(",")}"
|
28
|
+
end
|
26
29
|
end
|
27
30
|
end
|
31
|
+
Log.log.debug("resume params=#{@parameters}")
|
28
32
|
end
|
29
33
|
|
30
34
|
# calls block a number of times (resumes) until success or limit reached
|
@@ -45,10 +49,7 @@ module Aspera
|
|
45
49
|
# failure in ascp
|
46
50
|
if e.retryable? then
|
47
51
|
# exit if we exceed the max number of retry
|
48
|
-
|
49
|
-
Log.log.error "Maximum number of retry reached"
|
50
|
-
raise Fasp::Error,"max retry after: [#{status[:message]}]"
|
51
|
-
end
|
52
|
+
raise Fasp::Error,'Maximum number of retry reached' if remaining_resumes <= 0
|
52
53
|
else
|
53
54
|
# give one chance only to non retryable errors
|
54
55
|
unless remaining_resumes.eql?(@parameters[:iter_max])
|
data/lib/aspera/log.rb
CHANGED
@@ -14,7 +14,7 @@ module Aspera
|
|
14
14
|
attr_reader :logger
|
15
15
|
attr_reader :logger_type
|
16
16
|
# levels are :debug,:info,:warn,:error,fatal,:unknown
|
17
|
-
def self.levels; Logger::Severity.constants.map{|c|
|
17
|
+
def self.levels; Logger::Severity.constants.sort{|a,b|Logger::Severity.const_get(a)<=>Logger::Severity.const_get(b)}.map{|c|c.downcase.to_sym};end
|
18
18
|
|
19
19
|
# where logs are sent to
|
20
20
|
def self.logtypes; [:stderr,:stdout,:syslog];end
|
data/lib/aspera/node.rb
CHANGED
@@ -1,14 +1,74 @@
|
|
1
|
+
require 'aspera/rest'
|
2
|
+
require 'aspera/log'
|
1
3
|
require 'zlib'
|
2
4
|
require 'base64'
|
5
|
+
|
3
6
|
module Aspera
|
4
7
|
# Provides additional functions using node API.
|
5
8
|
class Node < Rest
|
9
|
+
# permissions
|
10
|
+
ACCESS_LEVELS=['delete','list','mkdir','preview','read','rename','write']
|
11
|
+
MATCH_EXEC_PREFIX='exec:'
|
12
|
+
|
13
|
+
# for information only
|
6
14
|
def self.decode_bearer_token(token)
|
7
15
|
return JSON.parse(Zlib::Inflate.inflate(Base64.decode64(token)).partition('==SIGNATURE==').first)
|
8
16
|
end
|
17
|
+
|
18
|
+
# for access keys: provide expression to match entry in folder
|
19
|
+
# if no prefix: regex
|
20
|
+
# if prefix: ruby code
|
21
|
+
# if filder is nil, then always match
|
22
|
+
def self.file_matcher(match_expression)
|
23
|
+
match_expression||="#{MATCH_EXEC_PREFIX}true"
|
24
|
+
if match_expression.start_with?(MATCH_EXEC_PREFIX)
|
25
|
+
return eval "lambda{|f|#{match_expression[MATCH_EXEC_PREFIX.length..-1]}}"
|
26
|
+
end
|
27
|
+
return lambda{|f|f['name'].match(/#{match_expression}/)}
|
28
|
+
end
|
29
|
+
|
9
30
|
def initialize(rest_params)
|
10
31
|
super(rest_params)
|
11
|
-
|
32
|
+
end
|
33
|
+
|
34
|
+
# recursively crawl in a folder.
|
35
|
+
# subfolders a processed if the processing method returns true
|
36
|
+
# @param processor must provide a method to process each entry
|
37
|
+
# @param opt options
|
38
|
+
# - top_file_id file id to start at (default = access key root file id)
|
39
|
+
# - top_file_path path of top folder (default = /)
|
40
|
+
# - method processing method (default= process_entry)
|
41
|
+
def crawl(processor,opt={})
|
42
|
+
Log.log.debug("crawl1 #{opt}")
|
43
|
+
# not possible with bearer token
|
44
|
+
opt[:top_file_id] ||= read('access_keys/self')[:data]['root_file_id']
|
45
|
+
opt[:top_file_path] ||= '/'
|
46
|
+
opt[:method] ||= :process_entry
|
47
|
+
raise "processor must have #{opt[:method]}" unless processor.respond_to?(opt[:method])
|
48
|
+
Log.log.debug("crawl #{opt}")
|
49
|
+
#top_info=read("files/#{opt[:top_file_id]}")[:data]
|
50
|
+
folders_to_explore=[{id: opt[:top_file_id], relpath: opt[:top_file_path]}]
|
51
|
+
Log.dump(:folders_to_explore,folders_to_explore)
|
52
|
+
while !folders_to_explore.empty? do
|
53
|
+
current_item = folders_to_explore.shift
|
54
|
+
Log.log.debug("searching #{current_item[:relpath]}".bg_green)
|
55
|
+
# get folder content
|
56
|
+
folder_contents = begin
|
57
|
+
read("files/#{current_item[:id]}/files")[:data]
|
58
|
+
rescue => e
|
59
|
+
Log.log.warn("#{current_item[:relpath]}: #{e.class} #{e.message}")
|
60
|
+
[]
|
61
|
+
end
|
62
|
+
Log.dump(:folder_contents,folder_contents)
|
63
|
+
folder_contents.each do |entry|
|
64
|
+
relative_path=File.join(current_item[:relpath],entry['name'])
|
65
|
+
Log.log.debug("looking #{relative_path}".bg_green)
|
66
|
+
# entry type is file, folder or link
|
67
|
+
if processor.send(opt[:method],entry,relative_path) and entry['type'].eql?('folder')
|
68
|
+
folders_to_explore.push({:id=>entry['id'],:relpath=>relative_path})
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
12
72
|
end
|
13
73
|
end
|
14
74
|
end
|
data/lib/aspera/oauth.rb
CHANGED
@@ -1,22 +1,26 @@
|
|
1
1
|
require 'aspera/open_application'
|
2
|
+
require 'aspera/web_auth'
|
2
3
|
require 'base64'
|
3
4
|
require 'date'
|
4
5
|
require 'socket'
|
5
6
|
require 'securerandom'
|
6
7
|
|
7
8
|
module Aspera
|
8
|
-
#
|
9
|
+
# Implement OAuth 2 for the REST client and generate a bearer token
|
9
10
|
# call get_authorization() to get a token.
|
10
11
|
# bearer tokens are kept in memory and also in a file cache for later re-use
|
11
12
|
# if a token is expired (api returns 4xx), call again get_authorization({:refresh=>true})
|
12
13
|
class Oauth
|
13
14
|
private
|
14
15
|
# remove 5 minutes to account for time offset (TODO: configurable?)
|
15
|
-
|
16
|
+
JWT_NOTBEFORE_OFFSET_SEC=300
|
16
17
|
# one hour validity (TODO: configurable?)
|
17
|
-
|
18
|
+
JWT_EXPIRY_OFFSET_SEC=3600
|
19
|
+
# tokens older than 30 minutes will be discarded from cache
|
20
|
+
TOKEN_CACHE_EXPIRY_SEC=1800
|
21
|
+
# a prefix for persistency of tokens (garbage collect)
|
18
22
|
PERSIST_CATEGORY_TOKEN='token'
|
19
|
-
private_constant :
|
23
|
+
private_constant :JWT_NOTBEFORE_OFFSET_SEC,:JWT_EXPIRY_OFFSET_SEC,:PERSIST_CATEGORY_TOKEN,:TOKEN_CACHE_EXPIRY_SEC
|
20
24
|
class << self
|
21
25
|
# OAuth methods supported
|
22
26
|
def auth_types
|
@@ -28,12 +32,18 @@ module Aspera
|
|
28
32
|
end
|
29
33
|
|
30
34
|
def persist_mgr
|
31
|
-
|
35
|
+
if @persist.nil?
|
36
|
+
Log.log.warn('Not using persistency (use Aspera::Oauth.persist_mgr=Aspera::PersistencyFolder.new)')
|
37
|
+
# create NULL persistency class
|
38
|
+
@persist=Class.new do
|
39
|
+
def get(x);nil;end;def delete(x);nil;end;def put(x,y);nil;end;def garbage_collect(x,y);nil;end
|
40
|
+
end.new
|
41
|
+
end
|
32
42
|
return @persist
|
33
43
|
end
|
34
44
|
|
35
45
|
def flush_tokens
|
36
|
-
persist_mgr.
|
46
|
+
persist_mgr.garbage_collect(PERSIST_CATEGORY_TOKEN,nil)
|
37
47
|
end
|
38
48
|
end
|
39
49
|
|
@@ -79,13 +89,19 @@ module Aspera
|
|
79
89
|
raise "redirect_uri must have a port" if uri.port.nil?
|
80
90
|
# we could check that host is localhost or local address
|
81
91
|
end
|
92
|
+
# cleanup expired tokens
|
93
|
+
self.class.persist_mgr.garbage_collect(PERSIST_CATEGORY_TOKEN,TOKEN_CACHE_EXPIRY_SEC)
|
82
94
|
end
|
83
95
|
|
84
|
-
THANK_YOU_HTML = "<html><head><title>Ok</title></head><body><h1>Thank you !</h1><p>You can close this window.</p></body></html>"
|
85
|
-
|
86
96
|
# open the login page, wait for code and check_code, then return code
|
87
97
|
def goto_page_and_get_code(login_page_url,check_code)
|
88
|
-
|
98
|
+
Log.log.info("login_page_url=#{login_page_url}".bg_red.gray)
|
99
|
+
# start a web server to receive request code
|
100
|
+
webserver=WebAuth.new(@params[:redirect_uri])
|
101
|
+
# start browser on login page
|
102
|
+
OpenApplication.instance.uri(login_page_url)
|
103
|
+
# wait for code in request
|
104
|
+
request_params=webserver.get_request
|
89
105
|
Log.log.error("state does not match") if !check_code.eql?(request_params['state'])
|
90
106
|
code=request_params['code']
|
91
107
|
return code
|
@@ -117,6 +133,9 @@ module Aspera
|
|
117
133
|
|
118
134
|
public
|
119
135
|
|
136
|
+
# used to change parameter, such as scope
|
137
|
+
attr_reader :params
|
138
|
+
|
120
139
|
# @param options : :scope and :refresh
|
121
140
|
def get_authorization(options={})
|
122
141
|
# api scope can be overriden to get auth for other scope
|
@@ -184,14 +203,13 @@ module Aspera
|
|
184
203
|
when :web
|
185
204
|
# AoC Web based Auth
|
186
205
|
check_code=SecureRandom.uuid
|
187
|
-
|
188
|
-
"#{@params[:base_url]}/#{@params[:path_authorize]}",
|
189
|
-
p_client_id_and_scope.merge({
|
206
|
+
auth_params=p_client_id_and_scope.merge({
|
190
207
|
:response_type => 'code',
|
191
208
|
:redirect_uri => @params[:redirect_uri],
|
192
|
-
:client_secret => @params[:client_secret],
|
193
209
|
:state => check_code
|
194
|
-
})
|
210
|
+
})
|
211
|
+
auth_params[:client_secret]=@params[:client_secret] if @params.has_key?(:client_secret)
|
212
|
+
login_page_url=Rest.build_uri("#{@params[:base_url]}/#{@params[:path_authorize]}",auth_params)
|
195
213
|
# here, we need a human to authorize on a web page
|
196
214
|
code=goto_page_and_get_code(login_page_url,check_code)
|
197
215
|
# exchange code for token
|
@@ -211,9 +229,19 @@ module Aspera
|
|
211
229
|
:iss => @params[:client_id], # issuer
|
212
230
|
:sub => @params[:jwt_subject], # subject
|
213
231
|
:aud => @params[:jwt_audience], # audience
|
214
|
-
:nbf => seconds_since_epoch-
|
215
|
-
:exp => seconds_since_epoch+
|
232
|
+
:nbf => seconds_since_epoch-JWT_NOTBEFORE_OFFSET_SEC, # not before
|
233
|
+
:exp => seconds_since_epoch+JWT_EXPIRY_OFFSET_SEC # expiration
|
216
234
|
}
|
235
|
+
# Hum.. compliant ? TODO: remove when Faspex5 API is clarified
|
236
|
+
if @params[:jwt_is_f5]
|
237
|
+
payload[:jti] = SecureRandom.uuid
|
238
|
+
payload[:iat] = seconds_since_epoch
|
239
|
+
payload.delete(:nbf)
|
240
|
+
p_scope[:redirect_uri]="https://127.0.0.1:5000/token"
|
241
|
+
p_scope[:state]=SecureRandom.uuid
|
242
|
+
p_scope[:client_id]=@params[:client_id]
|
243
|
+
@token_auth_api.params[:auth]={:type=>:none}
|
244
|
+
end
|
217
245
|
|
218
246
|
# non standard, only for global ids
|
219
247
|
payload.merge!(@params[:jwt_add]) if @params.has_key?(:jwt_add)
|
@@ -222,8 +250,8 @@ module Aspera
|
|
222
250
|
|
223
251
|
Log.log.debug("private=[#{rsa_private}]")
|
224
252
|
|
225
|
-
Log.log.debug("JWT
|
226
|
-
assertion = JWT.encode(payload, rsa_private, 'RS256')
|
253
|
+
Log.log.debug("JWT payload=[#{payload}]")
|
254
|
+
assertion = JWT.encode(payload, rsa_private, 'RS256',@params[:jwt_headers]||{})
|
227
255
|
|
228
256
|
Log.log.debug("assertion=[#{assertion}]")
|
229
257
|
|
@@ -233,8 +261,10 @@ module Aspera
|
|
233
261
|
}))
|
234
262
|
when :url_token
|
235
263
|
# AoC Public Link
|
264
|
+
params={:url_token=>@params[:url_token]}
|
265
|
+
params[:password]=@params[:password] if @params.has_key?(:password)
|
236
266
|
resp=create_token_advanced({
|
237
|
-
:json_params =>
|
267
|
+
:json_params => params,
|
238
268
|
:url_params => p_scope.merge({
|
239
269
|
:grant_type => 'url_token'
|
240
270
|
})})
|
@@ -288,32 +318,5 @@ module Aspera
|
|
288
318
|
return 'Bearer '+token_data[@params[:token_field]]
|
289
319
|
end
|
290
320
|
|
291
|
-
# open the login page, wait for code and return parameters
|
292
|
-
def self.goto_page_and_get_request(redirect_uri,login_page_url,html_page=THANK_YOU_HTML)
|
293
|
-
Log.log.info "login_page_url=#{login_page_url}".bg_red().gray()
|
294
|
-
# browser start is not blocking, we hope here that starting is slower than opening port
|
295
|
-
OpenApplication.instance.uri(login_page_url)
|
296
|
-
port=URI.parse(redirect_uri).port
|
297
|
-
Log.log.info "listening on port #{port}"
|
298
|
-
request_params=nil
|
299
|
-
TCPServer.open('127.0.0.1', port) { |webserver|
|
300
|
-
Log.log.info "server=#{webserver}"
|
301
|
-
websession = webserver.accept
|
302
|
-
sleep 1 # TODO: sometimes: returns nil ? use webrick ?
|
303
|
-
line = websession.gets.chomp
|
304
|
-
Log.log.info "line=#{line}"
|
305
|
-
if ! line.start_with?('GET /?') then
|
306
|
-
raise "unexpected request"
|
307
|
-
end
|
308
|
-
request = line.partition('?').last.partition(' ').first
|
309
|
-
data=URI.decode_www_form(request)
|
310
|
-
request_params=data.to_h
|
311
|
-
Log.log.debug "request_params=#{request_params}"
|
312
|
-
websession.print "HTTP/1.1 200/OK\r\nContent-type:text/html\r\n\r\n#{html_page}"
|
313
|
-
websession.close
|
314
|
-
}
|
315
|
-
return request_params
|
316
|
-
end
|
317
|
-
|
318
321
|
end # OAuth
|
319
322
|
end # Aspera
|
@@ -55,12 +55,17 @@ module Aspera
|
|
55
55
|
@cache.delete(object_id)
|
56
56
|
end
|
57
57
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
58
|
+
def garbage_collect(persist_category,max_age_seconds=nil)
|
59
|
+
garbage_files=Dir[File.join(@folder,persist_category+'*'+FILE_SUFFIX)]
|
60
|
+
if !max_age_seconds.nil?
|
61
|
+
current_time = Time.now
|
62
|
+
garbage_files.select! { |filepath| (current_time - File.stat(filepath).mtime).to_i > max_age_seconds}
|
63
|
+
end
|
64
|
+
garbage_files.each do |filepath|
|
61
65
|
File.delete(filepath)
|
66
|
+
Log.log.debug("Deleted expired: #{filepath}")
|
62
67
|
end
|
63
|
-
return
|
68
|
+
return garbage_files
|
64
69
|
end
|
65
70
|
|
66
71
|
private
|