aspera-cli 4.21.1 → 4.22.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 +52 -22
- data/CONTRIBUTING.md +69 -148
- data/README.md +929 -668
- data/bin/ascli +5 -14
- data/bin/asession +1 -3
- data/examples/get_proto_file.rb +4 -3
- data/examples/proxy.pac +20 -20
- data/lib/aspera/agent/base.rb +11 -5
- data/lib/aspera/agent/connect.rb +30 -28
- data/lib/aspera/agent/{alpha.rb → desktop.rb} +35 -31
- data/lib/aspera/agent/direct.rb +141 -121
- data/lib/aspera/agent/httpgw.rb +22 -26
- data/lib/aspera/agent/node.rb +14 -11
- data/lib/aspera/agent/transferd.rb +30 -19
- data/lib/aspera/api/alee.rb +1 -1
- data/lib/aspera/api/aoc.rb +6 -6
- data/lib/aspera/api/cos_node.rb +2 -2
- data/lib/aspera/api/httpgw.rb +7 -3
- data/lib/aspera/api/node.rb +10 -8
- data/lib/aspera/ascmd.rb +3 -3
- data/lib/aspera/ascp/installation.rb +53 -72
- data/lib/aspera/ascp/management.rb +1 -1
- data/lib/aspera/assert.rb +11 -2
- data/lib/aspera/cli/error.rb +2 -2
- data/lib/aspera/cli/extended_value.rb +46 -21
- data/lib/aspera/cli/formatter.rb +55 -48
- data/lib/aspera/cli/hints.rb +1 -1
- data/lib/aspera/cli/info.rb +1 -0
- data/lib/aspera/cli/main.rb +192 -170
- data/lib/aspera/cli/manager.rb +18 -18
- data/lib/aspera/cli/plugin.rb +23 -20
- 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 +247 -159
- data/lib/aspera/cli/plugins/ats.rb +19 -17
- data/lib/aspera/cli/plugins/config.rb +76 -113
- 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 +111 -84
- 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 +312 -182
- 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 +6 -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 +5 -5
- 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 +8 -5
- data/lib/aspera/environment.rb +26 -17
- data/lib/aspera/faspex_gw.rb +14 -14
- data/lib/aspera/faspex_postproc.rb +10 -11
- data/lib/aspera/hash_ext.rb +4 -14
- 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 +28 -34
- data/lib/aspera/nagios.rb +6 -6
- data/lib/aspera/node_simulator.rb +8 -8
- data/lib/aspera/oauth/base.rb +14 -7
- data/lib/aspera/oauth/factory.rb +5 -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/generator.rb +13 -10
- data/lib/aspera/preview/options.rb +16 -16
- data/lib/aspera/preview/terminal.rb +4 -4
- data/lib/aspera/preview/utils.rb +15 -17
- data/lib/aspera/products/connect.rb +35 -1
- data/lib/aspera/products/{alpha.rb → desktop.rb} +3 -3
- data/lib/aspera/products/transferd.rb +9 -2
- data/lib/aspera/proxy_auto_config.rb +2 -2
- data/lib/aspera/rest.rb +56 -47
- data/lib/aspera/rest_errors_aspera.rb +1 -1
- data/lib/aspera/secret_hider.rb +12 -5
- data/lib/aspera/ssh.rb +4 -4
- data/lib/aspera/temp_file_manager.rb +5 -4
- 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 +23 -72
- data/lib/aspera/transfer/sync_instance.schema.yaml +13 -0
- data/lib/aspera/transfer/sync_session.schema.yaml +79 -0
- data/lib/aspera/transfer/uri.rb +6 -6
- data/lib/aspera/uri_reader.rb +18 -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 +28 -165
- metadata.gz.sig +0 -0
- data/examples/build_exec +0 -74
- data/examples/build_exec_rubyc +0 -40
- data/examples/build_package.sh +0 -28
- data/lib/aspera/transfer/spec.yaml +0 -718
@@ -53,7 +53,9 @@ module Aspera
|
|
53
53
|
'completed' => true}.freeze
|
54
54
|
# options and parameters for Api::AoC.new
|
55
55
|
OPTIONS_NEW = %i[url auth client_id client_secret scope redirect_uri private_key passphrase username password workspace].freeze
|
56
|
-
|
56
|
+
PACKAGE_LIST_DEFAULT_FIELDS = %w[id name created_at files_completed bytes_transferred].freeze
|
57
|
+
|
58
|
+
private_constant :REDIRECT_LOCALHOST, :STD_AUTH_TYPES, :ADMIN_OBJECTS, :PACKAGE_RECEIVED_BASE_QUERY, :OPTIONS_NEW, :PACKAGE_LIST_DEFAULT_FIELDS
|
57
59
|
class << self
|
58
60
|
def application_name
|
59
61
|
'Aspera on Cloud'
|
@@ -78,15 +80,16 @@ module Aspera
|
|
78
80
|
}
|
79
81
|
end
|
80
82
|
|
81
|
-
# @param [String] url
|
83
|
+
# @param url [String] url to check
|
82
84
|
# @return [Bool] true if private key is required for the url (i.e. no passcode)
|
83
85
|
def private_key_required?(url)
|
84
86
|
# pub link do not need private key
|
85
87
|
return Api::AoC.link_info(url)[:token].nil?
|
86
88
|
end
|
87
89
|
|
88
|
-
# @param [
|
89
|
-
# @param [
|
90
|
+
# @param object [Plugin] An instance of this class
|
91
|
+
# @param private_key_path [String] path to private key
|
92
|
+
# @param pub_key_pem [String] PEM of public key
|
90
93
|
# @return [Hash] :preset_value, :test_args
|
91
94
|
def wizard(object:, private_key_path: nil, pub_key_pem: nil)
|
92
95
|
# set vars to look like object
|
@@ -121,7 +124,7 @@ module Aspera
|
|
121
124
|
formatter.display_status('Please Login to your Aspera on Cloud instance.')
|
122
125
|
formatter.display_status('Navigate to: 👤 → Account Settings → Profile → Public Key')
|
123
126
|
formatter.display_status('Check or update the value to:'.red.blink)
|
124
|
-
formatter.display_status(pub_key_pem)
|
127
|
+
formatter.display_status(pub_key_pem, hide_secrets: false)
|
125
128
|
if !options.get_option(:test_mode)
|
126
129
|
formatter.display_status('Once updated or validated, press enter.')
|
127
130
|
Environment.instance.open_uri(instance_url)
|
@@ -203,7 +206,7 @@ module Aspera
|
|
203
206
|
def api_from_options(new_base_path)
|
204
207
|
create_values = {subpath: new_base_path, secret_finder: config}
|
205
208
|
# create an API object with the same options, but with a different subpath
|
206
|
-
return Api::AoC.new(**OPTIONS_NEW.each_with_object(create_values)
|
209
|
+
return Api::AoC.new(**OPTIONS_NEW.each_with_object(create_values){ |i, m| m[i] = options.get_option(i) unless options.get_option(i).nil?})
|
207
210
|
rescue ArgumentError => e
|
208
211
|
if (m = e.message.match(/missing keyword: :(.*)$/))
|
209
212
|
raise Cli::Error, "Missing option: #{m[1]}"
|
@@ -216,13 +219,31 @@ module Aspera
|
|
216
219
|
@cache_api_aoc = api_from_options(Api::AoC::API_V1)
|
217
220
|
organization = @cache_api_aoc.read('organization')
|
218
221
|
if organization['http_gateway_enabled'] && organization['http_gateway_server_url']
|
219
|
-
transfer.httpgw_url_cb = lambda
|
222
|
+
transfer.httpgw_url_cb = lambda{organization['http_gateway_server_url']}
|
220
223
|
# @cache_api_aoc.current_user_info['connect_disabled']
|
221
224
|
end
|
222
225
|
end
|
223
226
|
return @cache_api_aoc
|
224
227
|
end
|
225
228
|
|
229
|
+
# Generate or update Hash with workspace id and name (option), if not already set
|
230
|
+
# @param hash [Hash, Nil] set in provided hash
|
231
|
+
# @param string [Bool] true to set key as string, else as symbol
|
232
|
+
# @param name [Bool] include name
|
233
|
+
# @return [Hash] with key `workspace_[id,name]` (symbol or string) only if defined
|
234
|
+
def workspace_id_hash(hash: nil, string: false, name: false)
|
235
|
+
info = aoc_api.workspace
|
236
|
+
hash = {} if hash.nil?
|
237
|
+
fields = %i[id]
|
238
|
+
fields.push(:name) if name
|
239
|
+
fields.each do |i|
|
240
|
+
k = "workspace_#{i}"
|
241
|
+
k = k.to_sym unless string
|
242
|
+
hash[k] = info[i] unless info[i].nil? || hash.key?(k)
|
243
|
+
end
|
244
|
+
return hash
|
245
|
+
end
|
246
|
+
|
226
247
|
# Get resource identifier from command line, either directly or from name.
|
227
248
|
# @param resource_class_path url path for resource
|
228
249
|
# @return identifier
|
@@ -240,7 +261,7 @@ module Aspera
|
|
240
261
|
|
241
262
|
# Call block with same query using paging and response information
|
242
263
|
# block must return a hash with :data and :http keys
|
243
|
-
# @return [Hash] {
|
264
|
+
# @return [Hash] {items: , total: }
|
244
265
|
def api_call_paging(base_query={})
|
245
266
|
Aspera.assert_type(base_query, Hash){'query'}
|
246
267
|
Aspera.assert(block_given?)
|
@@ -268,46 +289,59 @@ module Aspera
|
|
268
289
|
item_list += add_items
|
269
290
|
break if !max_items.nil? && item_list.count >= max_items
|
270
291
|
break if !max_pages.nil? && page_count >= max_pages
|
292
|
+
formatter.long_operation_running("#{item_list.count} / #{total_count}") unless total_count.eql?(item_list.count.to_s)
|
271
293
|
end
|
294
|
+
formatter.long_operation_terminated
|
272
295
|
item_list = item_list[0..max_items - 1] if !max_items.nil? && item_list.count > max_items
|
273
|
-
return {
|
296
|
+
return {items: item_list, total: total_count}
|
274
297
|
end
|
275
298
|
|
276
299
|
# read using the query and paging
|
277
300
|
# @return [Hash] {data: , total: }
|
278
301
|
def api_read_all(resource_class_path, base_query={})
|
279
302
|
return api_call_paging(base_query) do |query|
|
280
|
-
aoc_api.call(operation: 'GET', subpath: resource_class_path, headers: {'Accept' =>
|
303
|
+
aoc_api.call(operation: 'GET', subpath: resource_class_path, headers: {'Accept' => Rest::MIME_JSON}, query: query)
|
281
304
|
end
|
282
305
|
end
|
283
306
|
|
284
|
-
#
|
307
|
+
# List all entities, given additional, default and user's queries
|
285
308
|
# @param resource_class_path path to query on API
|
286
309
|
# @param fields fields to display
|
287
310
|
# @param base_query a query applied always
|
288
311
|
# @param default_query default query unless overriden by user
|
312
|
+
# @param &block (Optional) calls block with user's or default query
|
289
313
|
def result_list(resource_class_path, fields: nil, base_query: {}, default_query: {})
|
290
314
|
Aspera.assert_type(base_query, Hash)
|
291
315
|
Aspera.assert_type(default_query, Hash)
|
292
|
-
|
293
|
-
# caller may add specific modifications or checks
|
294
|
-
yield(
|
295
|
-
|
316
|
+
query = query_read_delete(default: default_query)
|
317
|
+
# caller may add specific modifications or checks to query
|
318
|
+
yield(query) if block_given?
|
319
|
+
result = api_read_all(resource_class_path, base_query.merge(query).compact)
|
320
|
+
return Main.result_object_list(result[:items], fields: fields, total: result[:total])
|
296
321
|
end
|
297
322
|
|
323
|
+
# Translates `dropbox_name` to `dropbox_id` and fills current workspace_id
|
298
324
|
def resolve_dropbox_name_default_ws_id(query)
|
299
325
|
if query.key?('dropbox_name')
|
300
326
|
# convenience: specify name instead of id
|
301
|
-
raise '
|
327
|
+
raise 'Use field dropbox_name or dropbox_id, not both' if query.key?('dropbox_id')
|
302
328
|
# 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')
|
329
|
+
query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query.delete('dropbox_name'))['id']
|
305
330
|
end
|
306
|
-
query
|
331
|
+
workspace_id_hash(hash: query, string: true)
|
307
332
|
# by default show dropbox packages only for dropboxes
|
308
333
|
query['exclude_dropbox_packages'] = !query.key?('dropbox_id') unless query.key?('exclude_dropbox_packages')
|
309
334
|
end
|
310
335
|
|
336
|
+
# @return [Hash] {items,total} with all packages according to combination of user's query and default query
|
337
|
+
def list_all_packages_with_query
|
338
|
+
query = query_read_delete(default: {})
|
339
|
+
Aspera.assert_type(query, Hash){'query'}
|
340
|
+
PACKAGE_RECEIVED_BASE_QUERY.each{ |k, v| query[k] = v unless query.key?(k)}
|
341
|
+
resolve_dropbox_name_default_ws_id(query)
|
342
|
+
return api_read_all('packages', query.compact)
|
343
|
+
end
|
344
|
+
|
311
345
|
NODE4_EXT_COMMANDS = %i[transfer].concat(Node::COMMANDS_GEN4).freeze
|
312
346
|
private_constant :NODE4_EXT_COMMANDS
|
313
347
|
|
@@ -316,9 +350,8 @@ module Aspera
|
|
316
350
|
def execute_nodegen4_command(command_repo, node_id, file_id: nil, scope: nil)
|
317
351
|
top_node_api = aoc_api.node_api_from(
|
318
352
|
node_id: node_id,
|
319
|
-
|
320
|
-
|
321
|
-
scope: scope
|
353
|
+
scope: scope,
|
354
|
+
**workspace_id_hash(name: true)
|
322
355
|
)
|
323
356
|
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
357
|
node_plugin = Node.new(**init_params, api: top_node_api)
|
@@ -348,7 +381,7 @@ module Aspera
|
|
348
381
|
transfer.agent_instance = Agent::Node.new(
|
349
382
|
url: client_apfid[:api].base_url,
|
350
383
|
username: client_apfid[:api].app_info[:node_info]['access_key'],
|
351
|
-
password: client_apfid[:api].oauth.
|
384
|
+
password: client_apfid[:api].oauth.authorization,
|
352
385
|
root_id: client_apfid[:file_id]
|
353
386
|
)
|
354
387
|
# additional node to node TS info
|
@@ -422,8 +455,8 @@ module Aspera
|
|
422
455
|
when :show
|
423
456
|
object = aoc_api.read(resource_instance_path)
|
424
457
|
# default: show all, but certificate
|
425
|
-
fields = object.keys.reject{|k|k.eql?('certificate')}
|
426
|
-
return
|
458
|
+
fields = object.keys.reject{ |k| k.eql?('certificate')}
|
459
|
+
return Main.result_single_object(object, fields: fields)
|
427
460
|
when :modify
|
428
461
|
changes = options.get_next_argument('properties', validation: Hash)
|
429
462
|
return do_bulk_operation(command: command, descr: 'identifier', values: res_id) do |one_id|
|
@@ -473,60 +506,111 @@ module Aspera
|
|
473
506
|
when :subscription
|
474
507
|
org = aoc_api.read('organization')
|
475
508
|
bss_graphql = api_from_options('bss/platform/graphql')
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
509
|
+
command_subscription = options.get_next_command(%i[account usage])
|
510
|
+
case command_subscription
|
511
|
+
when :account
|
512
|
+
# cspell:disable
|
513
|
+
graphql_query = <<-GRAPHQL
|
514
|
+
query ($organization_id: ID!) {
|
515
|
+
aoc (organization_id: $organization_id) {
|
516
|
+
bssSubscription {
|
517
|
+
aocVersion
|
518
|
+
endDate
|
519
|
+
startDate
|
520
|
+
termMonths
|
521
|
+
plan
|
522
|
+
trial
|
523
|
+
termType
|
524
|
+
aocOrganizations {
|
525
|
+
id
|
526
|
+
}
|
527
|
+
additionalStorageVolumeGb
|
528
|
+
additionalEgressVolumeGb
|
529
|
+
term {
|
530
|
+
startDate
|
531
|
+
endDate
|
532
|
+
transferVolumeGb
|
533
|
+
egressVolumeGb
|
534
|
+
storageVolumeGb
|
535
|
+
transferVolumeOffsetGb
|
536
|
+
}
|
537
|
+
paygoRate {
|
538
|
+
transferRate
|
539
|
+
storageRate
|
540
|
+
currency
|
541
|
+
}
|
542
|
+
aocPlanData {
|
543
|
+
tier
|
544
|
+
trial
|
545
|
+
workspaces { max }
|
546
|
+
users {
|
547
|
+
planAmount
|
548
|
+
max
|
549
|
+
}
|
550
|
+
samlIntegration
|
551
|
+
activity
|
552
|
+
sharedInboxes
|
553
|
+
uniqueUrls
|
554
|
+
support
|
555
|
+
watermarking
|
556
|
+
byok
|
557
|
+
automation { planAmount, max }
|
558
|
+
}
|
559
|
+
}
|
560
|
+
}
|
513
561
|
}
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
562
|
+
GRAPHQL
|
563
|
+
# cspell:enable
|
564
|
+
result = bss_graphql.create(nil, {query: graphql_query, variables: {organization_id: org['id']}})['data']
|
565
|
+
return Main.result_single_object(result['aoc']['bssSubscription'])
|
566
|
+
when :usage
|
567
|
+
# cspell:disable
|
568
|
+
graphql_query = <<-GRAPHQL
|
569
|
+
query ($organization_id: ID!, $startDate: Date!, $endDate: Date!, $aggregate: TransferUsageAggregateOption!) {
|
570
|
+
aoc (organization_id: $organization_id) {
|
571
|
+
bssSubscription {
|
572
|
+
aocOrganizations { id }
|
573
|
+
additionalStorageVolumeGb
|
574
|
+
additionalEgressVolumeGb
|
575
|
+
aocPlanData {
|
576
|
+
tier
|
577
|
+
trial
|
578
|
+
}
|
579
|
+
term {
|
580
|
+
transferVolumeGb
|
581
|
+
egressVolumeGb
|
582
|
+
storageVolumeGb
|
583
|
+
startDate
|
584
|
+
endDate
|
585
|
+
transferVolumeOffsetGb
|
586
|
+
}
|
587
|
+
termMonths
|
588
|
+
transferUsages (startDate: $startDate, endDate: $endDate, aggregate: $aggregate) { mbTotal }
|
589
|
+
egressUsages (startDate: $startDate, endDate: $endDate, aggregate: $aggregate) { usageMb }
|
590
|
+
}
|
591
|
+
subscriptionEntitlements {
|
592
|
+
id
|
593
|
+
transferUsages (startDate: $startDate, endDate: $endDate, aggregate: $aggregate) { mbTotal }
|
594
|
+
egressUsages (startDate: $startDate, endDate: $endDate, aggregate: $aggregate) { usageMb }
|
595
|
+
}
|
596
|
+
}
|
597
|
+
}
|
598
|
+
GRAPHQL
|
599
|
+
aggregate = options.get_next_argument('aggregation', accept_list: %i[ALL MONTHLY], default: :ALL)
|
600
|
+
today = Date.today
|
601
|
+
start_date = options.get_next_argument('start date', mandatory: false, default: today.prev_year.strftime('%Y-%m-%d'))
|
602
|
+
end_date = options.get_next_argument('end date', mandatory: false, default: today.strftime('%Y-%m-%d'))
|
603
|
+
# cspell:enable
|
604
|
+
result = bss_graphql.create(
|
605
|
+
nil,
|
606
|
+
{query: graphql_query,
|
607
|
+
variables: {
|
608
|
+
organization_id: org['id'],
|
609
|
+
aggregate: aggregate,
|
610
|
+
startDate: start_date,
|
611
|
+
endDate: end_date}})['data']
|
612
|
+
return Main.result_single_object(result['aoc'])
|
613
|
+
end
|
530
614
|
when :ats
|
531
615
|
ats_api = Rest.new(**aoc_api.params.deep_merge({
|
532
616
|
base_url: "#{aoc_api.base_url}/admin/ats/pub/v1",
|
@@ -543,7 +627,7 @@ module Aspera
|
|
543
627
|
when :application_events
|
544
628
|
event_type = command_analytics.to_s
|
545
629
|
events = analytics_api.read("organizations/#{aoc_api.current_user_info['organization_id']}/#{event_type}")[event_type]
|
546
|
-
return
|
630
|
+
return Main.result_object_list(events)
|
547
631
|
when :transfers
|
548
632
|
event_type = command_analytics.to_s
|
549
633
|
filter_resource = options.get_next_argument('resource', accept_list: %i[organizations users nodes])
|
@@ -584,25 +668,26 @@ module Aspera
|
|
584
668
|
config.send_email_template(values: {ev: tr_event})
|
585
669
|
end
|
586
670
|
end
|
587
|
-
return
|
671
|
+
return Main.result_object_list(events)
|
588
672
|
end
|
589
673
|
when :usage_reports
|
590
674
|
aoc_api.context = :files
|
591
|
-
return result_list('usage_reports', base_query:
|
675
|
+
return result_list('usage_reports', base_query: workspace_id_hash)
|
592
676
|
end
|
593
677
|
end
|
594
678
|
|
595
679
|
# Create a shared link for the given entity
|
596
|
-
# @param
|
597
|
-
# @param
|
598
|
-
|
680
|
+
# @param purpose_public [Symbol]
|
681
|
+
# @param shared_data [Hash] information for shared data
|
682
|
+
# @param block [Proc] Optional: called on creation
|
683
|
+
def short_link_command(purpose_public:, **shared_data)
|
599
684
|
link_type = options.get_next_argument('link type', accept_list: %i[public private])
|
600
685
|
purpose_local = case link_type
|
601
686
|
when :public
|
602
687
|
case purpose_public
|
603
688
|
when /package/ then 'send_package_to_dropbox'
|
604
689
|
when /shared/ then 'token_auth_redirection'
|
605
|
-
else
|
690
|
+
else Aspera.error_unexpected_value(purpose_public){'public link purpose'}
|
606
691
|
end
|
607
692
|
when :private then 'shared_folder_auth_link'
|
608
693
|
else Aspera.error_unreachable_line
|
@@ -631,7 +716,7 @@ module Aspera
|
|
631
716
|
result_create_short_link = aoc_api.create('short_links', creation_params)
|
632
717
|
# public: Creation: permission on node
|
633
718
|
yield(result_create_short_link['resource_id']) if block_given? && link_type.eql?(:public)
|
634
|
-
return
|
719
|
+
return Main.result_single_object(result_create_short_link)
|
635
720
|
when :list
|
636
721
|
query = if link_type.eql?(:private)
|
637
722
|
shared_data
|
@@ -667,6 +752,26 @@ module Aspera
|
|
667
752
|
end
|
668
753
|
end
|
669
754
|
|
755
|
+
# @return persistency object if option `once_only` is used.
|
756
|
+
def package_persistency
|
757
|
+
return nil unless options.get_option(:once_only, mandatory: true)
|
758
|
+
# TODO: add query info to id
|
759
|
+
PersistencyActionOnce.new(
|
760
|
+
manager: persistency,
|
761
|
+
data: [],
|
762
|
+
id: IdGenerator.from_list(
|
763
|
+
['aoc_recv',
|
764
|
+
options.get_option(:url, mandatory: true),
|
765
|
+
aoc_api.workspace[:id]
|
766
|
+
].concat(aoc_api.additional_persistence_ids)))
|
767
|
+
end
|
768
|
+
|
769
|
+
def reject_packages_from_persistency(all_packages, skip_ids_persistency)
|
770
|
+
return if skip_ids_persistency.nil?
|
771
|
+
skip_package = skip_ids_persistency.data.each_with_object({}){ |i, m| m[i] = true}
|
772
|
+
all_packages.reject!{ |pkg| skip_package[pkg['id']]}
|
773
|
+
end
|
774
|
+
|
670
775
|
# must be public
|
671
776
|
ACTIONS = %i[reminder servers bearer_token organization tier_restrictions user packages files admin automation gateway].freeze
|
672
777
|
|
@@ -688,29 +793,29 @@ module Aspera
|
|
688
793
|
Rest.new(base_url: "#{Api::AoC.api_base_url}/#{Api::AoC::API_V1}").create('organization_reminders', {email: user_email})
|
689
794
|
return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
|
690
795
|
when :servers
|
691
|
-
return
|
796
|
+
return Main.result_object_list(Rest.new(base_url: "#{Api::AoC.api_base_url}/#{Api::AoC::API_V1}").read('servers'))
|
692
797
|
when :bearer_token
|
693
|
-
return
|
798
|
+
return Main.result_text(aoc_api.oauth.authorization)
|
694
799
|
when :organization
|
695
|
-
return
|
800
|
+
return Main.result_single_object(aoc_api.read('organization'))
|
696
801
|
when :tier_restrictions
|
697
|
-
return
|
802
|
+
return Main.result_single_object(aoc_api.read('tier_restrictions'))
|
698
803
|
when :user
|
699
804
|
case options.get_next_command(%i[workspaces profile preferences])
|
700
805
|
# when :settings
|
701
|
-
# return
|
806
|
+
# return Main.result_object_list(aoc_api.read('client_settings/'))
|
702
807
|
when :workspaces
|
703
808
|
case options.get_next_command(%i[list current])
|
704
809
|
when :list
|
705
810
|
return result_list('workspaces', fields: %w[id name])
|
706
811
|
when :current
|
707
812
|
aoc_api.context = :files
|
708
|
-
return
|
813
|
+
return Main.result_single_object(aoc_api.workspace)
|
709
814
|
end
|
710
815
|
when :profile
|
711
816
|
case options.get_next_command(%i[show modify])
|
712
817
|
when :show
|
713
|
-
return
|
818
|
+
return Main.result_single_object(aoc_api.current_user_info(exception: true))
|
714
819
|
when :modify
|
715
820
|
aoc_api.update("users/#{aoc_api.current_user_info(exception: true)['id']}", options.get_next_argument('properties', validation: Hash))
|
716
821
|
return Main.result_status('modified')
|
@@ -719,7 +824,7 @@ module Aspera
|
|
719
824
|
user_preferences_res = "users/#{aoc_api.current_user_info(exception: true)['id']}/user_interaction_preferences"
|
720
825
|
case options.get_next_command(%i[show modify])
|
721
826
|
when :show
|
722
|
-
return
|
827
|
+
return Main.result_single_object(aoc_api.read(user_preferences_res))
|
723
828
|
when :modify
|
724
829
|
aoc_api.update(user_preferences_res, options.get_next_argument('properties', validation: Hash))
|
725
830
|
return Main.result_status('modified')
|
@@ -732,26 +837,24 @@ module Aspera
|
|
732
837
|
case options.get_next_command(%i[list show short_link])
|
733
838
|
when :list
|
734
839
|
default_query = {'embed[]' => 'dropbox', 'aggregate_permissions_by_dropbox' => true, 'sort' => 'dropbox_name'}
|
735
|
-
default_query
|
840
|
+
workspace_id_hash(hash: default_query, string: true)
|
736
841
|
return result_list('dropbox_memberships', fields: %w[dropbox_id dropbox.name], default_query: default_query)
|
737
842
|
when :show
|
738
|
-
return
|
843
|
+
return Main.result_single_object(aoc_api.read(get_resource_path_from_args('dropboxes')))
|
739
844
|
when :short_link
|
740
845
|
return short_link_command(
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
purpose_public: 'send_package_to_dropbox')
|
846
|
+
purpose_public: 'send_package_to_dropbox',
|
847
|
+
dropbox_id: get_resource_id_from_args('dropboxes'),
|
848
|
+
name: '',
|
849
|
+
**workspace_id_hash
|
850
|
+
)
|
747
851
|
end
|
748
852
|
when :send
|
749
853
|
package_data = value_create_modify(command: package_command)
|
750
854
|
new_user_option = options.get_option(:new_user_option)
|
751
855
|
option_validate = options.get_option(:validate_metadata)
|
752
|
-
# works for both normal
|
753
|
-
package_data
|
754
|
-
|
856
|
+
# works for both normal user auth and link auth
|
857
|
+
workspace_id_hash(hash: package_data, string: true) unless package_data.key?('workspace_id')
|
755
858
|
if !aoc_api.public_link.nil?
|
756
859
|
aoc_api.assert_public_link_types(%w[send_package_to_user send_package_to_dropbox])
|
757
860
|
box_type = aoc_api.public_link['purpose'].split('_').last
|
@@ -764,64 +867,49 @@ module Aspera
|
|
764
867
|
created_package = aoc_api.create_package_simple(package_data, option_validate, new_user_option)
|
765
868
|
Main.result_transfer(transfer.start(created_package[:spec], rest_token: created_package[:node]))
|
766
869
|
# return all info on package (especially package id)
|
767
|
-
return
|
870
|
+
return Main.result_single_object(created_package[:info])
|
768
871
|
when :receive
|
769
872
|
ids_to_download = nil
|
770
873
|
if !aoc_api.public_link.nil?
|
771
874
|
aoc_api.assert_public_link_types(['view_received_package'])
|
772
|
-
# set the package id
|
875
|
+
# set the package id from link
|
773
876
|
ids_to_download = aoc_api.public_link['data']['package_id']
|
774
877
|
end
|
775
878
|
# get from command line unless it was a public link
|
776
879
|
ids_to_download ||= instance_identifier
|
777
|
-
|
778
|
-
skip_ids_persistency = nil
|
779
|
-
if options.get_option(:once_only, mandatory: true)
|
780
|
-
# TODO: add query info to id
|
781
|
-
skip_ids_persistency = PersistencyActionOnce.new(
|
782
|
-
manager: persistency,
|
783
|
-
data: skip_ids_data,
|
784
|
-
id: IdGenerator.from_list(
|
785
|
-
['aoc_recv',
|
786
|
-
options.get_option(:url, mandatory: true),
|
787
|
-
aoc_api.workspace[:id]
|
788
|
-
].concat(aoc_api.additional_persistence_ids)))
|
789
|
-
end
|
880
|
+
skip_ids_persistency = package_persistency
|
790
881
|
case ids_to_download
|
791
882
|
when SpecialValues::ALL, SpecialValues::INIT
|
792
|
-
|
793
|
-
Aspera.assert_type(query, Hash){'query'}
|
794
|
-
resolve_dropbox_name_default_ws_id(query)
|
795
|
-
# remove from list the ones already downloaded
|
796
|
-
all_ids = api_read_all('packages', query)[:data].map{|e|e['id']}
|
883
|
+
all_packages = list_all_packages_with_query[:items]
|
797
884
|
if ids_to_download.eql?(SpecialValues::INIT)
|
798
|
-
Aspera.assert(skip_ids_persistency){'
|
799
|
-
skip_ids_persistency.data.clear.concat(
|
885
|
+
Aspera.assert(skip_ids_persistency){'INIT requires option once_only'}
|
886
|
+
skip_ids_persistency.data.clear.concat(all_packages.map{ |e| e['id']})
|
800
887
|
skip_ids_persistency.save
|
801
888
|
return Main.result_status("Initialized skip for #{skip_ids_persistency.data.count} package(s)")
|
802
889
|
end
|
803
|
-
#
|
804
|
-
|
890
|
+
# remove from list the ones already downloaded
|
891
|
+
reject_packages_from_persistency(all_packages, skip_ids_persistency)
|
892
|
+
ids_to_download = all_packages.map{ |e| e['id']}
|
805
893
|
else
|
894
|
+
# single id to array
|
806
895
|
ids_to_download = [ids_to_download] unless ids_to_download.is_a?(Array)
|
807
896
|
end
|
808
897
|
file_list =
|
809
898
|
begin
|
810
|
-
transfer.source_list.map{|i|{'source'=>i}}
|
899
|
+
transfer.source_list.map{ |i| {'source'=>i}}
|
811
900
|
rescue Cli::BadArgument
|
812
901
|
[{'source' => '.'}]
|
813
902
|
end
|
814
903
|
# list here
|
815
904
|
result_transfer = []
|
816
|
-
formatter.display_status("
|
905
|
+
formatter.display_status("Found #{ids_to_download.length} package(s).")
|
817
906
|
ids_to_download.each do |package_id|
|
818
907
|
package_info = aoc_api.read("packages/#{package_id}")
|
819
908
|
formatter.display_status("downloading package: [#{package_info['id']}] #{package_info['name']}")
|
820
909
|
package_node_api = aoc_api.node_api_from(
|
821
910
|
node_id: package_info['node_id'],
|
822
|
-
|
823
|
-
|
824
|
-
package_info: package_info)
|
911
|
+
package_info: package_info,
|
912
|
+
**workspace_id_hash(name: true))
|
825
913
|
statuses = transfer.start(
|
826
914
|
package_node_api.transfer_spec_gen4(
|
827
915
|
package_info['contents_file_id'],
|
@@ -830,22 +918,23 @@ module Aspera
|
|
830
918
|
rest_token: package_node_api)
|
831
919
|
result_transfer.push({'package' => package_id, Main::STATUS_FIELD => statuses})
|
832
920
|
# update skip list only if all transfer sessions completed
|
833
|
-
if TransferAgent.session_status(statuses).eql?(:success)
|
834
|
-
|
835
|
-
skip_ids_persistency
|
921
|
+
if skip_ids_persistency && TransferAgent.session_status(statuses).eql?(:success)
|
922
|
+
skip_ids_persistency.data.push(package_id)
|
923
|
+
skip_ids_persistency.save
|
836
924
|
end
|
837
925
|
end
|
838
926
|
return Main.result_transfer_multiple(result_transfer)
|
839
927
|
when :show
|
840
928
|
package_id = instance_identifier
|
841
929
|
package_info = aoc_api.read("packages/#{package_id}")
|
842
|
-
return
|
930
|
+
return Main.result_single_object(package_info)
|
843
931
|
when :list
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
932
|
+
result = list_all_packages_with_query
|
933
|
+
skip_ids_persistency = package_persistency
|
934
|
+
reject_packages_from_persistency(result[:items], skip_ids_persistency)
|
935
|
+
display_fields = PACKAGE_LIST_DEFAULT_FIELDS
|
936
|
+
display_fields += ['workspace_id'] if aoc_api.workspace[:id].nil?
|
937
|
+
return Main.result_object_list(result[:items], fields: display_fields, total: result[:total])
|
849
938
|
when :delete
|
850
939
|
return do_bulk_operation(command: package_command, descr: 'identifier', values: instance_identifier) do |id|
|
851
940
|
Aspera.assert_values(id.class, [String, Integer]){'identifier'}
|
@@ -864,16 +953,15 @@ module Aspera
|
|
864
953
|
when :short_link
|
865
954
|
folder_dest = options.get_next_argument('path', validation: String)
|
866
955
|
home_node_api = aoc_api.node_api_from(
|
867
|
-
node_id:
|
868
|
-
|
869
|
-
workspace_name: aoc_api.workspace[:name])
|
956
|
+
node_id: aoc_api.home[:node_id],
|
957
|
+
**workspace_id_hash(name: true))
|
870
958
|
shared_apfid = home_node_api.resolve_api_fid(aoc_api.home[:file_id], folder_dest)
|
871
959
|
return short_link_command(
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
960
|
+
purpose_public: 'view_shared_file',
|
961
|
+
node_id: shared_apfid[:api].app_info[:node_info]['id'],
|
962
|
+
file_id: shared_apfid[:file_id],
|
963
|
+
**workspace_id_hash
|
964
|
+
) do |resource_id|
|
877
965
|
# TODO: merge with node permissions ?
|
878
966
|
# TODO: access level as arg
|
879
967
|
access_levels = Api::Node::ACCESS_LEVELS # ['delete','list','mkdir','preview','read','rename','write']
|
@@ -885,13 +973,12 @@ module Aspera
|
|
885
973
|
'tags' => {
|
886
974
|
# TODO: really just here ? not in tags.aspera.files.workspace ?
|
887
975
|
'url_token' => true,
|
888
|
-
'workspace_id' => aoc_api.workspace[:id],
|
889
|
-
'workspace_name' => aoc_api.workspace[:name],
|
890
976
|
'folder_name' => File.basename(folder_dest),
|
891
977
|
'created_by_name' => aoc_api.current_user_info['name'],
|
892
978
|
'created_by_email' => aoc_api.current_user_info['email'],
|
893
979
|
'access_key' => shared_apfid[:api].app_info[:node_info]['access_key'],
|
894
|
-
'node' => shared_apfid[:api].app_info[:node_info]['host']
|
980
|
+
'node' => shared_apfid[:api].app_info[:node_info]['host'],
|
981
|
+
**workspace_id_hash(string: true, name: true)
|
895
982
|
}
|
896
983
|
}
|
897
984
|
created_data = shared_apfid[:api].create('permissions', perm_data)
|
@@ -914,7 +1001,7 @@ module Aspera
|
|
914
1001
|
when :launch
|
915
1002
|
wf_id = instance_identifier
|
916
1003
|
data = automation_api.create("workflows/#{wf_id}/launch", {})
|
917
|
-
return
|
1004
|
+
return Main.result_single_object(data)
|
918
1005
|
when :action
|
919
1006
|
# TODO: not complete
|
920
1007
|
wf_id = instance_identifier
|
@@ -925,16 +1012,17 @@ module Aspera
|
|
925
1012
|
action = automation_api.create('actions', {'step_id' => step['id'], 'type' => 'manual'})
|
926
1013
|
automation_api.update("steps/#{step['id']}", {'action_order' => [action['id']]})
|
927
1014
|
wf = automation_api.read("workflows/#{wf_id}")
|
928
|
-
return
|
1015
|
+
return Main.result_single_object(wf)
|
929
1016
|
end
|
930
1017
|
end
|
931
1018
|
when :admin
|
932
1019
|
return execute_admin_action
|
933
1020
|
when :gateway
|
934
1021
|
require 'aspera/faspex_gw'
|
935
|
-
|
936
|
-
uri = URI.parse(url)
|
937
|
-
server = WebServerSimple.new(uri)
|
1022
|
+
parameters = value_create_modify(command: command, default: {}).symbolize_keys
|
1023
|
+
uri = URI.parse(parameters.delete(:url){WebServerSimple::DEFAULT_URL})
|
1024
|
+
server = WebServerSimple.new(uri, **parameters.slice(*WebServerSimple::PARAMS))
|
1025
|
+
Aspera.assert(parameters.except(*WebServerSimple::PARAMS).empty?)
|
938
1026
|
aoc_api.context = :files
|
939
1027
|
server.mount(uri.path, Faspex4GWServlet, aoc_api, aoc_api.workspace[:id])
|
940
1028
|
server.start
|