aspera-cli 4.25.1 → 4.25.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +456 -405
- data/CONTRIBUTING.md +22 -18
- data/README.md +33 -9741
- data/bin/asession +111 -88
- data/lib/aspera/agent/connect.rb +1 -1
- data/lib/aspera/agent/desktop.rb +1 -1
- data/lib/aspera/agent/direct.rb +19 -18
- data/lib/aspera/agent/node.rb +1 -1
- data/lib/aspera/api/aoc.rb +44 -20
- data/lib/aspera/api/faspex.rb +25 -6
- data/lib/aspera/api/node.rb +20 -16
- data/lib/aspera/ascp/installation.rb +32 -51
- data/lib/aspera/assert.rb +2 -2
- data/lib/aspera/cli/extended_value.rb +1 -0
- data/lib/aspera/cli/formatter.rb +0 -4
- data/lib/aspera/cli/hints.rb +18 -4
- data/lib/aspera/cli/main.rb +3 -6
- data/lib/aspera/cli/manager.rb +46 -30
- data/lib/aspera/cli/plugins/aoc.rb +155 -131
- data/lib/aspera/cli/plugins/base.rb +15 -18
- data/lib/aspera/cli/plugins/config.rb +50 -87
- data/lib/aspera/cli/plugins/factory.rb +2 -2
- data/lib/aspera/cli/plugins/faspex.rb +4 -4
- data/lib/aspera/cli/plugins/faspex5.rb +74 -76
- data/lib/aspera/cli/plugins/node.rb +3 -5
- data/lib/aspera/cli/plugins/oauth.rb +26 -25
- data/lib/aspera/cli/plugins/preview.rb +9 -14
- data/lib/aspera/cli/plugins/shares.rb +15 -7
- data/lib/aspera/cli/transfer_agent.rb +2 -2
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +7 -0
- data/lib/aspera/environment.rb +30 -16
- data/lib/aspera/faspex_gw.rb +6 -6
- data/lib/aspera/faspex_postproc.rb +20 -14
- data/lib/aspera/hash_ext.rb +8 -0
- data/lib/aspera/log.rb +15 -15
- data/lib/aspera/markdown.rb +22 -0
- data/lib/aspera/node_simulator.rb +1 -1
- data/lib/aspera/oauth/base.rb +2 -2
- data/lib/aspera/oauth/url_json.rb +2 -2
- data/lib/aspera/oauth/web.rb +1 -1
- data/lib/aspera/preview/generator.rb +9 -9
- data/lib/aspera/rest.rb +44 -37
- data/lib/aspera/rest_call_error.rb +16 -8
- data/lib/aspera/rest_error_analyzer.rb +38 -36
- data/lib/aspera/rest_errors_aspera.rb +19 -18
- data/lib/aspera/transfer/resumer.rb +2 -2
- data/lib/aspera/yaml.rb +49 -0
- data.tar.gz.sig +0 -0
- metadata +17 -3
- metadata.gz.sig +0 -0
- data/release_notes.md +0 -8
|
@@ -102,7 +102,7 @@ module Aspera
|
|
|
102
102
|
# @param destination_folder [String] Base folder
|
|
103
103
|
# @param fld. [Array] List of fields of package
|
|
104
104
|
def unique_folder(package_info, destination_folder, fld: nil, seq: false, opt: false)
|
|
105
|
-
Aspera.assert_array_all(fld, String, type:
|
|
105
|
+
Aspera.assert_array_all(fld, String, type: BadArgument){'fld'}
|
|
106
106
|
Aspera.assert([1, 2].include?(fld.length)){'fld must have 1 or 2 elements'}
|
|
107
107
|
folder = Environment.instance.sanitized_filename(package_info[fld[0]])
|
|
108
108
|
if seq
|
|
@@ -181,7 +181,7 @@ module Aspera
|
|
|
181
181
|
end
|
|
182
182
|
myself = aoc_api.read('self')
|
|
183
183
|
if auto_set_pub_key
|
|
184
|
-
Aspera.assert(myself['public_key'].empty?, type:
|
|
184
|
+
Aspera.assert(myself['public_key'].empty?, type: Error){'Public key is already set in profile (use --override=yes)'} unless option_override
|
|
185
185
|
formatter.display_status('Updating profile with the public key.')
|
|
186
186
|
aoc_api.update("users/#{myself['id']}", {'public_key' => pub_key_pem})
|
|
187
187
|
end
|
|
@@ -224,21 +224,18 @@ module Aspera
|
|
|
224
224
|
@scope = new_scope
|
|
225
225
|
end
|
|
226
226
|
|
|
227
|
-
#
|
|
227
|
+
# Create an API object with the options from CLI, but with a different subpath
|
|
228
228
|
# @param aoc_base_path [String] New subpath
|
|
229
229
|
# @return [Api::AoC] API object for AoC (is Rest)
|
|
230
230
|
def api_from_options(aoc_base_path)
|
|
231
|
-
return
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
workspace: nil
|
|
240
|
-
}
|
|
241
|
-
)
|
|
231
|
+
return Api::AoC.new(**Oauth.args_from_options(
|
|
232
|
+
options,
|
|
233
|
+
defaults: {workspace: nil},
|
|
234
|
+
scope: @scope,
|
|
235
|
+
subpath: aoc_base_path,
|
|
236
|
+
secret_finder: config,
|
|
237
|
+
progress_disp: formatter
|
|
238
|
+
))
|
|
242
239
|
end
|
|
243
240
|
|
|
244
241
|
# AoC Rest object
|
|
@@ -256,11 +253,11 @@ module Aspera
|
|
|
256
253
|
end
|
|
257
254
|
|
|
258
255
|
# Generate or update Hash with workspace id and name (option), if not already set
|
|
259
|
-
# @param hash [Hash,nil] Optional base
|
|
260
|
-
# @param string [Boolean] true to set key as
|
|
261
|
-
# @param name [Boolean]
|
|
256
|
+
# @param hash [Hash,nil] Optional base `Hash` (modified)
|
|
257
|
+
# @param string [Boolean] `true` to set key as `String`, else as `Symbol`
|
|
258
|
+
# @param name [Boolean] Include name
|
|
262
259
|
# @return [Hash] with key `workspace_[id,name]` (symbol or string) only if defined
|
|
263
|
-
def workspace_id_hash(hash
|
|
260
|
+
def workspace_id_hash(hash = nil, string: false, name: false)
|
|
264
261
|
info = aoc_api.workspace
|
|
265
262
|
hash = {} if hash.nil?
|
|
266
263
|
fields = %i[id]
|
|
@@ -273,12 +270,12 @@ module Aspera
|
|
|
273
270
|
return hash
|
|
274
271
|
end
|
|
275
272
|
|
|
276
|
-
# Get resource identifier from command line, either directly or from name.
|
|
273
|
+
# Get resource identifier from command line, either directly specifying the `id` or from `name` (percent selector).
|
|
277
274
|
# @param resource_class_path url path for resource
|
|
278
275
|
# @return identifier
|
|
279
276
|
def get_resource_id_from_args(resource_class_path)
|
|
280
277
|
return instance_identifier do |field, value|
|
|
281
|
-
Aspera.assert(field.eql?('name'), type:
|
|
278
|
+
Aspera.assert(field.eql?('name'), type: BadArgument){'only selection by name is supported'}
|
|
282
279
|
aoc_api.lookup_by_name(resource_class_path, value)['id']
|
|
283
280
|
end
|
|
284
281
|
end
|
|
@@ -300,7 +297,7 @@ module Aspera
|
|
|
300
297
|
query = query_read_delete(default: default_query)
|
|
301
298
|
# caller may add specific modifications or checks to query
|
|
302
299
|
yield(query) if block_given?
|
|
303
|
-
result = aoc_api.read_with_paging(resource_class_path, base_query.merge(query).compact
|
|
300
|
+
result = aoc_api.read_with_paging(resource_class_path, base_query.merge(query).compact)
|
|
304
301
|
return Main.result_object_list(result[:items], fields: fields, total: result[:total])
|
|
305
302
|
end
|
|
306
303
|
|
|
@@ -312,7 +309,7 @@ module Aspera
|
|
|
312
309
|
# TODO : craft a query that looks for dropbox only in current workspace
|
|
313
310
|
query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query.delete('dropbox_name'))['id']
|
|
314
311
|
end
|
|
315
|
-
workspace_id_hash(
|
|
312
|
+
workspace_id_hash(query, string: true)
|
|
316
313
|
# by default show dropbox packages only for dropboxes
|
|
317
314
|
query['exclude_dropbox_packages'] = !query.key?('dropbox_id') unless query.key?('exclude_dropbox_packages')
|
|
318
315
|
end
|
|
@@ -325,7 +322,7 @@ module Aspera
|
|
|
325
322
|
Aspera.assert_type(query, Hash){'query'}
|
|
326
323
|
PACKAGE_RECEIVED_BASE_QUERY.each{ |k, v| query[k] = v unless query.key?(k)}
|
|
327
324
|
resolve_dropbox_name_default_ws_id(query)
|
|
328
|
-
return aoc_api.read_with_paging('packages', query.compact
|
|
325
|
+
return aoc_api.read_with_paging('packages', query.compact)
|
|
329
326
|
end
|
|
330
327
|
|
|
331
328
|
NODE4_EXT_COMMANDS = %i[transfer].concat(Node::COMMANDS_GEN4).freeze
|
|
@@ -470,11 +467,11 @@ module Aspera
|
|
|
470
467
|
return Main.result_success
|
|
471
468
|
when :do
|
|
472
469
|
command_repo = options.get_next_command(NODE4_EXT_COMMANDS)
|
|
473
|
-
return execute_nodegen4_command(command_repo, res_id, scope: Api::Node::
|
|
470
|
+
return execute_nodegen4_command(command_repo, res_id, scope: Api::Node::Scope::ADMIN)
|
|
474
471
|
when :bearer_token
|
|
475
472
|
node_api = aoc_api.node_api_from(
|
|
476
473
|
node_id: res_id,
|
|
477
|
-
scope: options.get_next_argument('scope')
|
|
474
|
+
scope: options.get_next_argument('scope', default: Api::Node::Scope::ADMIN)
|
|
478
475
|
)
|
|
479
476
|
return Main.result_text(node_api.oauth.authorization)
|
|
480
477
|
when :dropbox
|
|
@@ -504,7 +501,7 @@ module Aspera
|
|
|
504
501
|
node_id: shared_folder['node_id'],
|
|
505
502
|
workspace_id: res_id,
|
|
506
503
|
workspace_name: nil,
|
|
507
|
-
scope: Api::Node::
|
|
504
|
+
scope: Api::Node::Scope::USER
|
|
508
505
|
)
|
|
509
506
|
result = node_api.read(
|
|
510
507
|
'permissions',
|
|
@@ -741,110 +738,132 @@ module Aspera
|
|
|
741
738
|
end
|
|
742
739
|
end
|
|
743
740
|
|
|
744
|
-
# Create a
|
|
745
|
-
#
|
|
746
|
-
#
|
|
747
|
-
#
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
741
|
+
# Create a short link for the given entity: Shared folder or Shared Inbox
|
|
742
|
+
# Short link entity: `short_links` have:
|
|
743
|
+
# - a numerical id, e.g. `764412`
|
|
744
|
+
# - a resource type, e.g. `UrlToken`
|
|
745
|
+
# - a ressource id, e.g. `scQ7uXPbvQ`
|
|
746
|
+
# - a short URL path, e.g. `dxyRpT9`
|
|
747
|
+
# @param shared_data [Hash] Information for shared data: dropbox_id+name or file_id+node_id
|
|
748
|
+
# @param &perm_block [Proc] Optional: create/modify/delete permissions on node
|
|
749
|
+
def short_link_command(**shared_data, &perm_block)
|
|
750
|
+
link_type = options.get_next_argument('link access (public or private)', accept_list: %i[public private])
|
|
751
|
+
if shared_data.keys.sort == %i[dropbox_id name]
|
|
752
|
+
# Packages app, Shared inbox
|
|
753
|
+
token_purpose = 'send_package_to_dropbox'
|
|
754
|
+
short_link_purpose = link_type.eql?(:public) ? 'send_package_to_dropbox' : 'shared_folder_auth_link'
|
|
755
|
+
elsif shared_data.keys.sort == %i[file_id node_id]
|
|
756
|
+
# Files app, Shared folder
|
|
757
|
+
token_purpose = 'view_shared_file'
|
|
758
|
+
short_link_purpose = link_type.eql?(:public) ? 'token_auth_redirection' : 'shared_folder_auth_link'
|
|
759
|
+
else
|
|
760
|
+
Aspera.error_unexpected_value(shared_data.keys)
|
|
759
761
|
end
|
|
760
|
-
command = options.get_next_command(%i[create delete list show modify])
|
|
762
|
+
command = options.get_next_command(%i[create delete list show] + (link_type.eql?(:public) ? %i[modify] : []))
|
|
761
763
|
case command
|
|
762
764
|
when :create
|
|
763
|
-
|
|
764
|
-
|
|
765
|
+
# Add workspace id
|
|
766
|
+
workspace_id_hash(shared_data)
|
|
767
|
+
create_payload = {
|
|
768
|
+
purpose: short_link_purpose,
|
|
765
769
|
user_selected_name: nil
|
|
766
770
|
}
|
|
767
771
|
case link_type
|
|
768
772
|
when :private
|
|
769
|
-
|
|
773
|
+
create_payload[:data] = shared_data
|
|
770
774
|
when :public
|
|
771
|
-
|
|
772
|
-
|
|
775
|
+
create_payload[:expires_at] = nil
|
|
776
|
+
create_payload[:password_enabled] = false
|
|
773
777
|
shared_data[:name] = ''
|
|
774
|
-
|
|
778
|
+
create_payload[:data] = {
|
|
775
779
|
aoc: true,
|
|
776
780
|
url_token_data: {
|
|
777
781
|
data: shared_data,
|
|
778
|
-
purpose:
|
|
782
|
+
purpose: token_purpose
|
|
779
783
|
}
|
|
780
784
|
}
|
|
781
785
|
end
|
|
782
786
|
custom_data = value_create_modify(command: command, default: {})
|
|
787
|
+
access_levels = custom_data.delete('access_levels')
|
|
783
788
|
if (pass = custom_data.delete('password'))
|
|
784
|
-
|
|
785
|
-
|
|
789
|
+
create_payload[:data][:url_token_data][:password] = pass
|
|
790
|
+
create_payload[:password_enabled] = true
|
|
786
791
|
end
|
|
787
|
-
|
|
788
|
-
result_create_short_link = aoc_api.create('short_links',
|
|
789
|
-
#
|
|
790
|
-
yield(result_create_short_link['resource_id']) if block_given? && link_type.eql?(:public)
|
|
792
|
+
create_payload.deep_merge!(custom_data)
|
|
793
|
+
result_create_short_link = aoc_api.create('short_links', create_payload)
|
|
794
|
+
# Creation: perm_block: permission on node
|
|
795
|
+
yield(:create, result_create_short_link['resource_id'], access_levels) if block_given? && link_type.eql?(:public)
|
|
791
796
|
return Main.result_single_object(result_create_short_link)
|
|
792
|
-
when :list, :show
|
|
797
|
+
when :delete, :list, :show, :modify
|
|
798
|
+
workspace_id_hash(shared_data)
|
|
793
799
|
query = if link_type.eql?(:private)
|
|
794
800
|
shared_data
|
|
795
801
|
else
|
|
796
802
|
{
|
|
797
803
|
url_token_data: {
|
|
798
804
|
data: shared_data,
|
|
799
|
-
purpose:
|
|
805
|
+
purpose: token_purpose
|
|
800
806
|
}
|
|
801
807
|
}
|
|
802
808
|
end
|
|
803
809
|
list_params = {
|
|
804
810
|
json_query: query.to_json,
|
|
805
|
-
purpose:
|
|
811
|
+
purpose: short_link_purpose,
|
|
806
812
|
edit_access: true,
|
|
807
813
|
# embed: 'updated_by_user',
|
|
808
814
|
sort: '-created_at'
|
|
809
815
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
816
|
+
short_list = aoc_api.read_with_paging('short_links', list_params.merge(query_read_delete(default: {})).compact)
|
|
817
|
+
case command
|
|
818
|
+
when :delete
|
|
819
|
+
one_id = instance_identifier(description: 'short link id')
|
|
820
|
+
if link_type.eql?(:public)
|
|
821
|
+
found = short_list[:items].find{ |item| item['id'].eql?(one_id)}
|
|
822
|
+
raise BadIdentifier.new('Short link', one_id) if found.nil?
|
|
823
|
+
yield(:delete, found['resource_id'], nil)
|
|
824
|
+
end
|
|
825
|
+
aoc_api.delete("short_links/#{one_id}", {
|
|
826
|
+
edit_access: true,
|
|
827
|
+
json_query: shared_data.to_json
|
|
828
|
+
})
|
|
829
|
+
return Main.result_status('deleted')
|
|
830
|
+
when :list
|
|
831
|
+
return Main.result_object_list(short_list[:items], fields: Formatter.all_but('data'), total: short_list[:total])
|
|
832
|
+
when :show
|
|
833
|
+
one_id = instance_identifier(description: 'short link id')
|
|
834
|
+
found = short_list[:items].find{ |item| item['id'].eql?(one_id)}
|
|
835
|
+
raise BadIdentifier.new('Short link', one_id) if found.nil?
|
|
836
|
+
return Main.result_single_object(found, fields: Formatter.all_but('data'))
|
|
837
|
+
when :modify
|
|
838
|
+
one_id = instance_identifier(description: 'short link id')
|
|
839
|
+
node_file = shared_data.slice(:node_id, :file_id)
|
|
840
|
+
modify_payload = {
|
|
841
|
+
edit_access: true,
|
|
842
|
+
json_query: node_file
|
|
843
|
+
}
|
|
844
|
+
custom_data = value_create_modify(command: command)
|
|
845
|
+
if (pass = custom_data.delete('password'))
|
|
846
|
+
modify_payload[:password_enabled] = true
|
|
847
|
+
modify_payload[:data] = {
|
|
848
|
+
url_token_data: {
|
|
849
|
+
password: pass,
|
|
850
|
+
data: node_file
|
|
851
|
+
}
|
|
822
852
|
}
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
when :delete
|
|
836
|
-
one_id = instance_identifier
|
|
837
|
-
shared_data.delete(:workspace_id)
|
|
838
|
-
delete_params = {
|
|
839
|
-
edit_access: true,
|
|
840
|
-
json_query: shared_data.to_json
|
|
841
|
-
}
|
|
842
|
-
aoc_api.delete("short_links/#{one_id}", delete_params)
|
|
843
|
-
if link_type.eql?(:public)
|
|
844
|
-
# TODO: get permission id..
|
|
845
|
-
# shared_apfid[:api].delete('permissions', {ids: })
|
|
853
|
+
else
|
|
854
|
+
modify_payload[:password_enabled] = false
|
|
855
|
+
end
|
|
856
|
+
if custom_data.delete('access_levels')
|
|
857
|
+
# Modification: perm_block: permission on node
|
|
858
|
+
found = short_list[:items].find{ |item| item['id'].eql?(one_id)}
|
|
859
|
+
raise BadIdentifier.new('Short link', one_id) if found.nil?
|
|
860
|
+
yield(:update, found['resource_id'], access_levels)
|
|
861
|
+
end
|
|
862
|
+
modify_payload.deep_merge!(custom_data)
|
|
863
|
+
aoc_api.update("short_links/#{one_id}", modify_payload)
|
|
864
|
+
return Main.result_status('modified')
|
|
846
865
|
end
|
|
847
|
-
|
|
866
|
+
else Aspera.error_unexpected_value(command)
|
|
848
867
|
end
|
|
849
868
|
end
|
|
850
869
|
|
|
@@ -935,24 +954,20 @@ module Aspera
|
|
|
935
954
|
case options.get_next_command(%i[list show short_link])
|
|
936
955
|
when :list
|
|
937
956
|
default_query = {'embed[]' => 'dropbox', 'aggregate_permissions_by_dropbox' => true, 'sort' => 'dropbox_name'}
|
|
938
|
-
workspace_id_hash(
|
|
957
|
+
workspace_id_hash(default_query, string: true)
|
|
939
958
|
return result_list('dropbox_memberships', fields: %w[dropbox_id dropbox.name], default_query: default_query)
|
|
940
959
|
when :show
|
|
941
960
|
return Main.result_single_object(aoc_api.read(get_resource_path_from_args('dropboxes')))
|
|
942
961
|
when :short_link
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
dropbox_id: get_resource_id_from_args('dropboxes'),
|
|
946
|
-
name: '',
|
|
947
|
-
**workspace_id_hash
|
|
948
|
-
)
|
|
962
|
+
# TODO: check name
|
|
963
|
+
return short_link_command(dropbox_id: get_resource_id_from_args('dropboxes'), name: '')
|
|
949
964
|
end
|
|
950
965
|
when :send
|
|
951
966
|
package_data = value_create_modify(command: package_command)
|
|
952
967
|
new_user_option = options.get_option(:new_user_option)
|
|
953
968
|
option_validate = options.get_option(:validate_metadata)
|
|
954
969
|
# Works for both normal user auth and link auth.
|
|
955
|
-
workspace_id_hash(
|
|
970
|
+
workspace_id_hash(package_data, string: true) unless package_data.key?('workspace_id')
|
|
956
971
|
if !aoc_api.public_link.nil?
|
|
957
972
|
aoc_api.assert_public_link_types(%w[send_package_to_user send_package_to_dropbox])
|
|
958
973
|
box_type = aoc_api.public_link['purpose'].split('_').last
|
|
@@ -1041,7 +1056,7 @@ module Aspera
|
|
|
1041
1056
|
return Main.result_object_list(result[:items], fields: display_fields, total: result[:total])
|
|
1042
1057
|
when :delete
|
|
1043
1058
|
return do_bulk_operation(command: package_command, values: instance_identifier) do |id|
|
|
1044
|
-
Aspera.
|
|
1059
|
+
Aspera.assert_type(id, String, Integer){'identifier'}
|
|
1045
1060
|
aoc_api.delete("packages/#{id}")
|
|
1046
1061
|
end
|
|
1047
1062
|
when :modify
|
|
@@ -1052,13 +1067,13 @@ module Aspera
|
|
|
1052
1067
|
when *Node::NODE4_READ_ACTIONS
|
|
1053
1068
|
package_id = instance_identifier
|
|
1054
1069
|
package_info = aoc_api.read("packages/#{package_id}")
|
|
1055
|
-
return execute_nodegen4_command(package_command, package_info['node_id'], file_id: package_info['contents_file_id'], scope: Api::Node::
|
|
1070
|
+
return execute_nodegen4_command(package_command, package_info['node_id'], file_id: package_info['contents_file_id'], scope: Api::Node::Scope::USER)
|
|
1056
1071
|
end
|
|
1057
1072
|
when :files
|
|
1058
1073
|
command_repo = options.get_next_command([:short_link].concat(NODE4_EXT_COMMANDS))
|
|
1059
1074
|
case command_repo
|
|
1060
1075
|
when *NODE4_EXT_COMMANDS
|
|
1061
|
-
return execute_nodegen4_command(command_repo, aoc_api.home[:node_id], file_id: aoc_api.home[:file_id], scope: Api::Node::
|
|
1076
|
+
return execute_nodegen4_command(command_repo, aoc_api.home[:node_id], file_id: aoc_api.home[:file_id], scope: Api::Node::Scope::USER)
|
|
1062
1077
|
when :short_link
|
|
1063
1078
|
folder_dest = options.get_next_argument('path', validation: String)
|
|
1064
1079
|
home_node_api = aoc_api.node_api_from(
|
|
@@ -1067,33 +1082,42 @@ module Aspera
|
|
|
1067
1082
|
)
|
|
1068
1083
|
shared_apfid = home_node_api.resolve_api_fid(aoc_api.home[:file_id], folder_dest)
|
|
1069
1084
|
return short_link_command(
|
|
1070
|
-
purpose_public: 'view_shared_file',
|
|
1071
1085
|
node_id: shared_apfid[:api].app_info[:node_info]['id'],
|
|
1072
|
-
file_id: shared_apfid[:file_id]
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1086
|
+
file_id: shared_apfid[:file_id]
|
|
1087
|
+
) do |op, id, access_levels|
|
|
1088
|
+
case op
|
|
1089
|
+
when :create
|
|
1090
|
+
# `id` is the resource id
|
|
1091
|
+
perm_data = {
|
|
1092
|
+
'file_id' => shared_apfid[:file_id],
|
|
1093
|
+
'access_id' => id,
|
|
1094
|
+
'access_type' => 'user',
|
|
1095
|
+
'access_levels' => Api::AoC.expand_access_levels(access_levels),
|
|
1096
|
+
'tags' => {
|
|
1097
|
+
'url_token' => true,
|
|
1098
|
+
'folder_name' => File.basename(folder_dest),
|
|
1099
|
+
'created_by_name' => aoc_api.current_user_info['name'],
|
|
1100
|
+
'created_by_email' => aoc_api.current_user_info['email'],
|
|
1101
|
+
'access_key' => shared_apfid[:api].app_info[:node_info]['access_key'],
|
|
1102
|
+
'node' => shared_apfid[:api].app_info[:node_info]['name'],
|
|
1103
|
+
**workspace_id_hash(string: true, name: true)
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
created_data = shared_apfid[:api].create('permissions', perm_data)
|
|
1107
|
+
aoc_api.permissions_send_event(event_data: created_data, app_info: shared_apfid[:api].app_info)
|
|
1108
|
+
when :update
|
|
1109
|
+
# `id` is the permission_id
|
|
1110
|
+
found = shared_apfid[:api].read('permissions', {file_id: shared_apfid[:file_id], inherited: false, access_type: 'user', access_id: id}).find{ |i| i['access_id'].eql?(id)}
|
|
1111
|
+
raise Error, 'Short link not found: #{id}' if found.nil?
|
|
1112
|
+
shared_apfid[:api].update("permissions/#{found['id']}", {access_levels: Api::AoC.expand_access_levels(access_levels)})
|
|
1113
|
+
when :delete
|
|
1114
|
+
# `id` is the resource id, i.e. `access_id`
|
|
1115
|
+
found = shared_apfid[:api].read('permissions', {file_id: shared_apfid[:file_id], inherited: false, access_type: 'user', access_id: id}).first
|
|
1116
|
+
raise Error, 'Short link not found: #{id}' if found.nil?
|
|
1117
|
+
shared_apfid[:api].delete("permissions/#{found['id']}")
|
|
1118
|
+
else Aspera.error_unexpected_value(op)
|
|
1119
|
+
end
|
|
1120
|
+
end
|
|
1097
1121
|
end
|
|
1098
1122
|
when :automation
|
|
1099
1123
|
change_api_scope(Api::AoC::Scope::ADMIN_USER)
|
|
@@ -22,7 +22,6 @@ module Aspera
|
|
|
22
22
|
class << self
|
|
23
23
|
def declare_options(options)
|
|
24
24
|
options.declare(:query, 'Additional filter for for some commands (list/delete)', allowed: [Hash, Array, NilClass])
|
|
25
|
-
options.declare(:property, 'Name of property to set (modify operation)')
|
|
26
25
|
options.declare(:bulk, 'Bulk operation (only some)', allowed: Allowed::TYPES_BOOLEAN, default: false)
|
|
27
26
|
options.declare(:bfail, 'Bulk operation error handling', allowed: Allowed::TYPES_BOOLEAN, default: true)
|
|
28
27
|
end
|
|
@@ -40,7 +39,7 @@ module Aspera
|
|
|
40
39
|
def initialize(context:)
|
|
41
40
|
# Check presence in descendant of mandatory method and constant
|
|
42
41
|
Aspera.assert(respond_to?(:execute_action), type: InternalError){"Missing method 'execute_action' in #{self.class}"}
|
|
43
|
-
Aspera.assert(self.class.
|
|
42
|
+
Aspera.assert(self.class.const_defined?(:ACTIONS), type: InternalError){"Missing constant 'ACTIONS' in #{self.class}"}
|
|
44
43
|
@context = context
|
|
45
44
|
add_manual_header if @context.man_header
|
|
46
45
|
end
|
|
@@ -70,25 +69,25 @@ module Aspera
|
|
|
70
69
|
# Resource identifier as positional parameter
|
|
71
70
|
#
|
|
72
71
|
# @param description [String] description of the identifier
|
|
73
|
-
# @param block
|
|
72
|
+
# @param &block [Proc] block to search for identifier based on attribute value
|
|
74
73
|
# @return [String, Array] identifier or list of ids
|
|
75
|
-
def instance_identifier(description: 'identifier'
|
|
74
|
+
def instance_identifier(description: 'identifier')
|
|
76
75
|
res_id = options.get_next_argument(description, multiple: options.get_option(:bulk)) if res_id.nil?
|
|
77
76
|
# Can be an Array
|
|
78
77
|
if res_id.is_a?(String) && (m = Base.percent_selector(res_id))
|
|
79
|
-
Aspera.assert(
|
|
78
|
+
Aspera.assert(block_given?, type: Cli::BadArgument){"Percent syntax for #{description} not supported in this context"}
|
|
80
79
|
res_id = yield(m[:field], m[:value])
|
|
81
80
|
end
|
|
82
81
|
return res_id
|
|
83
82
|
end
|
|
84
83
|
|
|
85
84
|
# For create and delete operations: execute one action or multiple if bulk is yes
|
|
86
|
-
# @param command [Symbol]
|
|
87
|
-
# @param descr [String]
|
|
88
|
-
# @param values [Object]
|
|
89
|
-
# @param id_result [String]
|
|
90
|
-
# @param fields [Array]
|
|
91
|
-
# @param &block [Proc]
|
|
85
|
+
# @param command [Symbol] Operation: :create, :delete, ...
|
|
86
|
+
# @param descr [String] Description of the value
|
|
87
|
+
# @param values [Object] Value(s), or type of value to get from user
|
|
88
|
+
# @param id_result [String] Key in result hash to use as identifier
|
|
89
|
+
# @param fields [Array] Fields to display
|
|
90
|
+
# @param &block [Proc] Block to execute for each value
|
|
92
91
|
def do_bulk_operation(command:, descr: nil, values: Hash, id_result: 'id', fields: :default)
|
|
93
92
|
Aspera.assert(block_given?){'missing block'}
|
|
94
93
|
is_bulk = options.get_option(:bulk)
|
|
@@ -178,7 +177,7 @@ module Aspera
|
|
|
178
177
|
api.delete(
|
|
179
178
|
entity,
|
|
180
179
|
nil,
|
|
181
|
-
content_type:
|
|
180
|
+
content_type: Mime::JSON,
|
|
182
181
|
body: {delete_style => one_res_id}
|
|
183
182
|
)
|
|
184
183
|
return Main.result_status('deleted')
|
|
@@ -209,20 +208,18 @@ module Aspera
|
|
|
209
208
|
return Main.result_object_list(data, fields: display_fields) if data.empty? || data.first.is_a?(Hash)
|
|
210
209
|
return Main.result_value_list(data)
|
|
211
210
|
else
|
|
212
|
-
|
|
211
|
+
Aspera.error_unexpected_value(data.class.name){'list type'}
|
|
213
212
|
end
|
|
214
213
|
when :modify
|
|
215
214
|
parameters = value_create_modify(command: command)
|
|
216
|
-
property = options.get_option(:property)
|
|
217
|
-
parameters = {property => parameters} unless property.nil?
|
|
218
215
|
api.update(one_res_path, parameters)
|
|
219
216
|
return Main.result_status('modified')
|
|
220
217
|
else
|
|
221
|
-
|
|
218
|
+
Aspera.error_unexpected_value(command){'command'}
|
|
222
219
|
end
|
|
223
220
|
end
|
|
224
221
|
|
|
225
|
-
# Query parameters in URL suitable for REST: list
|
|
222
|
+
# Query parameters in URL suitable for REST: list/`GET` and delete/`DELETE`
|
|
226
223
|
def query_read_delete(default: nil)
|
|
227
224
|
# Dup default, as it could be frozen
|
|
228
225
|
query = options.get_option(:query) || default.dup
|
|
@@ -267,7 +264,7 @@ module Aspera
|
|
|
267
264
|
# @param entity [String,Symbol] API endpoint of entity to list
|
|
268
265
|
# @param items_key [String] Key in the result to get the list of items (Default: same as `entity`)
|
|
269
266
|
# @param query [Hash,nil] Additional query parameters
|
|
270
|
-
# @return [Array] items, total_count
|
|
267
|
+
# @return [Array<(Array<Hash>, Integer)>] items, total_count
|
|
271
268
|
def list_entities_limit_offset_total_count(
|
|
272
269
|
api:,
|
|
273
270
|
entity:,
|