aspera-cli 4.25.2 → 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 +412 -406
- data/CONTRIBUTING.md +17 -8
- data/README.md +6 -3
- data/lib/aspera/api/aoc.rb +19 -12
- data/lib/aspera/api/faspex.rb +25 -6
- data/lib/aspera/api/node.rb +4 -2
- data/lib/aspera/assert.rb +1 -1
- data/lib/aspera/cli/hints.rb +7 -0
- data/lib/aspera/cli/manager.rb +38 -26
- data/lib/aspera/cli/plugins/aoc.rb +149 -122
- data/lib/aspera/cli/plugins/base.rb +14 -17
- data/lib/aspera/cli/plugins/config.rb +4 -43
- data/lib/aspera/cli/plugins/faspex.rb +4 -4
- data/lib/aspera/cli/plugins/faspex5.rb +70 -73
- 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 +3 -3
- data/lib/aspera/cli/plugins/shares.rb +15 -7
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +7 -0
- data/lib/aspera/faspex_gw.rb +5 -5
- data/lib/aspera/faspex_postproc.rb +4 -4
- data/lib/aspera/log.rb +12 -11
- data/lib/aspera/markdown.rb +5 -0
- data/lib/aspera/node_simulator.rb +1 -1
- data/lib/aspera/oauth/base.rb +1 -1
- data/lib/aspera/oauth/url_json.rb +2 -2
- data/lib/aspera/rest.rb +44 -37
- data/lib/aspera/rest_error_analyzer.rb +38 -36
- data/lib/aspera/rest_errors_aspera.rb +19 -18
- data.tar.gz.sig +0 -0
- metadata +2 -2
- metadata.gz.sig +0 -0
|
@@ -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
|
|
@@ -741,111 +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: {})
|
|
783
787
|
access_levels = custom_data.delete('access_levels')
|
|
784
788
|
if (pass = custom_data.delete('password'))
|
|
785
|
-
|
|
786
|
-
|
|
789
|
+
create_payload[:data][:url_token_data][:password] = pass
|
|
790
|
+
create_payload[:password_enabled] = true
|
|
787
791
|
end
|
|
788
|
-
|
|
789
|
-
result_create_short_link = aoc_api.create('short_links',
|
|
790
|
-
#
|
|
791
|
-
yield(result_create_short_link['resource_id'], access_levels) 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)
|
|
792
796
|
return Main.result_single_object(result_create_short_link)
|
|
793
|
-
when :list, :show
|
|
797
|
+
when :delete, :list, :show, :modify
|
|
798
|
+
workspace_id_hash(shared_data)
|
|
794
799
|
query = if link_type.eql?(:private)
|
|
795
800
|
shared_data
|
|
796
801
|
else
|
|
797
802
|
{
|
|
798
803
|
url_token_data: {
|
|
799
804
|
data: shared_data,
|
|
800
|
-
purpose:
|
|
805
|
+
purpose: token_purpose
|
|
801
806
|
}
|
|
802
807
|
}
|
|
803
808
|
end
|
|
804
809
|
list_params = {
|
|
805
810
|
json_query: query.to_json,
|
|
806
|
-
purpose:
|
|
811
|
+
purpose: short_link_purpose,
|
|
807
812
|
edit_access: true,
|
|
808
813
|
# embed: 'updated_by_user',
|
|
809
814
|
sort: '-created_at'
|
|
810
815
|
}
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
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
|
+
}
|
|
823
852
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
when :delete
|
|
837
|
-
one_id = instance_identifier
|
|
838
|
-
shared_data.delete(:workspace_id)
|
|
839
|
-
delete_params = {
|
|
840
|
-
edit_access: true,
|
|
841
|
-
json_query: shared_data.to_json
|
|
842
|
-
}
|
|
843
|
-
aoc_api.delete("short_links/#{one_id}", delete_params)
|
|
844
|
-
if link_type.eql?(:public)
|
|
845
|
-
# TODO: get permission id..
|
|
846
|
-
# 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')
|
|
847
865
|
end
|
|
848
|
-
|
|
866
|
+
else Aspera.error_unexpected_value(command)
|
|
849
867
|
end
|
|
850
868
|
end
|
|
851
869
|
|
|
@@ -936,24 +954,20 @@ module Aspera
|
|
|
936
954
|
case options.get_next_command(%i[list show short_link])
|
|
937
955
|
when :list
|
|
938
956
|
default_query = {'embed[]' => 'dropbox', 'aggregate_permissions_by_dropbox' => true, 'sort' => 'dropbox_name'}
|
|
939
|
-
workspace_id_hash(
|
|
957
|
+
workspace_id_hash(default_query, string: true)
|
|
940
958
|
return result_list('dropbox_memberships', fields: %w[dropbox_id dropbox.name], default_query: default_query)
|
|
941
959
|
when :show
|
|
942
960
|
return Main.result_single_object(aoc_api.read(get_resource_path_from_args('dropboxes')))
|
|
943
961
|
when :short_link
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
dropbox_id: get_resource_id_from_args('dropboxes'),
|
|
947
|
-
name: '',
|
|
948
|
-
**workspace_id_hash
|
|
949
|
-
)
|
|
962
|
+
# TODO: check name
|
|
963
|
+
return short_link_command(dropbox_id: get_resource_id_from_args('dropboxes'), name: '')
|
|
950
964
|
end
|
|
951
965
|
when :send
|
|
952
966
|
package_data = value_create_modify(command: package_command)
|
|
953
967
|
new_user_option = options.get_option(:new_user_option)
|
|
954
968
|
option_validate = options.get_option(:validate_metadata)
|
|
955
969
|
# Works for both normal user auth and link auth.
|
|
956
|
-
workspace_id_hash(
|
|
970
|
+
workspace_id_hash(package_data, string: true) unless package_data.key?('workspace_id')
|
|
957
971
|
if !aoc_api.public_link.nil?
|
|
958
972
|
aoc_api.assert_public_link_types(%w[send_package_to_user send_package_to_dropbox])
|
|
959
973
|
box_type = aoc_api.public_link['purpose'].split('_').last
|
|
@@ -1042,7 +1056,7 @@ module Aspera
|
|
|
1042
1056
|
return Main.result_object_list(result[:items], fields: display_fields, total: result[:total])
|
|
1043
1057
|
when :delete
|
|
1044
1058
|
return do_bulk_operation(command: package_command, values: instance_identifier) do |id|
|
|
1045
|
-
Aspera.
|
|
1059
|
+
Aspera.assert_type(id, String, Integer){'identifier'}
|
|
1046
1060
|
aoc_api.delete("packages/#{id}")
|
|
1047
1061
|
end
|
|
1048
1062
|
when :modify
|
|
@@ -1068,29 +1082,42 @@ module Aspera
|
|
|
1068
1082
|
)
|
|
1069
1083
|
shared_apfid = home_node_api.resolve_api_fid(aoc_api.home[:file_id], folder_dest)
|
|
1070
1084
|
return short_link_command(
|
|
1071
|
-
purpose_public: 'view_shared_file',
|
|
1072
1085
|
node_id: shared_apfid[:api].app_info[:node_info]['id'],
|
|
1073
|
-
file_id: shared_apfid[:file_id]
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
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
|
|
1094
1121
|
end
|
|
1095
1122
|
when :automation
|
|
1096
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
|
|
@@ -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:,
|
|
@@ -210,7 +210,7 @@ module Aspera
|
|
|
210
210
|
keys_to_delete.each{ |k| @option_http_options.delete(k)}
|
|
211
211
|
OAuth::Factory.instance.persist_mgr = persistency if @option_cache_tokens
|
|
212
212
|
OAuth::Web.additional_info = "#{Info::CMD_NAME} v#{Cli::VERSION}"
|
|
213
|
-
Transfer::Parameters.file_list_folder = File.join(@main_folder,
|
|
213
|
+
Transfer::Parameters.file_list_folder = File.join(@main_folder, FILE_LIST_FOLDER_NAME)
|
|
214
214
|
RestErrorAnalyzer.instance.log_file = File.join(@main_folder, REST_EXCEPTIONS_LOG_FILENAME)
|
|
215
215
|
# Register aspera REST call error handlers
|
|
216
216
|
RestErrorsAspera.register_handlers
|
|
@@ -565,43 +565,6 @@ module Aspera
|
|
|
565
565
|
raise Cli::Error, e.to_s
|
|
566
566
|
end
|
|
567
567
|
|
|
568
|
-
def execute_connect_action
|
|
569
|
-
command = options.get_next_command(%i[list info version])
|
|
570
|
-
if %i[info version].include?(command)
|
|
571
|
-
connect_id = options.get_next_argument('id or title')
|
|
572
|
-
one_res = Products::Connect.instance.versions.find{ |i| i['id'].eql?(connect_id) || i['title'].eql?(connect_id)}
|
|
573
|
-
raise Cli::BadIdentifier.new(:connect, connect_id) if one_res.nil?
|
|
574
|
-
end
|
|
575
|
-
case command
|
|
576
|
-
when :list
|
|
577
|
-
return Main.result_object_list(Products::Connect.instance.versions, fields: %w[id title version])
|
|
578
|
-
when :info
|
|
579
|
-
one_res.delete('links')
|
|
580
|
-
return Main.result_single_object(one_res)
|
|
581
|
-
when :version
|
|
582
|
-
all_links = one_res['links']
|
|
583
|
-
command = options.get_next_command(%i[list download open])
|
|
584
|
-
if %i[download open].include?(command)
|
|
585
|
-
link_title = options.get_next_argument('title or rel')
|
|
586
|
-
one_link = all_links.find{ |i| i['title'].eql?(link_title) || i['rel'].eql?(link_title)}
|
|
587
|
-
raise "no such value: #{link_title}" if one_link.nil?
|
|
588
|
-
end
|
|
589
|
-
case command
|
|
590
|
-
when :list
|
|
591
|
-
return Main.result_object_list(all_links)
|
|
592
|
-
when :download
|
|
593
|
-
archive_path = one_link['href']
|
|
594
|
-
save_to_path = File.join(transfer.destination_folder(Transfer::Spec::DIRECTION_RECEIVE), archive_path.gsub(%r{.*/}, ''))
|
|
595
|
-
Products::Connect.instance.cdn_api.call(operation: 'GET', subpath: archive_path, save_to_file: save_to_path)
|
|
596
|
-
return Main.result_status("Downloaded: #{save_to_path}")
|
|
597
|
-
when :open
|
|
598
|
-
Environment.instance.open_uri(one_link['href'])
|
|
599
|
-
return Main.result_status("Opened: #{one_link['href']}")
|
|
600
|
-
end
|
|
601
|
-
end
|
|
602
|
-
Aspera.error_unreachable_line
|
|
603
|
-
end
|
|
604
|
-
|
|
605
568
|
def install_transfer_sdk
|
|
606
569
|
asked_version = options.get_next_argument('transferd version', mandatory: false)
|
|
607
570
|
name, version, folder = Ascp::Installation.instance.install_sdk(url: options.get_option(:sdk_url, mandatory: true), version: asked_version)
|
|
@@ -609,10 +572,8 @@ module Aspera
|
|
|
609
572
|
end
|
|
610
573
|
|
|
611
574
|
def execute_action_ascp
|
|
612
|
-
command = options.get_next_command(%i[
|
|
575
|
+
command = options.get_next_command(%i[show products info install spec schema errors])
|
|
613
576
|
case command
|
|
614
|
-
when :connect
|
|
615
|
-
return execute_connect_action
|
|
616
577
|
when :show
|
|
617
578
|
return Main.result_text(Ascp::Installation.instance.path(:ascp))
|
|
618
579
|
when :info
|
|
@@ -1198,7 +1159,7 @@ module Aspera
|
|
|
1198
1159
|
# Folder containing custom plugins in user's config folder
|
|
1199
1160
|
ASPERA_PLUGINS_FOLDERNAME = 'plugins'
|
|
1200
1161
|
PERSISTENCY_FOLDER = 'persist_store'
|
|
1201
|
-
|
|
1162
|
+
FILE_LIST_FOLDER_NAME = 'filelists'
|
|
1202
1163
|
REST_EXCEPTIONS_LOG_FILENAME = 'rest_exceptions.log'
|
|
1203
1164
|
ASPERA = 'aspera'
|
|
1204
1165
|
SERVER_COMMAND = 'server'
|
|
@@ -1232,7 +1193,7 @@ module Aspera
|
|
|
1232
1193
|
:CONF_PRESET_DEFAULTS,
|
|
1233
1194
|
:CONF_PRESET_GLOBAL,
|
|
1234
1195
|
:ASPERA_PLUGINS_FOLDERNAME,
|
|
1235
|
-
:
|
|
1196
|
+
:FILE_LIST_FOLDER_NAME,
|
|
1236
1197
|
:REST_EXCEPTIONS_LOG_FILENAME,
|
|
1237
1198
|
:ASPERA,
|
|
1238
1199
|
:DEMO_SERVER,
|
|
@@ -51,7 +51,7 @@ module Aspera
|
|
|
51
51
|
http = api.call(
|
|
52
52
|
operation: 'POST',
|
|
53
53
|
headers: {
|
|
54
|
-
'Content-type' =>
|
|
54
|
+
'Content-type' => Mime::TEXT,
|
|
55
55
|
'Accept' => 'application/xrds+xml'
|
|
56
56
|
},
|
|
57
57
|
ret: :resp
|
|
@@ -254,7 +254,7 @@ module Aspera
|
|
|
254
254
|
package_creation_data = api_public_link.call(
|
|
255
255
|
operation: 'POST',
|
|
256
256
|
subpath: create_path,
|
|
257
|
-
content_type:
|
|
257
|
+
content_type: Mime::JSON,
|
|
258
258
|
body: package_create_params,
|
|
259
259
|
headers: {'Accept' => 'text/javascript'},
|
|
260
260
|
ret: :resp
|
|
@@ -418,9 +418,9 @@ module Aspera
|
|
|
418
418
|
operation: 'POST',
|
|
419
419
|
subpath: 'issue-token',
|
|
420
420
|
query: {'direction' => 'down'},
|
|
421
|
-
content_type:
|
|
421
|
+
content_type: Mime::TEXT,
|
|
422
422
|
body: xml_payload,
|
|
423
|
-
headers: {'Accept' =>
|
|
423
|
+
headers: {'Accept' => Mime::TEXT, 'Content-Type' => 'application/vnd.aspera.url-list+xml'},
|
|
424
424
|
ret: :resp
|
|
425
425
|
).body
|
|
426
426
|
end
|