aspera-cli 4.21.2 → 4.23.0
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/BUGS.md +1 -1
- data/CHANGELOG.md +402 -374
- data/CONTRIBUTING.md +6 -10
- data/README.md +1018 -687
- data/lib/aspera/agent/base.rb +9 -5
- data/lib/aspera/agent/connect.rb +30 -28
- data/lib/aspera/agent/desktop.rb +29 -25
- data/lib/aspera/agent/direct.rb +137 -125
- data/lib/aspera/agent/httpgw.rb +22 -26
- data/lib/aspera/agent/node.rb +14 -11
- data/lib/aspera/agent/transferd.rb +6 -2
- data/lib/aspera/api/aoc.rb +15 -18
- data/lib/aspera/api/cos_node.rb +1 -1
- data/lib/aspera/api/httpgw.rb +15 -7
- data/lib/aspera/api/node.rb +6 -4
- data/lib/aspera/ascmd.rb +17 -9
- data/lib/aspera/ascp/installation.rb +21 -19
- data/lib/aspera/ascp/management.rb +1 -1
- data/lib/aspera/assert.rb +14 -5
- data/lib/aspera/cli/error.rb +2 -2
- data/lib/aspera/cli/extended_value.rb +38 -19
- data/lib/aspera/cli/formatter.rb +48 -48
- data/lib/aspera/cli/hints.rb +10 -2
- data/lib/aspera/cli/main.rb +190 -168
- data/lib/aspera/cli/manager.rb +16 -16
- data/lib/aspera/cli/plugin.rb +24 -21
- data/lib/aspera/cli/plugin_factory.rb +1 -1
- data/lib/aspera/cli/plugins/alee.rb +1 -1
- data/lib/aspera/cli/plugins/aoc.rb +173 -126
- data/lib/aspera/cli/plugins/ats.rb +19 -17
- data/lib/aspera/cli/plugins/config.rb +87 -98
- data/lib/aspera/cli/plugins/console.rb +5 -3
- data/lib/aspera/cli/plugins/faspex.rb +39 -35
- data/lib/aspera/cli/plugins/faspex5.rb +104 -80
- data/lib/aspera/cli/plugins/faspio.rb +13 -1
- data/lib/aspera/cli/plugins/httpgw.rb +13 -1
- data/lib/aspera/cli/plugins/node.rb +336 -205
- data/lib/aspera/cli/plugins/orchestrator.rb +34 -40
- data/lib/aspera/cli/plugins/preview.rb +3 -3
- data/lib/aspera/cli/plugins/server.rb +7 -6
- data/lib/aspera/cli/plugins/shares.rb +5 -5
- data/lib/aspera/cli/sync_actions.rb +19 -18
- data/lib/aspera/cli/transfer_agent.rb +11 -15
- data/lib/aspera/cli/transfer_progress.rb +2 -2
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/command_line_builder.rb +116 -95
- data/lib/aspera/coverage.rb +4 -3
- data/lib/aspera/data_repository.rb +1 -0
- data/lib/aspera/environment.rb +7 -6
- data/lib/aspera/faspex_gw.rb +14 -14
- data/lib/aspera/faspex_postproc.rb +7 -6
- data/lib/aspera/hash_ext.rb +2 -2
- data/lib/aspera/json_rpc.rb +1 -1
- data/lib/aspera/keychain/encrypted_hash.rb +47 -34
- data/lib/aspera/keychain/factory.rb +41 -0
- data/lib/aspera/keychain/hashicorp_vault.rb +71 -0
- data/lib/aspera/keychain/macos_security.rb +19 -11
- data/lib/aspera/log.rb +29 -34
- data/lib/aspera/nagios.rb +6 -6
- data/lib/aspera/node_simulator.rb +8 -8
- data/lib/aspera/oauth/base.rb +10 -6
- data/lib/aspera/oauth/factory.rb +6 -6
- data/lib/aspera/oauth/url_json.rb +6 -6
- data/lib/aspera/persistency_action_once.rb +6 -4
- data/lib/aspera/persistency_folder.rb +2 -2
- data/lib/aspera/preview/file_types.rb +40 -33
- data/lib/aspera/preview/generator.rb +1 -1
- data/lib/aspera/preview/options.rb +16 -16
- data/lib/aspera/preview/terminal.rb +3 -3
- data/lib/aspera/preview/utils.rb +11 -13
- data/lib/aspera/products/connect.rb +2 -1
- data/lib/aspera/products/desktop.rb +1 -1
- data/lib/aspera/products/transferd.rb +1 -1
- data/lib/aspera/proxy_auto_config.rb +2 -2
- data/lib/aspera/rest.rb +70 -50
- data/lib/aspera/rest_error_analyzer.rb +1 -0
- data/lib/aspera/rest_errors_aspera.rb +1 -1
- data/lib/aspera/secret_hider.rb +5 -5
- data/lib/aspera/ssh.rb +5 -5
- data/lib/aspera/temp_file_manager.rb +1 -0
- data/lib/aspera/timer_limiter.rb +7 -5
- data/lib/aspera/transfer/async_conf.schema.yaml +716 -0
- data/lib/aspera/transfer/convert.rb +29 -0
- data/lib/aspera/transfer/error_info.rb +66 -66
- data/lib/aspera/transfer/parameters.rb +13 -68
- data/lib/aspera/transfer/spec.rb +5 -6
- data/lib/aspera/transfer/spec.schema.yaml +753 -0
- data/lib/aspera/transfer/spec_doc.rb +62 -0
- data/lib/aspera/transfer/sync.rb +37 -76
- data/lib/aspera/transfer/sync_instance.schema.yaml +20 -0
- data/lib/aspera/transfer/sync_session.schema.yaml +86 -0
- data/lib/aspera/transfer/uri.rb +6 -6
- data/lib/aspera/uri_reader.rb +1 -1
- data/lib/aspera/web_auth.rb +1 -1
- data/lib/aspera/web_server_simple.rb +53 -44
- data.tar.gz.sig +0 -0
- metadata +38 -7
- metadata.gz.sig +0 -0
- data/examples/build_package.sh +0 -28
- data/examples/dascli +0 -30
- data/examples/get_proto_file.rb +0 -8
- data/examples/proxy.pac +0 -60
- data/lib/aspera/transfer/spec.yaml +0 -718
@@ -50,10 +50,13 @@ module Aspera
|
|
50
50
|
'archived' => false,
|
51
51
|
'has_content' => true,
|
52
52
|
'received' => true,
|
53
|
-
'completed' => true
|
53
|
+
'completed' => true
|
54
|
+
}.freeze
|
55
|
+
PACKAGE_LIST_DEFAULT_FIELDS = %w[id name created_at files_completed bytes_transferred].freeze
|
54
56
|
# options and parameters for Api::AoC.new
|
55
57
|
OPTIONS_NEW = %i[url auth client_id client_secret scope redirect_uri private_key passphrase username password workspace].freeze
|
56
|
-
|
58
|
+
|
59
|
+
private_constant :REDIRECT_LOCALHOST, :STD_AUTH_TYPES, :ADMIN_OBJECTS, :PACKAGE_RECEIVED_BASE_QUERY, :OPTIONS_NEW, :PACKAGE_LIST_DEFAULT_FIELDS
|
57
60
|
class << self
|
58
61
|
def application_name
|
59
62
|
'Aspera on Cloud'
|
@@ -78,15 +81,16 @@ module Aspera
|
|
78
81
|
}
|
79
82
|
end
|
80
83
|
|
81
|
-
# @param [String] url
|
84
|
+
# @param url [String] url to check
|
82
85
|
# @return [Bool] true if private key is required for the url (i.e. no passcode)
|
83
86
|
def private_key_required?(url)
|
84
87
|
# pub link do not need private key
|
85
88
|
return Api::AoC.link_info(url)[:token].nil?
|
86
89
|
end
|
87
90
|
|
88
|
-
# @param [
|
89
|
-
# @param [
|
91
|
+
# @param object [Plugin] An instance of this class
|
92
|
+
# @param private_key_path [String] path to private key
|
93
|
+
# @param pub_key_pem [String] PEM of public key
|
90
94
|
# @return [Hash] :preset_value, :test_args
|
91
95
|
def wizard(object:, private_key_path: nil, pub_key_pem: nil)
|
92
96
|
# set vars to look like object
|
@@ -121,7 +125,7 @@ module Aspera
|
|
121
125
|
formatter.display_status('Please Login to your Aspera on Cloud instance.')
|
122
126
|
formatter.display_status('Navigate to: 👤 → Account Settings → Profile → Public Key')
|
123
127
|
formatter.display_status('Check or update the value to:'.red.blink)
|
124
|
-
formatter.display_status(pub_key_pem)
|
128
|
+
formatter.display_status(pub_key_pem, hide_secrets: false)
|
125
129
|
if !options.get_option(:test_mode)
|
126
130
|
formatter.display_status('Once updated or validated, press enter.')
|
127
131
|
Environment.instance.open_uri(instance_url)
|
@@ -188,22 +192,28 @@ module Aspera
|
|
188
192
|
options.declare(:auth, 'OAuth type of authentication', values: STD_AUTH_TYPES, default: :jwt)
|
189
193
|
options.declare(:client_id, 'OAuth API client identifier')
|
190
194
|
options.declare(:client_secret, 'OAuth API client secret')
|
191
|
-
options.declare(:scope, 'OAuth scope for AoC API calls'
|
195
|
+
options.declare(:scope, 'OAuth scope for AoC API calls')
|
192
196
|
options.declare(:redirect_uri, 'OAuth API client redirect URI')
|
193
197
|
options.declare(:private_key, 'OAuth JWT RSA private key PEM value (prefix file path with @file:)')
|
194
198
|
options.declare(:passphrase, 'RSA private key passphrase', types: String)
|
195
199
|
options.declare(:workspace, 'Name of workspace', types: [String, NilClass], default: Api::AoC::DEFAULT_WORKSPACE)
|
196
200
|
options.declare(:new_user_option, 'New user creation option for unknown package recipients', types: Hash)
|
197
201
|
options.declare(:validate_metadata, 'Validate shared inbox metadata', values: :bool, default: true)
|
202
|
+
options.declare(:package_folder, 'Field of package to use as folder name, or @none:', types: [String, NilClass])
|
198
203
|
options.parse_options!
|
199
204
|
# add node plugin options (for manual)
|
200
205
|
Node.declare_options(options)
|
201
206
|
end
|
202
207
|
|
203
|
-
def api_from_options(
|
204
|
-
create_values = {
|
208
|
+
def api_from_options(aoc_base_path)
|
209
|
+
create_values = OPTIONS_NEW.each_with_object({
|
210
|
+
subpath: aoc_base_path,
|
211
|
+
secret_finder: config}) do |i, m|
|
212
|
+
m[i] = options.get_option(i) unless options.get_option(i).nil?
|
213
|
+
end
|
214
|
+
create_values[:scope] = Api::AoC::SCOPE_FILES_USER if create_values[:scope].nil?
|
205
215
|
# create an API object with the same options, but with a different subpath
|
206
|
-
return Api::AoC.new(**
|
216
|
+
return Api::AoC.new(**create_values)
|
207
217
|
rescue ArgumentError => e
|
208
218
|
if (m = e.message.match(/missing keyword: :(.*)$/))
|
209
219
|
raise Cli::Error, "Missing option: #{m[1]}"
|
@@ -216,13 +226,31 @@ module Aspera
|
|
216
226
|
@cache_api_aoc = api_from_options(Api::AoC::API_V1)
|
217
227
|
organization = @cache_api_aoc.read('organization')
|
218
228
|
if organization['http_gateway_enabled'] && organization['http_gateway_server_url']
|
219
|
-
transfer.httpgw_url_cb = lambda
|
229
|
+
transfer.httpgw_url_cb = lambda{organization['http_gateway_server_url']}
|
220
230
|
# @cache_api_aoc.current_user_info['connect_disabled']
|
221
231
|
end
|
222
232
|
end
|
223
233
|
return @cache_api_aoc
|
224
234
|
end
|
225
235
|
|
236
|
+
# Generate or update Hash with workspace id and name (option), if not already set
|
237
|
+
# @param hash [Hash, Nil] set in provided hash
|
238
|
+
# @param string [Bool] true to set key as string, else as symbol
|
239
|
+
# @param name [Bool] include name
|
240
|
+
# @return [Hash] with key `workspace_[id,name]` (symbol or string) only if defined
|
241
|
+
def workspace_id_hash(hash: nil, string: false, name: false)
|
242
|
+
info = aoc_api.workspace
|
243
|
+
hash = {} if hash.nil?
|
244
|
+
fields = %i[id]
|
245
|
+
fields.push(:name) if name
|
246
|
+
fields.each do |i|
|
247
|
+
k = "workspace_#{i}"
|
248
|
+
k = k.to_sym unless string
|
249
|
+
hash[k] = info[i] unless info[i].nil? || hash.key?(k)
|
250
|
+
end
|
251
|
+
return hash
|
252
|
+
end
|
253
|
+
|
226
254
|
# Get resource identifier from command line, either directly or from name.
|
227
255
|
# @param resource_class_path url path for resource
|
228
256
|
# @return identifier
|
@@ -240,7 +268,7 @@ module Aspera
|
|
240
268
|
|
241
269
|
# Call block with same query using paging and response information
|
242
270
|
# block must return a hash with :data and :http keys
|
243
|
-
# @return [Hash] {
|
271
|
+
# @return [Hash] {items: , total: }
|
244
272
|
def api_call_paging(base_query={})
|
245
273
|
Aspera.assert_type(base_query, Hash){'query'}
|
246
274
|
Aspera.assert(block_given?)
|
@@ -268,46 +296,59 @@ module Aspera
|
|
268
296
|
item_list += add_items
|
269
297
|
break if !max_items.nil? && item_list.count >= max_items
|
270
298
|
break if !max_pages.nil? && page_count >= max_pages
|
299
|
+
formatter.long_operation_running("#{item_list.count} / #{total_count}") unless total_count.eql?(item_list.count.to_s)
|
271
300
|
end
|
301
|
+
formatter.long_operation_terminated
|
272
302
|
item_list = item_list[0..max_items - 1] if !max_items.nil? && item_list.count > max_items
|
273
|
-
return {
|
303
|
+
return {items: item_list, total: total_count}
|
274
304
|
end
|
275
305
|
|
276
306
|
# read using the query and paging
|
277
307
|
# @return [Hash] {data: , total: }
|
278
308
|
def api_read_all(resource_class_path, base_query={})
|
279
309
|
return api_call_paging(base_query) do |query|
|
280
|
-
aoc_api.call(operation: 'GET', subpath: resource_class_path, headers: {'Accept' =>
|
310
|
+
aoc_api.call(operation: 'GET', subpath: resource_class_path, headers: {'Accept' => Rest::MIME_JSON}, query: query)
|
281
311
|
end
|
282
312
|
end
|
283
313
|
|
284
|
-
#
|
314
|
+
# List all entities, given additional, default and user's queries
|
285
315
|
# @param resource_class_path path to query on API
|
286
316
|
# @param fields fields to display
|
287
317
|
# @param base_query a query applied always
|
288
318
|
# @param default_query default query unless overriden by user
|
319
|
+
# @param &block (Optional) calls block with user's or default query
|
289
320
|
def result_list(resource_class_path, fields: nil, base_query: {}, default_query: {})
|
290
321
|
Aspera.assert_type(base_query, Hash)
|
291
322
|
Aspera.assert_type(default_query, Hash)
|
292
|
-
|
293
|
-
# caller may add specific modifications or checks
|
294
|
-
yield(
|
295
|
-
|
323
|
+
query = query_read_delete(default: default_query)
|
324
|
+
# caller may add specific modifications or checks to query
|
325
|
+
yield(query) if block_given?
|
326
|
+
result = api_read_all(resource_class_path, base_query.merge(query).compact)
|
327
|
+
return Main.result_object_list(result[:items], fields: fields, total: result[:total])
|
296
328
|
end
|
297
329
|
|
330
|
+
# Translates `dropbox_name` to `dropbox_id` and fills current workspace_id
|
298
331
|
def resolve_dropbox_name_default_ws_id(query)
|
299
332
|
if query.key?('dropbox_name')
|
300
333
|
# convenience: specify name instead of id
|
301
|
-
raise '
|
334
|
+
raise 'Use field dropbox_name or dropbox_id, not both' if query.key?('dropbox_id')
|
302
335
|
# TODO : craft a query that looks for dropbox only in current workspace
|
303
|
-
query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query
|
304
|
-
query.delete('dropbox_name')
|
336
|
+
query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query.delete('dropbox_name'))['id']
|
305
337
|
end
|
306
|
-
query
|
338
|
+
workspace_id_hash(hash: query, string: true)
|
307
339
|
# by default show dropbox packages only for dropboxes
|
308
340
|
query['exclude_dropbox_packages'] = !query.key?('dropbox_id') unless query.key?('exclude_dropbox_packages')
|
309
341
|
end
|
310
342
|
|
343
|
+
# @return [Hash] {items,total} with all packages according to combination of user's query and default query
|
344
|
+
def list_all_packages_with_query
|
345
|
+
query = query_read_delete(default: {})
|
346
|
+
Aspera.assert_type(query, Hash){'query'}
|
347
|
+
PACKAGE_RECEIVED_BASE_QUERY.each{ |k, v| query[k] = v unless query.key?(k)}
|
348
|
+
resolve_dropbox_name_default_ws_id(query)
|
349
|
+
return api_read_all('packages', query.compact)
|
350
|
+
end
|
351
|
+
|
311
352
|
NODE4_EXT_COMMANDS = %i[transfer].concat(Node::COMMANDS_GEN4).freeze
|
312
353
|
private_constant :NODE4_EXT_COMMANDS
|
313
354
|
|
@@ -316,9 +357,8 @@ module Aspera
|
|
316
357
|
def execute_nodegen4_command(command_repo, node_id, file_id: nil, scope: nil)
|
317
358
|
top_node_api = aoc_api.node_api_from(
|
318
359
|
node_id: node_id,
|
319
|
-
|
320
|
-
|
321
|
-
scope: scope
|
360
|
+
scope: scope,
|
361
|
+
**workspace_id_hash(name: true)
|
322
362
|
)
|
323
363
|
file_id = top_node_api.read("access_keys/#{top_node_api.app_info[:node_info]['access_key']}")['root_file_id'] if file_id.nil?
|
324
364
|
node_plugin = Node.new(**init_params, api: top_node_api)
|
@@ -410,7 +450,9 @@ module Aspera
|
|
410
450
|
default_fields.push('app_type', 'app_name', 'available', 'direct_authorizations_allowed', 'workspace_authorizations_allowed')
|
411
451
|
when :client, :client_access_key, :dropbox, :group, :package, :saml_configuration, :workspace then default_fields.push('name')
|
412
452
|
when :client_registration_token then default_fields.push('value', 'data.client_subject_scopes', 'created_at')
|
413
|
-
when :contact
|
453
|
+
when :contact
|
454
|
+
default_fields = %w[source_type source_id name email]
|
455
|
+
default_query = {'include_only_user_personal_contacts' => true} if aoc_api.oauth.scope == Api::AoC::SCOPE_FILES_USER
|
414
456
|
when :node then default_fields.push('name', 'host', 'access_key')
|
415
457
|
when :operation then default_fields = nil
|
416
458
|
when :short_link then default_fields.push('short_url', 'data.url_token_data.purpose')
|
@@ -422,8 +464,8 @@ module Aspera
|
|
422
464
|
when :show
|
423
465
|
object = aoc_api.read(resource_instance_path)
|
424
466
|
# default: show all, but certificate
|
425
|
-
fields = object.keys.reject{|k|k.eql?('certificate')}
|
426
|
-
return
|
467
|
+
fields = object.keys.reject{ |k| k.eql?('certificate')}
|
468
|
+
return Main.result_single_object(object, fields: fields)
|
427
469
|
when :modify
|
428
470
|
changes = options.get_next_argument('properties', validation: Hash)
|
429
471
|
return do_bulk_operation(command: command, descr: 'identifier', values: res_id) do |one_id|
|
@@ -453,8 +495,8 @@ module Aspera
|
|
453
495
|
ADMIN_ACTIONS = %i[ats resource usage_reports analytics subscription auth_providers].concat(ADMIN_OBJECTS).freeze
|
454
496
|
|
455
497
|
def execute_admin_action
|
456
|
-
#
|
457
|
-
aoc_api.oauth.scope = Api::AoC::SCOPE_FILES_ADMIN
|
498
|
+
# default scope to admin
|
499
|
+
aoc_api.oauth.scope = Api::AoC::SCOPE_FILES_ADMIN if options.get_option(:scope).nil?
|
458
500
|
command_admin = options.get_next_command(ADMIN_ACTIONS)
|
459
501
|
case command_admin
|
460
502
|
when :resource
|
@@ -529,7 +571,7 @@ module Aspera
|
|
529
571
|
GRAPHQL
|
530
572
|
# cspell:enable
|
531
573
|
result = bss_graphql.create(nil, {query: graphql_query, variables: {organization_id: org['id']}})['data']
|
532
|
-
return
|
574
|
+
return Main.result_single_object(result['aoc']['bssSubscription'])
|
533
575
|
when :usage
|
534
576
|
# cspell:disable
|
535
577
|
graphql_query = <<-GRAPHQL
|
@@ -576,7 +618,7 @@ module Aspera
|
|
576
618
|
aggregate: aggregate,
|
577
619
|
startDate: start_date,
|
578
620
|
endDate: end_date}})['data']
|
579
|
-
return
|
621
|
+
return Main.result_single_object(result['aoc'])
|
580
622
|
end
|
581
623
|
when :ats
|
582
624
|
ats_api = Rest.new(**aoc_api.params.deep_merge({
|
@@ -594,7 +636,7 @@ module Aspera
|
|
594
636
|
when :application_events
|
595
637
|
event_type = command_analytics.to_s
|
596
638
|
events = analytics_api.read("organizations/#{aoc_api.current_user_info['organization_id']}/#{event_type}")[event_type]
|
597
|
-
return
|
639
|
+
return Main.result_object_list(events)
|
598
640
|
when :transfers
|
599
641
|
event_type = command_analytics.to_s
|
600
642
|
filter_resource = options.get_next_argument('resource', accept_list: %i[organizations users nodes])
|
@@ -635,25 +677,26 @@ module Aspera
|
|
635
677
|
config.send_email_template(values: {ev: tr_event})
|
636
678
|
end
|
637
679
|
end
|
638
|
-
return
|
680
|
+
return Main.result_object_list(events)
|
639
681
|
end
|
640
682
|
when :usage_reports
|
641
683
|
aoc_api.context = :files
|
642
|
-
return result_list('usage_reports', base_query:
|
684
|
+
return result_list('usage_reports', base_query: workspace_id_hash)
|
643
685
|
end
|
644
686
|
end
|
645
687
|
|
646
688
|
# Create a shared link for the given entity
|
647
|
-
# @param
|
648
|
-
# @param
|
649
|
-
|
689
|
+
# @param purpose_public [Symbol]
|
690
|
+
# @param shared_data [Hash] information for shared data
|
691
|
+
# @param block [Proc] Optional: called on creation
|
692
|
+
def short_link_command(purpose_public:, **shared_data)
|
650
693
|
link_type = options.get_next_argument('link type', accept_list: %i[public private])
|
651
694
|
purpose_local = case link_type
|
652
695
|
when :public
|
653
696
|
case purpose_public
|
654
697
|
when /package/ then 'send_package_to_dropbox'
|
655
698
|
when /shared/ then 'token_auth_redirection'
|
656
|
-
else
|
699
|
+
else Aspera.error_unexpected_value(purpose_public){'public link purpose'}
|
657
700
|
end
|
658
701
|
when :private then 'shared_folder_auth_link'
|
659
702
|
else Aspera.error_unreachable_line
|
@@ -682,7 +725,7 @@ module Aspera
|
|
682
725
|
result_create_short_link = aoc_api.create('short_links', creation_params)
|
683
726
|
# public: Creation: permission on node
|
684
727
|
yield(result_create_short_link['resource_id']) if block_given? && link_type.eql?(:public)
|
685
|
-
return
|
728
|
+
return Main.result_single_object(result_create_short_link)
|
686
729
|
when :list
|
687
730
|
query = if link_type.eql?(:private)
|
688
731
|
shared_data
|
@@ -718,6 +761,26 @@ module Aspera
|
|
718
761
|
end
|
719
762
|
end
|
720
763
|
|
764
|
+
# @return persistency object if option `once_only` is used.
|
765
|
+
def package_persistency
|
766
|
+
return nil unless options.get_option(:once_only, mandatory: true)
|
767
|
+
# TODO: add query info to id
|
768
|
+
PersistencyActionOnce.new(
|
769
|
+
manager: persistency,
|
770
|
+
data: [],
|
771
|
+
id: IdGenerator.from_list(
|
772
|
+
['aoc_recv',
|
773
|
+
options.get_option(:url, mandatory: true),
|
774
|
+
aoc_api.workspace[:id]
|
775
|
+
].concat(aoc_api.additional_persistence_ids)))
|
776
|
+
end
|
777
|
+
|
778
|
+
def reject_packages_from_persistency(all_packages, skip_ids_persistency)
|
779
|
+
return if skip_ids_persistency.nil?
|
780
|
+
skip_package = skip_ids_persistency.data.each_with_object({}){ |i, m| m[i] = true}
|
781
|
+
all_packages.reject!{ |pkg| skip_package[pkg['id']]}
|
782
|
+
end
|
783
|
+
|
721
784
|
# must be public
|
722
785
|
ACTIONS = %i[reminder servers bearer_token organization tier_restrictions user packages files admin automation gateway].freeze
|
723
786
|
|
@@ -739,29 +802,31 @@ module Aspera
|
|
739
802
|
Rest.new(base_url: "#{Api::AoC.api_base_url}/#{Api::AoC::API_V1}").create('organization_reminders', {email: user_email})
|
740
803
|
return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
|
741
804
|
when :servers
|
742
|
-
return
|
805
|
+
return Main.result_object_list(Rest.new(base_url: "#{Api::AoC.api_base_url}/#{Api::AoC::API_V1}").read('servers'))
|
743
806
|
when :bearer_token
|
744
|
-
return
|
807
|
+
return Main.result_text(aoc_api.oauth.authorization)
|
745
808
|
when :organization
|
746
|
-
return
|
809
|
+
return Main.result_single_object(aoc_api.read('organization'))
|
747
810
|
when :tier_restrictions
|
748
|
-
return
|
811
|
+
return Main.result_single_object(aoc_api.read('tier_restrictions'))
|
749
812
|
when :user
|
750
|
-
case options.get_next_command(%i[workspaces profile preferences])
|
813
|
+
case options.get_next_command(%i[workspaces profile preferences contacts])
|
814
|
+
when :contacts
|
815
|
+
return execute_resource_action(:contact)
|
751
816
|
# when :settings
|
752
|
-
# return
|
817
|
+
# return Main.result_object_list(aoc_api.read('client_settings/'))
|
753
818
|
when :workspaces
|
754
819
|
case options.get_next_command(%i[list current])
|
755
820
|
when :list
|
756
821
|
return result_list('workspaces', fields: %w[id name])
|
757
822
|
when :current
|
758
823
|
aoc_api.context = :files
|
759
|
-
return
|
824
|
+
return Main.result_single_object(aoc_api.workspace)
|
760
825
|
end
|
761
826
|
when :profile
|
762
827
|
case options.get_next_command(%i[show modify])
|
763
828
|
when :show
|
764
|
-
return
|
829
|
+
return Main.result_single_object(aoc_api.current_user_info(exception: true))
|
765
830
|
when :modify
|
766
831
|
aoc_api.update("users/#{aoc_api.current_user_info(exception: true)['id']}", options.get_next_argument('properties', validation: Hash))
|
767
832
|
return Main.result_status('modified')
|
@@ -770,7 +835,7 @@ module Aspera
|
|
770
835
|
user_preferences_res = "users/#{aoc_api.current_user_info(exception: true)['id']}/user_interaction_preferences"
|
771
836
|
case options.get_next_command(%i[show modify])
|
772
837
|
when :show
|
773
|
-
return
|
838
|
+
return Main.result_single_object(aoc_api.read(user_preferences_res))
|
774
839
|
when :modify
|
775
840
|
aoc_api.update(user_preferences_res, options.get_next_argument('properties', validation: Hash))
|
776
841
|
return Main.result_status('modified')
|
@@ -783,26 +848,24 @@ module Aspera
|
|
783
848
|
case options.get_next_command(%i[list show short_link])
|
784
849
|
when :list
|
785
850
|
default_query = {'embed[]' => 'dropbox', 'aggregate_permissions_by_dropbox' => true, 'sort' => 'dropbox_name'}
|
786
|
-
default_query
|
851
|
+
workspace_id_hash(hash: default_query, string: true)
|
787
852
|
return result_list('dropbox_memberships', fields: %w[dropbox_id dropbox.name], default_query: default_query)
|
788
853
|
when :show
|
789
|
-
return
|
854
|
+
return Main.result_single_object(aoc_api.read(get_resource_path_from_args('dropboxes')))
|
790
855
|
when :short_link
|
791
856
|
return short_link_command(
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
purpose_public: 'send_package_to_dropbox')
|
857
|
+
purpose_public: 'send_package_to_dropbox',
|
858
|
+
dropbox_id: get_resource_id_from_args('dropboxes'),
|
859
|
+
name: '',
|
860
|
+
**workspace_id_hash
|
861
|
+
)
|
798
862
|
end
|
799
863
|
when :send
|
800
864
|
package_data = value_create_modify(command: package_command)
|
801
865
|
new_user_option = options.get_option(:new_user_option)
|
802
866
|
option_validate = options.get_option(:validate_metadata)
|
803
|
-
# works for both normal
|
804
|
-
package_data
|
805
|
-
|
867
|
+
# works for both normal user auth and link auth
|
868
|
+
workspace_id_hash(hash: package_data, string: true) unless package_data.key?('workspace_id')
|
806
869
|
if !aoc_api.public_link.nil?
|
807
870
|
aoc_api.assert_public_link_types(%w[send_package_to_user send_package_to_dropbox])
|
808
871
|
box_type = aoc_api.public_link['purpose'].split('_').last
|
@@ -815,88 +878,73 @@ module Aspera
|
|
815
878
|
created_package = aoc_api.create_package_simple(package_data, option_validate, new_user_option)
|
816
879
|
Main.result_transfer(transfer.start(created_package[:spec], rest_token: created_package[:node]))
|
817
880
|
# return all info on package (especially package id)
|
818
|
-
return
|
881
|
+
return Main.result_single_object(created_package[:info])
|
819
882
|
when :receive
|
820
883
|
ids_to_download = nil
|
821
884
|
if !aoc_api.public_link.nil?
|
822
885
|
aoc_api.assert_public_link_types(['view_received_package'])
|
823
|
-
# set the package id
|
886
|
+
# set the package id from link
|
824
887
|
ids_to_download = aoc_api.public_link['data']['package_id']
|
825
888
|
end
|
826
889
|
# get from command line unless it was a public link
|
827
890
|
ids_to_download ||= instance_identifier
|
828
|
-
|
829
|
-
skip_ids_persistency = nil
|
830
|
-
if options.get_option(:once_only, mandatory: true)
|
831
|
-
# TODO: add query info to id
|
832
|
-
skip_ids_persistency = PersistencyActionOnce.new(
|
833
|
-
manager: persistency,
|
834
|
-
data: skip_ids_data,
|
835
|
-
id: IdGenerator.from_list(
|
836
|
-
['aoc_recv',
|
837
|
-
options.get_option(:url, mandatory: true),
|
838
|
-
aoc_api.workspace[:id]
|
839
|
-
].concat(aoc_api.additional_persistence_ids)))
|
840
|
-
end
|
891
|
+
skip_ids_persistency = package_persistency
|
841
892
|
case ids_to_download
|
842
893
|
when SpecialValues::ALL, SpecialValues::INIT
|
843
|
-
|
844
|
-
Aspera.assert_type(query, Hash){'query'}
|
845
|
-
resolve_dropbox_name_default_ws_id(query)
|
846
|
-
# remove from list the ones already downloaded
|
847
|
-
all_ids = api_read_all('packages', query)[:data].map{|e|e['id']}
|
894
|
+
all_packages = list_all_packages_with_query[:items]
|
848
895
|
if ids_to_download.eql?(SpecialValues::INIT)
|
849
|
-
Aspera.assert(skip_ids_persistency){'
|
850
|
-
skip_ids_persistency.data.clear.concat(
|
896
|
+
Aspera.assert(skip_ids_persistency){'INIT requires option once_only'}
|
897
|
+
skip_ids_persistency.data.clear.concat(all_packages.map{ |e| e['id']})
|
851
898
|
skip_ids_persistency.save
|
852
899
|
return Main.result_status("Initialized skip for #{skip_ids_persistency.data.count} package(s)")
|
853
900
|
end
|
854
|
-
#
|
855
|
-
|
901
|
+
# remove from list the ones already downloaded
|
902
|
+
reject_packages_from_persistency(all_packages, skip_ids_persistency)
|
903
|
+
ids_to_download = all_packages.map{ |e| e['id']}
|
904
|
+
formatter.display_status("Found #{ids_to_download.length} package(s).")
|
856
905
|
else
|
906
|
+
# single id to array
|
857
907
|
ids_to_download = [ids_to_download] unless ids_to_download.is_a?(Array)
|
858
908
|
end
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
[{'source' => '.'}]
|
864
|
-
end
|
865
|
-
# list here
|
909
|
+
# download all files, or specified list only
|
910
|
+
ts_paths = transfer.ts_source_paths(default: ['.'])
|
911
|
+
per_package_field = options.get_option(:package_folder)
|
912
|
+
destination_folder = transfer.destination_folder(Transfer::Spec::DIRECTION_RECEIVE)
|
866
913
|
result_transfer = []
|
867
|
-
formatter.display_status("found #{ids_to_download.length} package(s).")
|
868
914
|
ids_to_download.each do |package_id|
|
869
915
|
package_info = aoc_api.read("packages/#{package_id}")
|
870
|
-
formatter.display_status("downloading package: [#{package_info['id']}] #{package_info['name']}")
|
871
916
|
package_node_api = aoc_api.node_api_from(
|
872
917
|
node_id: package_info['node_id'],
|
873
|
-
|
874
|
-
|
875
|
-
|
918
|
+
package_info: package_info,
|
919
|
+
**workspace_id_hash(name: true))
|
920
|
+
transfer_spec = package_node_api.transfer_spec_gen4(
|
921
|
+
package_info['contents_file_id'],
|
922
|
+
Transfer::Spec::DIRECTION_RECEIVE,
|
923
|
+
{'paths'=> ts_paths})
|
924
|
+
transfer.option_transfer_spec['destination_root'] = File.join(destination_folder, package_info[per_package_field]) unless per_package_field.nil?
|
925
|
+
formatter.display_status(%Q{Downloading package: [#{package_info['id']}] "#{package_info['name']}" to [#{transfer.option_transfer_spec['destination_root']}]})
|
876
926
|
statuses = transfer.start(
|
877
|
-
|
878
|
-
package_info['contents_file_id'],
|
879
|
-
Transfer::Spec::DIRECTION_RECEIVE,
|
880
|
-
{'paths'=> file_list}),
|
927
|
+
transfer_spec,
|
881
928
|
rest_token: package_node_api)
|
882
929
|
result_transfer.push({'package' => package_id, Main::STATUS_FIELD => statuses})
|
883
930
|
# update skip list only if all transfer sessions completed
|
884
|
-
if TransferAgent.session_status(statuses).eql?(:success)
|
885
|
-
|
886
|
-
skip_ids_persistency
|
931
|
+
if skip_ids_persistency && TransferAgent.session_status(statuses).eql?(:success)
|
932
|
+
skip_ids_persistency.data.push(package_id)
|
933
|
+
skip_ids_persistency.save
|
887
934
|
end
|
888
935
|
end
|
889
936
|
return Main.result_transfer_multiple(result_transfer)
|
890
937
|
when :show
|
891
938
|
package_id = instance_identifier
|
892
939
|
package_info = aoc_api.read("packages/#{package_id}")
|
893
|
-
return
|
940
|
+
return Main.result_single_object(package_info)
|
894
941
|
when :list
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
942
|
+
result = list_all_packages_with_query
|
943
|
+
skip_ids_persistency = package_persistency
|
944
|
+
reject_packages_from_persistency(result[:items], skip_ids_persistency)
|
945
|
+
display_fields = PACKAGE_LIST_DEFAULT_FIELDS
|
946
|
+
display_fields += ['workspace_id'] if aoc_api.workspace[:id].nil?
|
947
|
+
return Main.result_object_list(result[:items], fields: display_fields, total: result[:total])
|
900
948
|
when :delete
|
901
949
|
return do_bulk_operation(command: package_command, descr: 'identifier', values: instance_identifier) do |id|
|
902
950
|
Aspera.assert_values(id.class, [String, Integer]){'identifier'}
|
@@ -915,16 +963,15 @@ module Aspera
|
|
915
963
|
when :short_link
|
916
964
|
folder_dest = options.get_next_argument('path', validation: String)
|
917
965
|
home_node_api = aoc_api.node_api_from(
|
918
|
-
node_id:
|
919
|
-
|
920
|
-
workspace_name: aoc_api.workspace[:name])
|
966
|
+
node_id: aoc_api.home[:node_id],
|
967
|
+
**workspace_id_hash(name: true))
|
921
968
|
shared_apfid = home_node_api.resolve_api_fid(aoc_api.home[:file_id], folder_dest)
|
922
969
|
return short_link_command(
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
970
|
+
purpose_public: 'view_shared_file',
|
971
|
+
node_id: shared_apfid[:api].app_info[:node_info]['id'],
|
972
|
+
file_id: shared_apfid[:file_id],
|
973
|
+
**workspace_id_hash
|
974
|
+
) do |resource_id|
|
928
975
|
# TODO: merge with node permissions ?
|
929
976
|
# TODO: access level as arg
|
930
977
|
access_levels = Api::Node::ACCESS_LEVELS # ['delete','list','mkdir','preview','read','rename','write']
|
@@ -936,13 +983,12 @@ module Aspera
|
|
936
983
|
'tags' => {
|
937
984
|
# TODO: really just here ? not in tags.aspera.files.workspace ?
|
938
985
|
'url_token' => true,
|
939
|
-
'workspace_id' => aoc_api.workspace[:id],
|
940
|
-
'workspace_name' => aoc_api.workspace[:name],
|
941
986
|
'folder_name' => File.basename(folder_dest),
|
942
987
|
'created_by_name' => aoc_api.current_user_info['name'],
|
943
988
|
'created_by_email' => aoc_api.current_user_info['email'],
|
944
989
|
'access_key' => shared_apfid[:api].app_info[:node_info]['access_key'],
|
945
|
-
'node' => shared_apfid[:api].app_info[:node_info]['host']
|
990
|
+
'node' => shared_apfid[:api].app_info[:node_info]['host'],
|
991
|
+
**workspace_id_hash(string: true, name: true)
|
946
992
|
}
|
947
993
|
}
|
948
994
|
created_data = shared_apfid[:api].create('permissions', perm_data)
|
@@ -965,7 +1011,7 @@ module Aspera
|
|
965
1011
|
when :launch
|
966
1012
|
wf_id = instance_identifier
|
967
1013
|
data = automation_api.create("workflows/#{wf_id}/launch", {})
|
968
|
-
return
|
1014
|
+
return Main.result_single_object(data)
|
969
1015
|
when :action
|
970
1016
|
# TODO: not complete
|
971
1017
|
wf_id = instance_identifier
|
@@ -976,16 +1022,17 @@ module Aspera
|
|
976
1022
|
action = automation_api.create('actions', {'step_id' => step['id'], 'type' => 'manual'})
|
977
1023
|
automation_api.update("steps/#{step['id']}", {'action_order' => [action['id']]})
|
978
1024
|
wf = automation_api.read("workflows/#{wf_id}")
|
979
|
-
return
|
1025
|
+
return Main.result_single_object(wf)
|
980
1026
|
end
|
981
1027
|
end
|
982
1028
|
when :admin
|
983
1029
|
return execute_admin_action
|
984
1030
|
when :gateway
|
985
1031
|
require 'aspera/faspex_gw'
|
986
|
-
|
987
|
-
uri = URI.parse(url)
|
988
|
-
server = WebServerSimple.new(uri)
|
1032
|
+
parameters = value_create_modify(command: command, default: {}).symbolize_keys
|
1033
|
+
uri = URI.parse(parameters.delete(:url){WebServerSimple::DEFAULT_URL})
|
1034
|
+
server = WebServerSimple.new(uri, **parameters.slice(*WebServerSimple::PARAMS))
|
1035
|
+
Aspera.assert(parameters.except(*WebServerSimple::PARAMS).empty?)
|
989
1036
|
aoc_api.context = :files
|
990
1037
|
server.mount(uri.path, Faspex4GWServlet, aoc_api, aoc_api.workspace[:id])
|
991
1038
|
server.start
|