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