aspera-cli 4.9.0 → 4.11.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 +20 -0
- data/CHANGELOG.md +509 -0
- data/CONTRIBUTING.md +118 -0
- data/README.md +1241 -916
- data/bin/ascli +4 -4
- data/bin/asession +11 -11
- data/docs/test_env.conf +32 -21
- data/examples/aoc.rb +4 -4
- data/examples/dascli +16 -9
- data/examples/faspex4.rb +8 -8
- data/examples/node.rb +12 -12
- data/examples/server.rb +10 -10
- data/lib/aspera/aoc.rb +273 -266
- data/lib/aspera/ascmd.rb +56 -54
- data/lib/aspera/ats_api.rb +4 -4
- data/lib/aspera/cli/basic_auth_plugin.rb +15 -12
- data/lib/aspera/cli/extended_value.rb +5 -5
- data/lib/aspera/cli/formater.rb +64 -64
- data/lib/aspera/cli/info.rb +2 -2
- data/lib/aspera/cli/listener/line_dump.rb +1 -1
- data/lib/aspera/cli/listener/logger.rb +1 -1
- data/lib/aspera/cli/listener/progress.rb +5 -6
- data/lib/aspera/cli/listener/progress_multi.rb +14 -19
- data/lib/aspera/cli/main.rb +66 -67
- data/lib/aspera/cli/manager.rb +112 -110
- data/lib/aspera/cli/plugin.rb +57 -36
- data/lib/aspera/cli/plugins/alee.rb +4 -4
- data/lib/aspera/cli/plugins/aoc.rb +309 -670
- data/lib/aspera/cli/plugins/ats.rb +44 -46
- data/lib/aspera/cli/plugins/bss.rb +10 -10
- data/lib/aspera/cli/plugins/config.rb +497 -378
- data/lib/aspera/cli/plugins/console.rb +12 -12
- data/lib/aspera/cli/plugins/cos.rb +18 -20
- data/lib/aspera/cli/plugins/faspex.rb +112 -114
- data/lib/aspera/cli/plugins/faspex5.rb +71 -46
- data/lib/aspera/cli/plugins/node.rb +379 -283
- data/lib/aspera/cli/plugins/orchestrator.rb +46 -46
- data/lib/aspera/cli/plugins/preview.rb +122 -114
- data/lib/aspera/cli/plugins/server.rb +137 -83
- data/lib/aspera/cli/plugins/shares.rb +30 -29
- data/lib/aspera/cli/plugins/sync.rb +13 -33
- data/lib/aspera/cli/transfer_agent.rb +60 -59
- data/lib/aspera/cli/version.rb +1 -1
- data/lib/aspera/colors.rb +3 -3
- data/lib/aspera/command_line_builder.rb +27 -27
- data/lib/aspera/cos_node.rb +22 -20
- data/lib/aspera/data_repository.rb +1 -1
- data/lib/aspera/environment.rb +35 -15
- data/lib/aspera/fasp/agent_base.rb +15 -15
- data/lib/aspera/fasp/agent_connect.rb +23 -21
- data/lib/aspera/fasp/agent_direct.rb +66 -64
- data/lib/aspera/fasp/agent_httpgw.rb +141 -78
- data/lib/aspera/fasp/agent_node.rb +23 -21
- data/lib/aspera/fasp/agent_trsdk.rb +20 -20
- data/lib/aspera/fasp/error.rb +3 -2
- data/lib/aspera/fasp/error_info.rb +11 -8
- data/lib/aspera/fasp/installation.rb +79 -79
- data/lib/aspera/fasp/listener.rb +1 -1
- data/lib/aspera/fasp/parameters.rb +86 -71
- data/lib/aspera/fasp/parameters.yaml +7 -4
- data/lib/aspera/fasp/resume_policy.rb +8 -8
- data/lib/aspera/fasp/transfer_spec.rb +35 -2
- data/lib/aspera/fasp/uri.rb +7 -7
- data/lib/aspera/faspex_gw.rb +7 -5
- data/lib/aspera/hash_ext.rb +3 -3
- data/lib/aspera/id_generator.rb +5 -5
- data/lib/aspera/keychain/encrypted_hash.rb +38 -105
- data/lib/aspera/keychain/macos_security.rb +128 -57
- data/lib/aspera/log.rb +7 -7
- data/lib/aspera/nagios.rb +19 -18
- data/lib/aspera/node.rb +209 -35
- data/lib/aspera/oauth.rb +37 -36
- data/lib/aspera/open_application.rb +19 -11
- data/lib/aspera/persistency_action_once.rb +4 -4
- data/lib/aspera/persistency_folder.rb +16 -15
- data/lib/aspera/preview/file_types.rb +8 -8
- data/lib/aspera/preview/generator.rb +67 -67
- data/lib/aspera/preview/utils.rb +27 -27
- data/lib/aspera/proxy_auto_config.js +41 -41
- data/lib/aspera/proxy_auto_config.rb +21 -14
- data/lib/aspera/rest.rb +72 -67
- data/lib/aspera/rest_call_error.rb +2 -1
- data/lib/aspera/rest_error_analyzer.rb +18 -17
- data/lib/aspera/rest_errors_aspera.rb +16 -16
- data/lib/aspera/secret_hider.rb +15 -13
- data/lib/aspera/ssh.rb +11 -10
- data/lib/aspera/sync.rb +158 -44
- data/lib/aspera/temp_file_manager.rb +2 -2
- data/lib/aspera/uri_reader.rb +4 -4
- data/lib/aspera/web_auth.rb +14 -13
- data.tar.gz.sig +0 -0
- metadata +11 -36
- metadata.gz.sig +0 -0
@@ -16,334 +16,94 @@ require 'date'
|
|
16
16
|
module Aspera
|
17
17
|
module Cli
|
18
18
|
module Plugins
|
19
|
-
class Aoc < BasicAuthPlugin
|
19
|
+
class Aoc < Aspera::Cli::BasicAuthPlugin
|
20
20
|
class << self
|
21
21
|
def detect(base_url)
|
22
22
|
api = Rest.new({base_url: base_url})
|
23
23
|
# either in standard domain, or product name in page
|
24
24
|
if URI.parse(base_url).host.end_with?(Aspera::AoC::PROD_DOMAIN) ||
|
25
25
|
api.call({operation: 'GET', redirect_max: 1, headers: {'Accept' => 'text/html'}})[:http].body.include?(Aspera::AoC::PRODUCT_NAME)
|
26
|
-
return {product: :aoc,version: 'SaaS' }
|
26
|
+
return {product: :aoc, version: 'SaaS' }
|
27
27
|
end
|
28
28
|
return nil
|
29
29
|
end
|
30
30
|
end
|
31
31
|
# special value for package id
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
KNOWN_AOC_RES = %i[
|
33
|
+
self
|
34
|
+
organization
|
35
|
+
user
|
36
|
+
group
|
37
|
+
group_membership
|
38
|
+
client
|
39
|
+
contact
|
40
|
+
dropbox
|
41
|
+
node
|
42
|
+
operation
|
43
|
+
package
|
44
|
+
saml_configuration
|
45
|
+
workspace
|
46
|
+
workspace_membership
|
47
|
+
dropbox_membership
|
48
|
+
short_link
|
49
|
+
application
|
50
|
+
client_registration_token
|
51
|
+
client_access_key
|
37
52
|
kms_profile].freeze
|
53
|
+
ENTITY_NAME_SPECIFIER = 'name'
|
38
54
|
|
39
55
|
def initialize(env)
|
40
56
|
super(env)
|
41
|
-
@
|
42
|
-
@
|
43
|
-
@
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
options.
|
48
|
-
options.
|
49
|
-
options.add_opt_simple(:
|
50
|
-
options.add_opt_simple(:
|
51
|
-
options.add_opt_simple(:
|
52
|
-
options.add_opt_simple(:
|
53
|
-
options.add_opt_simple(:
|
54
|
-
options.add_opt_simple(:
|
55
|
-
options.add_opt_simple(:
|
56
|
-
options.add_opt_simple(:
|
57
|
-
options.
|
58
|
-
options.
|
59
|
-
options.
|
60
|
-
options.
|
61
|
-
options.
|
62
|
-
options.
|
63
|
-
options.set_option(:
|
64
|
-
options.set_option(:validate_metadata,:yes)
|
65
|
-
options.set_option(:new_user_option,{'package_contact' => true})
|
66
|
-
options.set_option(:operation,:push)
|
67
|
-
options.set_option(:auth,:jwt)
|
68
|
-
options.set_option(:scope,AoC::SCOPE_FILES_USER)
|
69
|
-
options.set_option(:private_key,'@file:' + env[:private_key_path]) if env[:private_key_path].is_a?(String)
|
70
|
-
options.set_option(:workspace,:default)
|
57
|
+
@cache_workspace_info = nil
|
58
|
+
@cache_home_node_file = nil
|
59
|
+
@cache_api_aoc = nil
|
60
|
+
options.add_opt_list(:auth, Oauth::STD_AUTH_TYPES, 'OAuth type of authentication')
|
61
|
+
options.add_opt_list(:operation, %i[push pull], 'client operation for transfers')
|
62
|
+
options.add_opt_simple(:client_id, 'OAuth API client identifier in application')
|
63
|
+
options.add_opt_simple(:client_secret, 'OAuth API client passcode')
|
64
|
+
options.add_opt_simple(:redirect_uri, 'OAuth API client redirect URI')
|
65
|
+
options.add_opt_simple(:private_key, 'OAuth JWT RSA private key PEM value (prefix file path with @file:)')
|
66
|
+
options.add_opt_simple(:scope, 'OAuth scope for AoC API calls')
|
67
|
+
options.add_opt_simple(:passphrase, 'RSA private key passphrase')
|
68
|
+
options.add_opt_simple(:workspace, 'Name of workspace')
|
69
|
+
options.add_opt_simple(:name, "Resource name (prefer to use keyword #{ENTITY_NAME_SPECIFIER})")
|
70
|
+
options.add_opt_simple(:link, 'Public link to shared resource')
|
71
|
+
options.add_opt_simple(:new_user_option, 'New user creation option for unknown package recipients')
|
72
|
+
options.add_opt_simple(:from_folder, 'Source folder for Folder-to-Folder transfer')
|
73
|
+
options.add_opt_boolean(:validate_metadata, 'Validate shared inbox metadata')
|
74
|
+
options.set_option(:validate_metadata, :yes)
|
75
|
+
options.set_option(:operation, :push)
|
76
|
+
options.set_option(:auth, :jwt)
|
77
|
+
options.set_option(:scope, AoC::SCOPE_FILES_USER)
|
78
|
+
options.set_option(:private_key, '@file:' + env[:private_key_path]) if env[:private_key_path].is_a?(String)
|
79
|
+
options.set_option(:workspace, :default)
|
71
80
|
options.parse_options!
|
72
|
-
|
73
|
-
|
81
|
+
# add node plugin options
|
82
|
+
Node.new(env.merge({man_only: true, skip_basic_auth_options: true}))
|
83
|
+
end
|
84
|
+
|
85
|
+
# build list of options for AoC API, based on options of CLI
|
86
|
+
def aoc_params(subpath)
|
87
|
+
# copy command line options to args
|
88
|
+
return Aspera::AoC::OPTIONS_NEW.each_with_object({subpath: subpath}){|i, m|m[i] = options.get_option(i)}
|
74
89
|
end
|
75
90
|
|
76
91
|
def aoc_api
|
77
|
-
if @
|
78
|
-
@
|
92
|
+
if @cache_api_aoc.nil?
|
93
|
+
@cache_api_aoc = AoC.new(aoc_params(AoC::API_V1))
|
79
94
|
# add keychain for access key secrets
|
80
|
-
@
|
95
|
+
@cache_api_aoc.secret_finder = @agents[:config]
|
81
96
|
end
|
82
|
-
return @
|
83
|
-
end
|
84
|
-
|
85
|
-
# starts transfer using transfer agent
|
86
|
-
def transfer_start(app,direction,node_file,ts_add)
|
87
|
-
ts_add.deep_merge!(AoC.analytics_ts(app,direction,@workspace_info['id'],@workspace_info['name']))
|
88
|
-
ts_add.deep_merge!(aoc_api.console_ts(app))
|
89
|
-
return transfer.start(*aoc_api.tr_spec(app,direction,node_file,ts_add))
|
90
|
-
end
|
91
|
-
|
92
|
-
NODE4_CMD_PATH = %i[bearer_token_node node_info browse find]
|
93
|
-
NODE4_COMMANDS = [NODE4_CMD_PATH,%i[mkdir rename delete upload download transfer http_node_download v3 file]].flatten.freeze
|
94
|
-
|
95
|
-
def execute_node_gen4_command(command_repo,top_node_file)
|
96
|
-
case command_repo
|
97
|
-
when :bearer_token_node
|
98
|
-
thepath = options.get_next_argument('path')
|
99
|
-
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
100
|
-
node_api = aoc_api.get_node_api(node_file[:node_info], use_secret: false)
|
101
|
-
return Main.result_status(node_api.oauth_token)
|
102
|
-
when :node_info
|
103
|
-
thepath = options.get_next_argument('path')
|
104
|
-
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
105
|
-
node_api = aoc_api.get_node_api(node_file[:node_info], use_secret: false)
|
106
|
-
return {type: :single_object,data: {
|
107
|
-
url: node_file[:node_info]['url'],
|
108
|
-
username: node_file[:node_info]['access_key'],
|
109
|
-
password: node_api.oauth_token,
|
110
|
-
root_id: node_file[:file_id]
|
111
|
-
}}
|
112
|
-
when :browse
|
113
|
-
thepath = options.get_next_argument('path')
|
114
|
-
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
115
|
-
node_api = aoc_api.get_node_api(node_file[:node_info])
|
116
|
-
file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
|
117
|
-
if file_info['type'].eql?('folder')
|
118
|
-
result = node_api.read("files/#{node_file[:file_id]}/files",options.get_option(:value))
|
119
|
-
items = result[:data]
|
120
|
-
self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
|
121
|
-
else
|
122
|
-
items = [file_info]
|
123
|
-
end
|
124
|
-
return {type: :object_list,data: items,fields: %w[name type recursive_size size modified_time access_level]}
|
125
|
-
when :find
|
126
|
-
thepath = options.get_next_argument('path')
|
127
|
-
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
128
|
-
test_block = Aspera::Node.file_matcher(options.get_option(:value))
|
129
|
-
return {type: :object_list,data: aoc_api.find_files(node_file,test_block),fields: ['path']}
|
130
|
-
when :mkdir
|
131
|
-
thepath = options.get_next_argument('path')
|
132
|
-
containing_folder_path = thepath.split(AoC::PATH_SEPARATOR)
|
133
|
-
new_folder = containing_folder_path.pop
|
134
|
-
node_file = aoc_api.resolve_node_file(top_node_file,containing_folder_path.join(AoC::PATH_SEPARATOR))
|
135
|
-
node_api = aoc_api.get_node_api(node_file[:node_info])
|
136
|
-
result = node_api.create("files/#{node_file[:file_id]}/files",{name: new_folder,type: :folder})[:data]
|
137
|
-
return Main.result_status("created: #{result['name']} (id=#{result['id']})")
|
138
|
-
when :rename
|
139
|
-
thepath = options.get_next_argument('source path')
|
140
|
-
newname = options.get_next_argument('new name')
|
141
|
-
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
142
|
-
node_api = aoc_api.get_node_api(node_file[:node_info])
|
143
|
-
result = node_api.update("files/#{node_file[:file_id]}",{name: newname})[:data]
|
144
|
-
return Main.result_status("renamed #{thepath} to #{newname}")
|
145
|
-
when :delete
|
146
|
-
thepath = options.get_next_argument('path')
|
147
|
-
return do_bulk_operation(thepath,'deleted',id_result: 'path') do |l_path|
|
148
|
-
raise "expecting String (path), got #{l_path.class.name} (#{l_path})" unless l_path.is_a?(String)
|
149
|
-
node_file = aoc_api.resolve_node_file(top_node_file,l_path)
|
150
|
-
node_api = aoc_api.get_node_api(node_file[:node_info])
|
151
|
-
result = node_api.delete("files/#{node_file[:file_id]}")[:data]
|
152
|
-
{'path' => l_path}
|
153
|
-
end
|
154
|
-
when :transfer
|
155
|
-
# client side is agent
|
156
|
-
# server side is protocol server
|
157
|
-
# in same workspace
|
158
|
-
server_home_node_file = client_home_node_file = top_node_file
|
159
|
-
# default is push
|
160
|
-
case options.get_option(:operation,is_type: :mandatory)
|
161
|
-
when :push
|
162
|
-
client_tr_oper = Fasp::TransferSpec::DIRECTION_SEND
|
163
|
-
client_folder = options.get_option(:from_folder,is_type: :mandatory)
|
164
|
-
server_folder = transfer.destination_folder(client_tr_oper)
|
165
|
-
when :pull
|
166
|
-
client_tr_oper = Fasp::TransferSpec::DIRECTION_RECEIVE
|
167
|
-
client_folder = transfer.destination_folder(client_tr_oper)
|
168
|
-
server_folder = options.get_option(:from_folder,is_type: :mandatory)
|
169
|
-
end
|
170
|
-
client_node_file = aoc_api.resolve_node_file(client_home_node_file,client_folder)
|
171
|
-
server_node_file = aoc_api.resolve_node_file(server_home_node_file,server_folder)
|
172
|
-
# force node as transfer agent
|
173
|
-
client_node_api = aoc_api.get_node_api(client_node_file[:node_info], use_secret: false)
|
174
|
-
@agents[:transfer].agent_instance = Fasp::AgentNode.new({
|
175
|
-
url: client_node_api.params[:base_url],
|
176
|
-
username: client_node_file[:node_info]['access_key'],
|
177
|
-
password: client_node_api.oauth_token,
|
178
|
-
root_id: client_node_file[:file_id]
|
179
|
-
})
|
180
|
-
# additional node to node TS info
|
181
|
-
add_ts = {
|
182
|
-
'remote_access_key' => server_node_file[:node_info]['access_key'],
|
183
|
-
'destination_root_id' => server_node_file[:file_id],
|
184
|
-
'source_root_id' => client_node_file[:file_id]
|
185
|
-
}
|
186
|
-
return Main.result_transfer(transfer_start(AoC::FILES_APP,client_tr_oper,server_node_file,add_ts))
|
187
|
-
when :upload
|
188
|
-
node_file = aoc_api.resolve_node_file(top_node_file,transfer.destination_folder(Fasp::TransferSpec::DIRECTION_SEND))
|
189
|
-
add_ts = {'tags' => {'aspera' => {'files' => {'parentCwd' => "#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
|
190
|
-
return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_SEND,node_file,add_ts))
|
191
|
-
when :download
|
192
|
-
source_paths = transfer.ts_source_paths
|
193
|
-
# special case for AoC : all files must be in same folder
|
194
|
-
source_folder = source_paths.shift['source']
|
195
|
-
# if a single file: split into folder and path
|
196
|
-
if source_paths.empty?
|
197
|
-
source_folder = source_folder.split(AoC::PATH_SEPARATOR)
|
198
|
-
source_paths = [{'source' => source_folder.pop}]
|
199
|
-
source_folder = source_folder.join(AoC::PATH_SEPARATOR)
|
200
|
-
end
|
201
|
-
node_file = aoc_api.resolve_node_file(top_node_file,source_folder)
|
202
|
-
# override paths with just filename
|
203
|
-
add_ts = {'tags' => {'aspera' => {'files' => {'parentCwd' => "#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
|
204
|
-
add_ts['paths'] = source_paths
|
205
|
-
return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_RECEIVE,node_file,add_ts))
|
206
|
-
when :http_node_download
|
207
|
-
source_paths = transfer.ts_source_paths
|
208
|
-
source_folder = source_paths.shift['source']
|
209
|
-
if source_paths.empty?
|
210
|
-
source_folder = source_folder.split(AoC::PATH_SEPARATOR)
|
211
|
-
source_paths = [{'source' => source_folder.pop}]
|
212
|
-
source_folder = source_folder.join(AoC::PATH_SEPARATOR)
|
213
|
-
end
|
214
|
-
raise CliBadArgument,'one file at a time only in HTTP mode' if source_paths.length > 1
|
215
|
-
file_name = source_paths.first['source']
|
216
|
-
node_file = aoc_api.resolve_node_file(top_node_file,File.join(source_folder,file_name))
|
217
|
-
node_api = aoc_api.get_node_api(node_file[:node_info])
|
218
|
-
node_api.call(
|
219
|
-
operation: 'GET',
|
220
|
-
subpath: "files/#{node_file[:file_id]}/content",
|
221
|
-
save_to_file: File.join(transfer.destination_folder(Fasp::TransferSpec::DIRECTION_RECEIVE),file_name))
|
222
|
-
return Main.result_status("downloaded: #{file_name}")
|
223
|
-
when :v3
|
224
|
-
# Note: other common actions are unauthorized with user scope
|
225
|
-
command_legacy = options.get_next_command(Node::SIMPLE_ACTIONS)
|
226
|
-
# TODO: shall we support all methods here ? what if there is a link ?
|
227
|
-
node_api = aoc_api.get_node_api(top_node_file[:node_info])
|
228
|
-
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: node_api)).execute_action(command_legacy)
|
229
|
-
when :file
|
230
|
-
command_node_file = options.get_next_command(%i[show permission modify])
|
231
|
-
file_path = options.get_option(:path)
|
232
|
-
node_file =
|
233
|
-
if !file_path.nil?
|
234
|
-
# directly returns node_file info
|
235
|
-
aoc_api.resolve_node_file(top_node_file,file_path) # TODO: allow follow link ?
|
236
|
-
else
|
237
|
-
# build node_file info from next argument on command line
|
238
|
-
{node_info: top_node_file[:node_info],file_id: instance_identifier}
|
239
|
-
end
|
240
|
-
node_api = aoc_api.get_node_api(node_file[:node_info])
|
241
|
-
case command_node_file
|
242
|
-
when :show
|
243
|
-
items = node_api.read("files/#{node_file[:file_id]}")[:data]
|
244
|
-
return {type: :single_object,data: items}
|
245
|
-
when :modify
|
246
|
-
update_param = options.get_next_argument('update data (Hash)')
|
247
|
-
res = node_api.update("files/#{node_file[:file_id]}",update_param)[:data]
|
248
|
-
return {type: :single_object,data: res}
|
249
|
-
when :permission
|
250
|
-
command_perm = options.get_next_command(%i[list create delete])
|
251
|
-
case command_perm
|
252
|
-
when :list
|
253
|
-
# generic options : TODO: as arg ? option_url_query
|
254
|
-
list_options ||= {'include' => ['[]','access_level','permission_count']}
|
255
|
-
# special value: ALL will show all permissions
|
256
|
-
if !VAL_ALL.eql?(node_file[:file_id])
|
257
|
-
# add which one to get
|
258
|
-
list_options['file_id'] = node_file[:file_id]
|
259
|
-
list_options['inherited'] ||= false
|
260
|
-
end
|
261
|
-
items = node_api.read('permissions',list_options)[:data]
|
262
|
-
return {type: :object_list,data: items}
|
263
|
-
when :delete
|
264
|
-
perm_id=instance_identifier
|
265
|
-
return do_bulk_operation(perm_id,'deleted') do |one_id|
|
266
|
-
node_api.delete("permissions/#{perm_id}")
|
267
|
-
{'id' => one_id}
|
268
|
-
end
|
269
|
-
#node_api.delete("permissions/#{perm_id}")
|
270
|
-
when :create
|
271
|
-
create_param=options.get_next_argument('creation data (Hash)')
|
272
|
-
#access_id = "#{ID_AK_ADMIN}_WS_#{@workspace_info['id']}"
|
273
|
-
default_params = {
|
274
|
-
'file_id' => node_file[:file_id], # mandatory
|
275
|
-
#'access_type' => 'user', # mandatory: user or group
|
276
|
-
#'access_id' => access_id, # id of user or group
|
277
|
-
'access_levels' => Aspera::Node::ACCESS_LEVELS,
|
278
|
-
'tags' => {'aspera' => {'files' => {'workspace' => {
|
279
|
-
'id' => @workspace_info['id'],
|
280
|
-
'workspace_name' => @workspace_info['name'],
|
281
|
-
'user_name' => aoc_api.user_info['name'],
|
282
|
-
'shared_by_user_id' => aoc_api.user_info['id'],
|
283
|
-
'shared_by_name' => aoc_api.user_info['name'],
|
284
|
-
'shared_by_email' => aoc_api.user_info['email'],
|
285
|
-
#'shared_with_name' => access_id,
|
286
|
-
'access_key' => node_file[:node_info]['access_key'],
|
287
|
-
'node' => node_file[:node_info]['name']}}}}}
|
288
|
-
create_param = default_params.deep_merge(create_param)
|
289
|
-
if create_param.has_key?('with')
|
290
|
-
contact_info = aoc_api.lookup_entity_by_name(
|
291
|
-
'contacts',
|
292
|
-
create_param['with'],
|
293
|
-
{'current_workspace_id' => @workspace_info['id'],'context'=> 'share_folder'})
|
294
|
-
create_param.delete('with')
|
295
|
-
create_param['access_type']=contact_info['source_type']
|
296
|
-
create_param['access_id']=contact_info['source_id']
|
297
|
-
create_param['tags']['aspera']['files']['workspace']['shared_with_name']=contact_info['email']
|
298
|
-
end
|
299
|
-
opt_link_name=nil
|
300
|
-
if create_param.has_key?('link_name')
|
301
|
-
opt_link_name=create_param['link_name']
|
302
|
-
create_param.delete('link_name')
|
303
|
-
end
|
304
|
-
# for admin type:
|
305
|
-
#node_file[:node_info]
|
306
|
-
#node_api = aoc_api.get_node_api(node_file[:node_info])
|
307
|
-
created_data = node_api.create('permissions',create_param)[:data]
|
308
|
-
event_creation={
|
309
|
-
'types' => ['permission.created'],
|
310
|
-
'node_id' => node_file[:node_info]['id'],
|
311
|
-
'workspace_id' => @workspace_info['id'],
|
312
|
-
'data' => created_data # Response from previous step
|
313
|
-
}
|
314
|
-
#(optional). The name of the folder to be displayed to the destination user. Use it if its value is different from the "share_as" field.
|
315
|
-
event_creation['link_name']=opt_link_name unless opt_link_name.nil?
|
316
|
-
aoc_api.create('events',event_creation)
|
317
|
-
return { type: :single_object, data: created_data}
|
318
|
-
else raise "internal error:shall not reach here (#{command_perm})"
|
319
|
-
end
|
320
|
-
else raise "internal error:shall not reach here (#{command_node_file})"
|
321
|
-
end
|
322
|
-
end # command_repo
|
323
|
-
raise 'internal error:shall not reach here'
|
324
|
-
end # execute_node_gen4_command
|
325
|
-
AOC_PARAMS_COPY=%i[link url auth client_id client_secret scope redirect_uri private_key passphrase username password].freeze
|
326
|
-
# build constructor option list for AoC based on options of CLI
|
327
|
-
def aoc_params(subpath)
|
328
|
-
# copy command line options to args
|
329
|
-
opt = AOC_PARAMS_COPY.each_with_object({}){|i,m|m[i] = options.get_option(i)}
|
330
|
-
opt[:subpath] = subpath
|
331
|
-
return opt
|
97
|
+
return @cache_api_aoc
|
332
98
|
end
|
333
99
|
|
334
|
-
#
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
def set_workspace_info
|
340
|
-
@url_token_data = aoc_api.url_token_data
|
341
|
-
if @url_token_data.nil?
|
342
|
-
default_workspace_id = aoc_api.user_info['default_workspace_id']
|
343
|
-
@persist_ids = [aoc_api.user_info['id']]
|
100
|
+
# @return [Hash] current workspace information,
|
101
|
+
def current_workspace_info
|
102
|
+
return @cache_workspace_info unless @cache_workspace_info.nil?
|
103
|
+
default_workspace_id = if aoc_api.url_token_data.nil?
|
104
|
+
aoc_api.user_info['default_workspace_id']
|
344
105
|
else
|
345
|
-
|
346
|
-
@persist_ids = [] # TODO : @url_token_data['id'] ?
|
106
|
+
aoc_api.url_token_data['data']['workspace_id']
|
347
107
|
end
|
348
108
|
|
349
109
|
ws_name = options.get_option(:workspace)
|
@@ -351,42 +111,42 @@ module Aspera
|
|
351
111
|
case ws_name
|
352
112
|
when :default
|
353
113
|
Log.log.debug('Using default workspace'.green)
|
354
|
-
raise CliError,'No default workspace defined for user, please specify workspace' if default_workspace_id.nil?
|
114
|
+
raise CliError, 'No default workspace defined for user, please specify workspace' if default_workspace_id.nil?
|
355
115
|
default_workspace_id
|
356
|
-
when String then aoc_api.lookup_entity_by_name('workspaces',ws_name)['id']
|
116
|
+
when String then aoc_api.lookup_entity_by_name('workspaces', ws_name)['id']
|
357
117
|
when NilClass then nil
|
358
|
-
else raise CliError,'unexpected value type for workspace'
|
118
|
+
else raise CliError, 'unexpected value type for workspace'
|
359
119
|
end
|
360
|
-
@
|
120
|
+
@cache_workspace_info =
|
361
121
|
begin
|
362
122
|
aoc_api.read("workspaces/#{ws_id}")[:data]
|
363
123
|
rescue Aspera::RestCallError => e
|
364
124
|
Log.log.debug(e.message)
|
365
125
|
{ 'id' => :undefined, 'name' => :undefined }
|
366
126
|
end
|
367
|
-
Log.dump(:
|
127
|
+
Log.dump(:current_workspace_info, @cache_workspace_info)
|
368
128
|
# display workspace
|
369
|
-
|
370
|
-
|
129
|
+
default_flag = @cache_workspace_info['id'] == default_workspace_id ? ' (default)' : ''
|
130
|
+
self.format.display_status("Current Workspace: #{@cache_workspace_info['name'].to_s.red}#{default_flag}")
|
131
|
+
return @cache_workspace_info
|
371
132
|
end
|
372
133
|
|
373
|
-
# @
|
374
|
-
def
|
375
|
-
|
134
|
+
# @return [Hash] with :node_id and :file_id
|
135
|
+
def home_info
|
136
|
+
return @cache_home_node_file unless @cache_home_node_file.nil?
|
137
|
+
if !aoc_api.url_token_data.nil?
|
376
138
|
assert_public_link_types(['view_shared_file'])
|
377
|
-
home_node_id =
|
378
|
-
home_file_id =
|
139
|
+
home_node_id = aoc_api.url_token_data['data']['node_id']
|
140
|
+
home_file_id = aoc_api.url_token_data['data']['file_id']
|
379
141
|
end
|
380
|
-
home_node_id ||=
|
381
|
-
home_file_id ||=
|
142
|
+
home_node_id ||= current_workspace_info['home_node_id'] || current_workspace_info['node_id']
|
143
|
+
home_file_id ||= current_workspace_info['home_file_id']
|
382
144
|
raise "Cannot get user's home node id, check your default workspace or specify one" if home_node_id.to_s.empty?
|
383
|
-
@
|
384
|
-
|
385
|
-
file_id:
|
145
|
+
@cache_home_node_file = {
|
146
|
+
node_id: home_node_id,
|
147
|
+
file_id: home_file_id
|
386
148
|
}
|
387
|
-
|
388
|
-
|
389
|
-
return nil
|
149
|
+
return @cache_home_node_file
|
390
150
|
end
|
391
151
|
|
392
152
|
# get identifier or name from command line
|
@@ -396,11 +156,11 @@ module Aspera
|
|
396
156
|
l_res_name = options.get_option(:name)
|
397
157
|
raise 'Provide either option id or name, not both' unless l_res_id.nil? || l_res_name.nil?
|
398
158
|
# try to find item by name (single partial match or exact match)
|
399
|
-
l_res_id = aoc_api.lookup_entity_by_name(resource_class_path,l_res_name)['id'] unless l_res_name.nil?
|
159
|
+
l_res_id = aoc_api.lookup_entity_by_name(resource_class_path, l_res_name)['id'] unless l_res_name.nil?
|
400
160
|
# if no name or id option, taken on command line (after command)
|
401
161
|
if l_res_id.nil?
|
402
162
|
l_res_id = options.get_next_argument('identifier')
|
403
|
-
l_res_id = aoc_api.lookup_entity_by_name(resource_class_path,options.get_next_argument('identifier'))['id'] if l_res_id.eql?(
|
163
|
+
l_res_id = aoc_api.lookup_entity_by_name(resource_class_path, options.get_next_argument('identifier'))['id'] if l_res_id.eql?(ENTITY_NAME_SPECIFIER)
|
404
164
|
end
|
405
165
|
return l_res_id
|
406
166
|
end
|
@@ -409,60 +169,14 @@ module Aspera
|
|
409
169
|
return "#{resource_class_path}/#{get_resource_id_from_args(resource_class_path)}"
|
410
170
|
end
|
411
171
|
|
412
|
-
# Normalize package creation recipient lists as expected by AoC API
|
413
|
-
# AoC expects {type: , id: }, but ascli allows providing either the native values or just a name
|
414
|
-
# in that case, the name is resolved and replaced with {type: , id: }
|
415
|
-
# @param package_data The whole package creation payload
|
416
|
-
# @param recipient_list_field The field in structure, i.e. recipients or bcc_recipients
|
417
|
-
# @return nil package_data is modified
|
418
|
-
def resolve_package_recipients(package_data,recipient_list_field)
|
419
|
-
return unless package_data.has_key?(recipient_list_field)
|
420
|
-
raise CliBadArgument,"#{recipient_list_field} must be an Array" unless package_data[recipient_list_field].is_a?(Array)
|
421
|
-
new_user_option = options.get_option(:new_user_option,is_type: :mandatory)
|
422
|
-
# list with resolved elements
|
423
|
-
resolved_list = []
|
424
|
-
package_data[recipient_list_field].each do |short_recipient_info|
|
425
|
-
case short_recipient_info
|
426
|
-
when Hash # native API information, check keys
|
427
|
-
raise "#{recipient_list_field} element shall have fields: id and type" unless short_recipient_info.keys.sort.eql?(%w[id type])
|
428
|
-
when String # CLI helper: need to resolve provided name to type/id
|
429
|
-
# email: user, else dropbox
|
430
|
-
entity_type = short_recipient_info.include?('@') ? 'contacts' : 'dropboxes'
|
431
|
-
begin
|
432
|
-
full_recipient_info = aoc_api.lookup_entity_by_name(entity_type,short_recipient_info,{'current_workspace_id' => @workspace_info['id']})
|
433
|
-
rescue RuntimeError => e
|
434
|
-
raise e unless e.message.start_with?(Aspera::AoC::ENTITY_NOT_FOUND)
|
435
|
-
# dropboxes cannot be created on the fly
|
436
|
-
raise "no such shared inbox in workspace #{@workspace_info['name']}" if entity_type.eql?('dropboxes')
|
437
|
-
# unknown user: create it as external user
|
438
|
-
full_recipient_info = aoc_api.create('contacts',{
|
439
|
-
'current_workspace_id' => @workspace_info['id'],
|
440
|
-
'email' => short_recipient_info}.merge(new_user_option))[:data]
|
441
|
-
end
|
442
|
-
short_recipient_info = if entity_type.eql?('dropboxes')
|
443
|
-
{'id' => full_recipient_info['id'],'type' => 'dropbox'}
|
444
|
-
else
|
445
|
-
{'id' => full_recipient_info['source_id'],'type' => full_recipient_info['source_type']}
|
446
|
-
end
|
447
|
-
else # unexpected extended value, must be String or Hash
|
448
|
-
raise "#{recipient_list_field} item must be a String (email, shared inbox) or Hash (id,type)"
|
449
|
-
end # type of recipient info
|
450
|
-
# add original or resolved recipient info
|
451
|
-
resolved_list.push(short_recipient_info)
|
452
|
-
end
|
453
|
-
# replace with resolved elements
|
454
|
-
package_data[recipient_list_field] = resolved_list
|
455
|
-
return nil
|
456
|
-
end
|
457
|
-
|
458
172
|
def normalize_metadata(pkg_data)
|
459
173
|
case pkg_data['metadata']
|
460
|
-
when Array,NilClass # no action
|
174
|
+
when Array, NilClass # no action
|
461
175
|
when Hash
|
462
176
|
api_meta = []
|
463
|
-
pkg_data['metadata'].each do |k,v|
|
177
|
+
pkg_data['metadata'].each do |k, v|
|
464
178
|
api_meta.push({
|
465
|
-
#'input_type' => 'single-dropdown',
|
179
|
+
# 'input_type' => 'single-dropdown',
|
466
180
|
'name' => k,
|
467
181
|
'values' => v.is_a?(Array) ? v : [v]
|
468
182
|
})
|
@@ -473,65 +187,18 @@ module Aspera
|
|
473
187
|
return nil
|
474
188
|
end
|
475
189
|
|
476
|
-
# Check metadata: remove when validation is done server side
|
477
|
-
def validate_metadata(pkg_data)
|
478
|
-
# validate only for shared inboxes
|
479
|
-
return unless
|
480
|
-
pkg_data['recipients'].is_a?(Array) &&
|
481
|
-
pkg_data['recipients'].first.is_a?(Hash) &&
|
482
|
-
pkg_data['recipients'].first.has_key?('type') &&
|
483
|
-
pkg_data['recipients'].first['type'].eql?('dropbox')
|
484
|
-
|
485
|
-
shbx_kid = pkg_data['recipients'].first['id']
|
486
|
-
meta_schema = aoc_api.read("dropboxes/#{shbx_kid}")[:data]['metadata_schema']
|
487
|
-
if meta_schema.nil? || meta_schema.empty?
|
488
|
-
Log.log.debug('no metadata in shared inbox')
|
489
|
-
return
|
490
|
-
end
|
491
|
-
pkg_meta = pkg_data['metadata']
|
492
|
-
raise "package requires metadata: #{meta_schema}" unless pkg_data.has_key?('metadata')
|
493
|
-
raise 'metadata must be an Array' unless pkg_meta.is_a?(Array)
|
494
|
-
Log.dump(:metadata,pkg_meta)
|
495
|
-
pkg_meta.each do |field|
|
496
|
-
raise 'metadata field must be Hash' unless field.is_a?(Hash)
|
497
|
-
raise 'metadata field must have name' unless field.has_key?('name')
|
498
|
-
raise 'metadata field must have values' unless field.has_key?('values')
|
499
|
-
raise 'metadata values must be an Array' unless field['values'].is_a?(Array)
|
500
|
-
raise "unknown metadata field: #{field['name']}" if meta_schema.select{|i|i['name'].eql?(field['name'])}.empty?
|
501
|
-
end
|
502
|
-
meta_schema.each do |field|
|
503
|
-
provided=pkg_meta.select{|i|i['name'].eql?(field['name'])}
|
504
|
-
raise "only one field with name #{field['name']} allowed" if provided.count > 1
|
505
|
-
raise "missing mandatory field: #{field['name']}" if field['required'] && provided.empty?
|
506
|
-
end
|
507
|
-
end
|
508
|
-
|
509
|
-
# private
|
510
|
-
def option_url_query(default)
|
511
|
-
query = options.get_option(:query)
|
512
|
-
query = default if query.nil?
|
513
|
-
Log.log.debug("Query=#{query}".bg_red)
|
514
|
-
begin
|
515
|
-
# check it is suitable
|
516
|
-
URI.encode_www_form(query) unless query.nil?
|
517
|
-
rescue StandardError => e
|
518
|
-
raise CliBadArgument,"query must be an extended value which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
|
519
|
-
end
|
520
|
-
return query
|
521
|
-
end
|
522
|
-
|
523
190
|
def assert_public_link_types(expected)
|
524
|
-
raise CliBadArgument,"public link type is #{
|
525
|
-
unless expected.include?(
|
191
|
+
raise CliBadArgument, "public link type is #{aoc_api.url_token_data['purpose']} but action requires one of #{expected.join(',')}" \
|
192
|
+
unless expected.include?(aoc_api.url_token_data['purpose'])
|
526
193
|
end
|
527
194
|
|
528
195
|
# Call aoc_api.read with same parameters.
|
529
196
|
# Use paging if necessary to get all results
|
530
197
|
# @return {list: , total: }
|
531
|
-
def read_with_paging(resource_class_path,base_query)
|
198
|
+
def read_with_paging(resource_class_path, base_query)
|
532
199
|
raise 'Query must be Hash' unless base_query.is_a?(Hash)
|
533
200
|
# set default large page if user does not specify own parameters. AoC Caps to 1000 anyway
|
534
|
-
base_query['per_page'] = 1000 unless base_query.
|
201
|
+
base_query['per_page'] = 1000 unless base_query.key?('per_page')
|
535
202
|
max_items = base_query[MAX_ITEMS]
|
536
203
|
base_query.delete(MAX_ITEMS)
|
537
204
|
max_pages = base_query[MAX_PAGES]
|
@@ -544,7 +211,7 @@ module Aspera
|
|
544
211
|
loop do
|
545
212
|
query = base_query.clone
|
546
213
|
query['page'] = current_page
|
547
|
-
result = aoc_api.read(resource_class_path,query)
|
214
|
+
result = aoc_api.read(resource_class_path, query)
|
548
215
|
total_count = result[:http]['X-Total-Count']
|
549
216
|
page_count += 1
|
550
217
|
current_page += 1
|
@@ -555,9 +222,67 @@ module Aspera
|
|
555
222
|
break if !max_pages.nil? && page_count > max_pages
|
556
223
|
break if !max_items.nil? && item_list.count > max_items
|
557
224
|
end
|
558
|
-
return {list: item_list,total: total_count}
|
225
|
+
return {list: item_list, total: total_count}
|
559
226
|
end
|
560
227
|
|
228
|
+
NODE4_EXT_COMMANDS = %i[transfer].concat(Node::COMMANDS_GEN4).freeze
|
229
|
+
private_constant :NODE4_EXT_COMMANDS
|
230
|
+
|
231
|
+
# @param file_id [String] root file id for the operation (can be AK root, or other, e.g. package, or link)
|
232
|
+
# @param scope [String] node scope, or nil (admin)
|
233
|
+
def execute_nodegen4_command(command_repo, node_id, file_id: nil, scope: nil)
|
234
|
+
top_node_api = aoc_api.node_id_to_api(
|
235
|
+
node_id: node_id,
|
236
|
+
plugin: self,
|
237
|
+
scope: scope
|
238
|
+
)
|
239
|
+
file_id = top_node_api.read("access_keys/#{top_node_api.app_info[:node_info]['access_key']}")[:data]['root_file_id'] if file_id.nil?
|
240
|
+
node_plugin = Node.new(@agents.merge(
|
241
|
+
skip_basic_auth_options: true,
|
242
|
+
skip_node_options: true,
|
243
|
+
node_api: top_node_api))
|
244
|
+
case command_repo
|
245
|
+
when *Node::COMMANDS_GEN4
|
246
|
+
return node_plugin.execute_command_gen4(command_repo, file_id)
|
247
|
+
when :transfer
|
248
|
+
# client side is agent
|
249
|
+
# server side is protocol server
|
250
|
+
# in same workspace
|
251
|
+
# default is push
|
252
|
+
case options.get_option(:operation, is_type: :mandatory)
|
253
|
+
when :push
|
254
|
+
client_tr_oper = Fasp::TransferSpec::DIRECTION_SEND
|
255
|
+
client_folder = options.get_option(:from_folder, is_type: :mandatory)
|
256
|
+
server_folder = transfer.destination_folder(client_tr_oper)
|
257
|
+
when :pull
|
258
|
+
client_tr_oper = Fasp::TransferSpec::DIRECTION_RECEIVE
|
259
|
+
client_folder = transfer.destination_folder(client_tr_oper)
|
260
|
+
server_folder = options.get_option(:from_folder, is_type: :mandatory)
|
261
|
+
end
|
262
|
+
client_apfid = top_node_api.resolve_api_fid(file_id, client_folder)
|
263
|
+
server_apfid = top_node_api.resolve_api_fid(file_id, server_folder)
|
264
|
+
# force node as transfer agent
|
265
|
+
@agents[:transfer].agent_instance = Fasp::AgentNode.new({
|
266
|
+
url: client_apfid[:api].params[:base_url],
|
267
|
+
username: client_apfid[:api].app_info[:node_info]['access_key'],
|
268
|
+
password: client_apfid[:api].oauth_token,
|
269
|
+
root_id: client_apfid[:file_id]
|
270
|
+
})
|
271
|
+
# additional node to node TS info
|
272
|
+
add_ts = {
|
273
|
+
'remote_access_key' => server_apfid[:api].app_info[:node_info]['access_key'],
|
274
|
+
'destination_root_id' => server_apfid[:file_id],
|
275
|
+
'source_root_id' => client_apfid[:file_id]
|
276
|
+
}
|
277
|
+
return Main.result_transfer(transfer.start(server_apfid[:api].transfer_spec_gen4(
|
278
|
+
server_apfid[:file_id],
|
279
|
+
client_tr_oper,
|
280
|
+
add_ts)))
|
281
|
+
else raise "INTERNAL ERROR: Missing case: #{command_repo}"
|
282
|
+
end # command_repo
|
283
|
+
# raise 'internal error:shall not reach here'
|
284
|
+
end # execute_nodegen4_command
|
285
|
+
|
561
286
|
def execute_admin_action
|
562
287
|
# upgrade scope to admin
|
563
288
|
aoc_api.oauth.gparams[:scope] = AoC::SCOPE_FILES_ADMIN
|
@@ -568,7 +293,7 @@ module Aspera
|
|
568
293
|
case command_auth_prov
|
569
294
|
when :list
|
570
295
|
providers = aoc_api.read('admin/auth_providers')[:data]
|
571
|
-
return {type: :object_list,data: providers}
|
296
|
+
return {type: :object_list, data: providers}
|
572
297
|
when :update
|
573
298
|
raise 'not implemented'
|
574
299
|
end
|
@@ -623,17 +348,17 @@ module Aspera
|
|
623
348
|
}
|
624
349
|
}
|
625
350
|
"
|
626
|
-
result = bss_api.create('graphql',{'variables' => {'organization_id' => org['id']},'query' => graphql_query})[:data]['data']
|
627
|
-
return {type: :single_object,data: result['aoc']['bssSubscription']}
|
351
|
+
result = bss_api.create('graphql', {'variables' => {'organization_id' => org['id']}, 'query' => graphql_query})[:data]['data']
|
352
|
+
return {type: :single_object, data: result['aoc']['bssSubscription']}
|
628
353
|
when :ats
|
629
354
|
ats_api = Rest.new(aoc_api.params.deep_merge({
|
630
355
|
base_url: aoc_api.params[:base_url] + '/admin/ats/pub/v1',
|
631
356
|
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
632
357
|
}))
|
633
|
-
return Ats.new(@agents).execute_action_gen(ats_api)
|
358
|
+
return Ats.new(@agents.merge(skip_node_options: true)).execute_action_gen(ats_api)
|
634
359
|
when :analytics
|
635
360
|
analytics_api = Rest.new(aoc_api.params.deep_merge({
|
636
|
-
base_url: aoc_api.params[:base_url].gsub('/api/v1','') + '/analytics/v2',
|
361
|
+
base_url: aoc_api.params[:base_url].gsub('/api/v1', '') + '/analytics/v2',
|
637
362
|
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
638
363
|
}))
|
639
364
|
command_analytics = options.get_next_command(%i[application_events transfers])
|
@@ -641,51 +366,53 @@ module Aspera
|
|
641
366
|
when :application_events
|
642
367
|
event_type = command_analytics.to_s
|
643
368
|
events = analytics_api.read("organizations/#{aoc_api.user_info['organization_id']}/#{event_type}")[:data][event_type]
|
644
|
-
return {type: :object_list,data: events}
|
369
|
+
return {type: :object_list, data: events}
|
645
370
|
when :transfers
|
646
371
|
event_type = command_analytics.to_s
|
647
372
|
filter_resource = options.get_option(:name) || 'organizations'
|
648
373
|
filter_id = options.get_option(:id) ||
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
374
|
+
case filter_resource
|
375
|
+
when 'organizations' then aoc_api.user_info['organization_id']
|
376
|
+
when 'users' then aoc_api.user_info['id']
|
377
|
+
when 'nodes' then aoc_api.user_info['id'] # TODO: consistent ? # rubocop:disable Lint/DuplicateBranch
|
378
|
+
else raise 'organizations or users for option --name'
|
379
|
+
end
|
655
380
|
filter = options.get_option(:query) || {}
|
656
381
|
raise 'query must be Hash' unless filter.is_a?(Hash)
|
657
382
|
filter['limit'] ||= 100
|
658
|
-
if options.get_option(:once_only,is_type: :mandatory)
|
383
|
+
if options.get_option(:once_only, is_type: :mandatory)
|
659
384
|
saved_date = []
|
660
385
|
startdate_persistency = PersistencyActionOnce.new(
|
661
386
|
manager: @agents[:persistency],
|
662
387
|
data: saved_date,
|
663
|
-
ids: IdGenerator.from_list(['aoc_ana_date',options.get_option(:url,is_type: :mandatory)
|
388
|
+
ids: IdGenerator.from_list(['aoc_ana_date', options.get_option(:url, is_type: :mandatory), current_workspace_info['name']].push(
|
389
|
+
filter_resource,
|
390
|
+
filter_id)))
|
664
391
|
start_datetime = saved_date.first
|
665
392
|
stop_datetime = Time.now.utc.strftime('%FT%T.%LZ')
|
666
|
-
#Log.log().error("start: #{start_datetime}")
|
667
|
-
#Log.log().error("end: #{stop_datetime}")
|
393
|
+
# Log.log().error("start: #{start_datetime}")
|
394
|
+
# Log.log().error("end: #{stop_datetime}")
|
668
395
|
saved_date[0] = stop_datetime
|
669
396
|
filter['start_time'] = start_datetime unless start_datetime.nil?
|
670
397
|
filter['stop_time'] = stop_datetime
|
671
398
|
end
|
672
|
-
events = analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",option_url_query(filter))[:data][event_type]
|
399
|
+
events = analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}", option_url_query(filter))[:data][event_type]
|
673
400
|
startdate_persistency&.save
|
674
401
|
if !options.get_option(:notif_to).nil?
|
675
402
|
events.each do |tr_event|
|
676
|
-
config.send_email_template({ev: tr_event})
|
403
|
+
config.send_email_template(values: {ev: tr_event})
|
677
404
|
end
|
678
405
|
end
|
679
|
-
return {type: :object_list,data: events}
|
406
|
+
return {type: :object_list, data: events}
|
680
407
|
end
|
681
408
|
when :resource
|
682
|
-
resource_type = options.get_next_argument('resource',expected: KNOWN_AOC_RES)
|
409
|
+
resource_type = options.get_next_argument('resource', expected: KNOWN_AOC_RES)
|
683
410
|
# get path on API, resource type is singular, but api is plural
|
684
411
|
resource_class_path =
|
685
412
|
case resource_type
|
686
413
|
# special cases: singleton, in admin, with x
|
687
|
-
when :self
|
688
|
-
when :client_registration_token
|
414
|
+
when :self, :organization then resource_type
|
415
|
+
when :client_registration_token, :client_access_key then "admin/#{resource_type}s"
|
689
416
|
when :application then 'admin/apps_new'
|
690
417
|
when :dropbox then resource_type.to_s + 'es'
|
691
418
|
when :kms_profile then "integrations/#{resource_type}s"
|
@@ -695,10 +422,9 @@ module Aspera
|
|
695
422
|
singleton_object = %i[self organization].include?(resource_type)
|
696
423
|
global_operations = %i[create list]
|
697
424
|
supported_operations = %i[show modify]
|
698
|
-
supported_operations.push(:delete
|
699
|
-
supported_operations.push(:
|
425
|
+
supported_operations.push(:delete, *global_operations) unless singleton_object
|
426
|
+
supported_operations.push(:do) if resource_type.eql?(:node)
|
700
427
|
supported_operations.push(:set_pub_key) if resource_type.eql?(:client)
|
701
|
-
supported_operations.push(:shared_folder) if resource_type.eql?(:workspace)
|
702
428
|
command = options.get_next_command(supported_operations)
|
703
429
|
# require identifier for non global commands
|
704
430
|
if !singleton_object && !global_operations.include?(command)
|
@@ -712,42 +438,43 @@ module Aspera
|
|
712
438
|
id_result = 'token' if resource_class_path.eql?('admin/client_registration_tokens')
|
713
439
|
# TODO: report inconsistency: creation url is !=, and does not return id.
|
714
440
|
resource_class_path = 'admin/client_registration/token' if resource_class_path.eql?('admin/client_registration_tokens')
|
715
|
-
list_or_one = options.get_next_argument('creation data
|
716
|
-
return do_bulk_operation(list_or_one,'created',id_result: id_result) do |params|
|
441
|
+
list_or_one = options.get_next_argument('creation data', type: Hash)
|
442
|
+
return do_bulk_operation(list_or_one, 'created', id_result: id_result) do |params|
|
717
443
|
raise 'expecting Hash' unless params.is_a?(Hash)
|
718
|
-
aoc_api.create(resource_class_path,params)[:data]
|
444
|
+
aoc_api.create(resource_class_path, params)[:data]
|
719
445
|
end
|
720
446
|
when :list
|
721
447
|
default_fields = ['id']
|
722
448
|
default_query = {}
|
723
449
|
case resource_type
|
724
|
-
when :application
|
725
|
-
|
726
|
-
|
727
|
-
when :
|
450
|
+
when :application
|
451
|
+
default_query = {organization_apps: true}
|
452
|
+
default_fields.push('app_type', 'app_name', 'available', 'direct_authorizations_allowed', 'workspace_authorizations_allowed')
|
453
|
+
when :client, :client_access_key, :dropbox, :group, :package, :saml_configuration, :workspace then default_fields.push('name')
|
454
|
+
when :client_registration_token then default_fields.push('value', 'data.client_subject_scopes', 'created_at')
|
728
455
|
when :contact then default_fields = %w[email name source_id source_type]
|
729
|
-
when :node then default_fields.push('name','host','access_key')
|
456
|
+
when :node then default_fields.push('name', 'host', 'access_key')
|
730
457
|
when :operation then default_fields = nil
|
731
|
-
when :short_link then default_fields.push('short_url','data.url_token_data.purpose')
|
732
|
-
when :user then default_fields.push('name','email')
|
458
|
+
when :short_link then default_fields.push('short_url', 'data.url_token_data.purpose')
|
459
|
+
when :user then default_fields.push('name', 'email')
|
733
460
|
when :group_membership then default_fields.push(*%w[group_id member_type member_id])
|
734
461
|
when :workspace_membership then default_fields.push(*%w[workspace_id member_type member_id])
|
735
462
|
end
|
736
|
-
items = read_with_paging(resource_class_path,option_url_query(default_query))
|
463
|
+
items = read_with_paging(resource_class_path, option_url_query(default_query))
|
737
464
|
count_msg = "Items: #{items[:list].length}/#{items[:total]}"
|
738
465
|
count_msg = count_msg.bg_red unless items[:list].length.eql?(items[:total].to_i)
|
739
466
|
self.format.display_status(count_msg)
|
740
|
-
return {type: :object_list,data: items[:list],fields: default_fields}
|
467
|
+
return {type: :object_list, data: items[:list], fields: default_fields}
|
741
468
|
when :show
|
742
469
|
object = aoc_api.read(resource_instance_path)[:data]
|
743
470
|
fields = object.keys.reject{|k|k.eql?('certificate')}
|
744
471
|
return { type: :single_object, data: object, fields: fields }
|
745
472
|
when :modify
|
746
473
|
changes = options.get_next_argument('modified parameters (hash)')
|
747
|
-
aoc_api.update(resource_instance_path,changes)
|
474
|
+
aoc_api.update(resource_instance_path, changes)
|
748
475
|
return Main.result_status('modified')
|
749
476
|
when :delete
|
750
|
-
return do_bulk_operation(res_id,'deleted') do |one_id|
|
477
|
+
return do_bulk_operation(res_id, 'deleted') do |one_id|
|
751
478
|
aoc_api.delete("#{resource_class_path}/#{one_id}")
|
752
479
|
{'id' => one_id}
|
753
480
|
end
|
@@ -755,109 +482,15 @@ module Aspera
|
|
755
482
|
# special : reads private and generate public
|
756
483
|
the_private_key = options.get_next_argument('private_key')
|
757
484
|
the_public_key = OpenSSL::PKey::RSA.new(the_private_key).public_key.to_s
|
758
|
-
aoc_api.update(resource_instance_path,{jwt_grant_enabled: true, public_key: the_public_key})
|
485
|
+
aoc_api.update(resource_instance_path, {jwt_grant_enabled: true, public_key: the_public_key})
|
759
486
|
return Main.result_success
|
760
|
-
when :
|
761
|
-
|
762
|
-
|
763
|
-
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action if command.eql?(:v3)
|
764
|
-
ak_root_file_id = api_node.read("access_keys/#{res_data['access_key']}")[:data]['root_file_id']
|
765
|
-
command_repo = options.get_next_command(NODE4_COMMANDS)
|
766
|
-
return execute_node_gen4_command(command_repo,{node_info: res_data, file_id: ak_root_file_id})
|
767
|
-
when :shared_folder
|
768
|
-
Log.log.warn('ATTENTION: alpha, under development, do not use')
|
769
|
-
# inside a workspace
|
770
|
-
command_shared = options.get_next_command(%i[list create delete]) # member
|
771
|
-
core_api=Rest.new(aoc_api.params.merge(base_url: aoc_api.params[:base_url].gsub('/api.','/sedemo.')))
|
772
|
-
# generic permission created for each shared folder
|
773
|
-
access_id = "#{ID_AK_ADMIN}_WS_#{res_id}"
|
774
|
-
case command_shared
|
775
|
-
when :list
|
776
|
-
query=options.get_option(:query)
|
777
|
-
query={'admin' => true, 'access_id' => access_id, 'access_type' => 'user'} if query.nil?
|
778
|
-
res_data = aoc_api.read("#{resource_instance_path}/permissions",query)[:data]
|
779
|
-
return { type: :object_list, data: res_data, fields: %w[id node_id file_id node_name file.path tags.aspera.files.workspace.share_as access_id]}
|
780
|
-
when :member
|
781
|
-
#https://sedemo.ibmaspera.com/api/v1/node/8669/permissions_and_members/3270?inherited=false&aspera-node-basic=8669&admin=true&page=1&per_page=25
|
782
|
-
when :delete
|
783
|
-
shared_id=instance_identifier
|
784
|
-
all_shared=aoc_api.read("#{resource_instance_path}/permissions",query)[:data].select{|i|i['id'].eql?(shared_id)}
|
785
|
-
raise 'no such shared folder id' if all_shared.empty?
|
786
|
-
raise 'error' unless all_shared.length.eql?(1)
|
787
|
-
shared_info=all_shared.first
|
788
|
-
#return { type: :single_object, data: shared_info}
|
789
|
-
node_id=shared_info['node_id']
|
790
|
-
Log.log.warn('ATTENTION: under dev: user vars: V1 and V2')
|
791
|
-
core_api.call(
|
792
|
-
operation: 'DELETE',
|
793
|
-
subpath: "node/#{node_id}/permissions",
|
794
|
-
headers: {
|
795
|
-
'Accept' => 'application/json',
|
796
|
-
'aspera-node-auth' => ENV['V1'],
|
797
|
-
'aspera-node-tokens' => ENV['V2']
|
798
|
-
},
|
799
|
-
url_params: {
|
800
|
-
'ids' => shared_id,
|
801
|
-
'aspera-node-basic' => node_id,
|
802
|
-
'aspera-node-prefer-basic' => node_id
|
803
|
-
}
|
804
|
-
)
|
805
|
-
return Main.result_success
|
806
|
-
when :create
|
807
|
-
# workspace information
|
808
|
-
ws_info = aoc_api.read(resource_instance_path)[:data]
|
809
|
-
shared_create_data = options.get_next_argument('creation data',type: Hash)
|
810
|
-
# node is either provided by user, or by default the one of workspace
|
811
|
-
node_id = shared_create_data.has_key?('node_id') ? shared_create_data['node_id'] : ws_info['node_id']
|
812
|
-
# remove from creation data if present, as it is not a standard argument
|
813
|
-
shared_create_data.delete('node_id')
|
814
|
-
# get optional link_name
|
815
|
-
#opt_link_name=shared_create_data['link_name']
|
816
|
-
shared_create_data.delete('link_name')
|
817
|
-
raise 'missing node information: path' unless shared_create_data.has_key?('path')
|
818
|
-
folder_path=shared_create_data['path']
|
819
|
-
shared_create_data.delete('path')
|
820
|
-
node_file={node_info: aoc_api.read("nodes/#{node_id}")[:data], file_id: 1}
|
821
|
-
node_file = aoc_api.resolve_node_file(node_file,folder_path)
|
822
|
-
node_api = aoc_api.get_node_api(node_file[:node_info])
|
823
|
-
access_id = "#{ID_AK_ADMIN}_WS_#{ws_info['id']}"
|
824
|
-
# use can specify: tags.aspera.files.workspace.share_as to File.basename(folder_path)
|
825
|
-
default_create_data = {
|
826
|
-
'file_id' => node_file[:file_id],
|
827
|
-
'access_type' => 'user',
|
828
|
-
'access_id' => access_id,
|
829
|
-
'access_levels' => %w[list read write delete mkdir rename preview],
|
830
|
-
'tags' => {'aspera' => {'files' => {'workspace' => {
|
831
|
-
'id' => ws_info['id'],
|
832
|
-
'workspace_name' => ws_info['name'],
|
833
|
-
'user_name' => aoc_api.user_info['name'],
|
834
|
-
'shared_by_user_id' => aoc_api.user_info['id'],
|
835
|
-
'shared_by_name' => aoc_api.user_info['name'],
|
836
|
-
'shared_by_email' => aoc_api.user_info['email'],
|
837
|
-
'shared_with_name' => access_id,
|
838
|
-
'access_key' => node_file[:node_info]['access_key'],
|
839
|
-
'node' => node_file[:node_info]['name']}
|
840
|
-
}}}}
|
841
|
-
shared_create_data = default_create_data.deep_merge(default_create_data) # ?aspera-node-basic=#{node_id}&aspera-node-prefer-basic=#{node_id}
|
842
|
-
created_data = node_api.create('permissions',shared_create_data)[:data]
|
843
|
-
# new API:
|
844
|
-
#created_data=aoc_api.create("node/#{node_id}/permissions",shared_create_data)[:data]
|
845
|
-
# TODO: send event
|
846
|
-
event_creation={
|
847
|
-
'types' => ['permission.created'],
|
848
|
-
'node_id' => node_file[:node_info]['id'],
|
849
|
-
'workspace_id' => ws_info['id'],
|
850
|
-
'data' => created_data # Response from previous step
|
851
|
-
}
|
852
|
-
#(optional). The name of the folder to be displayed to the destination user. Use it if its value is different from the "share_as" field.
|
853
|
-
#event_creation['link_name']=opt_link_name unless opt_link_name.nil?
|
854
|
-
aoc_api.create('events',event_creation)
|
855
|
-
return { type: :single_object, data: created_data}
|
856
|
-
end
|
487
|
+
when :do
|
488
|
+
command_repo = options.get_next_command(NODE4_EXT_COMMANDS)
|
489
|
+
return execute_nodegen4_command(command_repo, res_id)
|
857
490
|
else raise 'unknown command'
|
858
491
|
end
|
859
492
|
when :usage_reports
|
860
|
-
return {type: :object_list,data: aoc_api.read('usage_reports',{workspace_id:
|
493
|
+
return {type: :object_list, data: aoc_api.read('usage_reports', {workspace_id: current_workspace_info['id']})[:data]}
|
861
494
|
end
|
862
495
|
end
|
863
496
|
|
@@ -869,13 +502,13 @@ module Aspera
|
|
869
502
|
case command
|
870
503
|
when :reminder
|
871
504
|
# send an email reminder with list of orgs
|
872
|
-
user_email = options.get_option(:username,is_type: :mandatory)
|
873
|
-
Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").create('organization_reminders',{email: user_email})[:data]
|
505
|
+
user_email = options.get_option(:username, is_type: :mandatory)
|
506
|
+
Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").create('organization_reminders', {email: user_email})[:data]
|
874
507
|
return Main.result_status("List of organizations user is member of, has been sent by e-mail to #{user_email}")
|
875
508
|
when :servers
|
876
|
-
return {type: :object_list,data: Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
|
509
|
+
return {type: :object_list, data: Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
|
877
510
|
when :bearer_token
|
878
|
-
return {type: :text,data: aoc_api.oauth_token}
|
511
|
+
return {type: :text, data: aoc_api.oauth_token}
|
879
512
|
when :organization
|
880
513
|
return { type: :single_object, data: aoc_api.read('organization')[:data] }
|
881
514
|
when :tier_restrictions
|
@@ -887,99 +520,101 @@ module Aspera
|
|
887
520
|
when :workspaces
|
888
521
|
case options.get_next_command(%i[list current])
|
889
522
|
when :list
|
890
|
-
return {type: :object_list,data: aoc_api.read('workspaces')[:data],fields: %w[id name]}
|
523
|
+
return {type: :object_list, data: aoc_api.read('workspaces')[:data], fields: %w[id name]}
|
891
524
|
when :current
|
892
|
-
|
893
|
-
return { type: :single_object, data: @workspace_info }
|
525
|
+
return { type: :single_object, data: current_workspace_info }
|
894
526
|
end
|
895
527
|
when :profile
|
896
528
|
case options.get_next_command(%i[show modify])
|
897
529
|
when :show
|
898
|
-
return { type: :single_object, data: aoc_api.user_info }
|
530
|
+
return { type: :single_object, data: aoc_api.user_info(exception: true) }
|
899
531
|
when :modify
|
900
|
-
aoc_api.update("users/#{aoc_api.user_info['id']}",options.get_next_argument('modified parameters (hash)'))
|
532
|
+
aoc_api.update("users/#{aoc_api.user_info(exception: true)['id']}", options.get_next_argument('modified parameters (hash)'))
|
901
533
|
return Main.result_status('modified')
|
902
534
|
end
|
903
535
|
end
|
904
536
|
when :packages
|
905
|
-
|
906
|
-
package_command = options.get_next_command([%i[shared_inboxes send recv list show delete],NODE4_CMD_PATH].flatten)
|
537
|
+
package_command = options.get_next_command(%i[shared_inboxes send recv list show delete].concat(Node::NODE4_READ_ACTIONS))
|
907
538
|
case package_command
|
908
539
|
when :shared_inboxes
|
909
540
|
case options.get_next_command(%i[list show])
|
910
541
|
when :list
|
911
542
|
query = option_url_query(nil)
|
912
543
|
if query.nil?
|
913
|
-
query = {'embed[]' => 'dropbox','aggregate_permissions_by_dropbox' => true,'sort' => 'dropbox_name'}
|
914
|
-
query['workspace_id']
|
544
|
+
query = {'embed[]' => 'dropbox', 'aggregate_permissions_by_dropbox' => true, 'sort' => 'dropbox_name'}
|
545
|
+
query['workspace_id'] = current_workspace_info['id'] unless current_workspace_info['id'].eql?(:undefined)
|
915
546
|
end
|
916
|
-
return {type: :object_list,data: aoc_api.read('dropbox_memberships',query)[:data],fields: ['dropbox_id','dropbox.name']}
|
547
|
+
return {type: :object_list, data: aoc_api.read('dropbox_memberships', query)[:data], fields: ['dropbox_id', 'dropbox.name']}
|
917
548
|
when :show
|
918
|
-
return {type: :single_object,data: aoc_api.read(get_resource_path_from_args('dropboxes'),query)[:data]}
|
549
|
+
return {type: :single_object, data: aoc_api.read(get_resource_path_from_args('dropboxes'), query)[:data]}
|
919
550
|
end
|
920
551
|
when :send
|
921
|
-
package_data = options.get_option(:value,is_type: :mandatory)
|
922
|
-
raise CliBadArgument,'value must be hash, refer to doc' unless package_data.is_a?(Hash)
|
552
|
+
package_data = options.get_option(:value, is_type: :mandatory)
|
553
|
+
raise CliBadArgument, 'value must be hash, refer to doc' unless package_data.is_a?(Hash)
|
923
554
|
|
924
|
-
if
|
555
|
+
if !aoc_api.url_token_data.nil?
|
925
556
|
assert_public_link_types(%w[send_package_to_user send_package_to_dropbox])
|
926
|
-
box_type =
|
927
|
-
package_data['recipients'] = [{'id' =>
|
557
|
+
box_type = aoc_api.url_token_data['purpose'].split('_').last
|
558
|
+
package_data['recipients'] = [{'id' => aoc_api.url_token_data['data']["#{box_type}_id"], 'type' => box_type}]
|
928
559
|
# TODO: probably this line is not needed
|
929
|
-
|
560
|
+
current_workspace_info['id'] = aoc_api.url_token_data['data']['workspace_id']
|
930
561
|
end
|
931
562
|
|
932
|
-
package_data['workspace_id'] =
|
563
|
+
package_data['workspace_id'] = current_workspace_info['id']
|
933
564
|
|
934
565
|
# list of files to include in package, optional
|
935
|
-
#package_data['file_names']=self.transfer.ts_source_paths.map{|i|File.basename(i['source'])}
|
566
|
+
# package_data['file_names']=self.transfer.ts_source_paths.map{|i|File.basename(i['source'])}
|
936
567
|
|
937
568
|
# lookup users
|
938
|
-
|
939
|
-
resolve_package_recipients(package_data,'
|
569
|
+
new_user_option = options.get_option(:new_user_option)
|
570
|
+
aoc_api.resolve_package_recipients(package_data, current_workspace_info['id'], 'recipients', new_user_option)
|
571
|
+
aoc_api.resolve_package_recipients(package_data, current_workspace_info['id'], 'bcc_recipients', new_user_option)
|
940
572
|
normalize_metadata(package_data)
|
941
|
-
validate_metadata(package_data) if options.get_option(:validate_metadata)
|
573
|
+
aoc_api.validate_metadata(package_data) if options.get_option(:validate_metadata)
|
942
574
|
|
943
575
|
# create a new package container
|
944
|
-
package_info = aoc_api.create('packages',package_data)[:data]
|
945
|
-
|
946
|
-
# get node information for the node on which package must be created
|
947
|
-
node_info = aoc_api.read("nodes/#{package_info['node_id']}")[:data]
|
576
|
+
package_info = aoc_api.create('packages', package_data)[:data]
|
948
577
|
|
949
578
|
# tell AoC what to expect in package: 1 transfer (can also be done after transfer)
|
950
579
|
# TODO: if multisession was used we should probably tell
|
951
580
|
# also, currently no "multi-source" , i.e. only from client-side files, unless "node" agent is used
|
952
|
-
aoc_api.update("packages/#{package_info['id']}",{'sent' => true,'transfers_expected' => 1})[:data]
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
581
|
+
aoc_api.update("packages/#{package_info['id']}", {'sent' => true, 'transfers_expected' => 1})[:data]
|
582
|
+
package_node_api = aoc_api.node_id_to_api(
|
583
|
+
node_id: package_info['node_id'],
|
584
|
+
plugin: self,
|
585
|
+
package_info: package_info,
|
586
|
+
scope: AoC::SCOPE_NODE_USER
|
587
|
+
)
|
588
|
+
# raise error if necessary (but not return, package info is returned on success)
|
589
|
+
Main.result_transfer(transfer.start(package_node_api.transfer_spec_gen4(
|
590
|
+
package_info['contents_file_id'],
|
591
|
+
Fasp::TransferSpec::DIRECTION_SEND)))
|
958
592
|
# return all info on package
|
959
593
|
return { type: :single_object, data: package_info}
|
960
594
|
when :recv
|
961
|
-
if
|
595
|
+
if !aoc_api.url_token_data.nil?
|
962
596
|
assert_public_link_types(['view_received_package'])
|
963
|
-
options.set_option(:id
|
597
|
+
options.set_option(:id, aoc_api.url_token_data['data']['package_id'])
|
964
598
|
end
|
965
599
|
# scalar here
|
966
600
|
ids_to_download = instance_identifier
|
967
601
|
skip_ids_data = []
|
968
602
|
skip_ids_persistency = nil
|
969
|
-
if options.get_option(:once_only,is_type: :mandatory)
|
603
|
+
if options.get_option(:once_only, is_type: :mandatory)
|
970
604
|
skip_ids_persistency = PersistencyActionOnce.new(
|
971
605
|
manager: @agents[:persistency],
|
972
606
|
data: skip_ids_data,
|
973
|
-
id: IdGenerator.from_list(['aoc_recv',options.get_option(:url,is_type: :mandatory)
|
607
|
+
id: IdGenerator.from_list(['aoc_recv', options.get_option(:url, is_type: :mandatory),
|
608
|
+
current_workspace_info['id']].concat(aoc_api.additional_persistence_ids)))
|
974
609
|
end
|
975
|
-
if
|
610
|
+
if VAL_ALL.eql?(ids_to_download)
|
976
611
|
# get list of packages in inbox
|
977
|
-
package_info = aoc_api.read('packages',{
|
612
|
+
package_info = aoc_api.read('packages', {
|
978
613
|
'archived' => false,
|
979
614
|
'exclude_dropbox_packages' => true,
|
980
615
|
'has_content' => true,
|
981
616
|
'received' => true,
|
982
|
-
'workspace_id' =>
|
617
|
+
'workspace_id' => current_workspace_info['id']})[:data]
|
983
618
|
# remove from list the ones already downloaded
|
984
619
|
ids_to_download = package_info.map{|e|e['id']}
|
985
620
|
# array here
|
@@ -991,12 +626,18 @@ module Aspera
|
|
991
626
|
self.format.display_status("found #{ids_to_download.length} package(s).")
|
992
627
|
ids_to_download.each do |package_id|
|
993
628
|
package_info = aoc_api.read("packages/#{package_id}")[:data]
|
994
|
-
node_info = aoc_api.read("nodes/#{package_info['node_id']}")[:data]
|
995
629
|
self.format.display_status("downloading package: #{package_info['name']}")
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
630
|
+
package_node_api = aoc_api.node_id_to_api(
|
631
|
+
node_id: package_info['node_id'],
|
632
|
+
plugin: self,
|
633
|
+
package_info: package_info,
|
634
|
+
scope: AoC::SCOPE_NODE_USER
|
635
|
+
)
|
636
|
+
statuses = transfer.start(package_node_api.transfer_spec_gen4(
|
637
|
+
package_info['contents_file_id'],
|
638
|
+
Fasp::TransferSpec::DIRECTION_RECEIVE,
|
639
|
+
{'paths'=> [{'source' => '.'}]}))
|
640
|
+
result_transfer.push({'package' => package_id, Main::STATUS_FIELD => statuses})
|
1000
641
|
# update skip list only if all transfer sessions completed
|
1001
642
|
if TransferAgent.session_status(statuses).eql?(:success)
|
1002
643
|
skip_ids_data.push(package_id)
|
@@ -1009,62 +650,61 @@ module Aspera
|
|
1009
650
|
package_info = aoc_api.read("packages/#{package_id}")[:data]
|
1010
651
|
return { type: :single_object, data: package_info }
|
1011
652
|
when :list
|
1012
|
-
display_fields
|
1013
|
-
query = option_url_query({'archived' => false,'exclude_dropbox_packages' => true,'has_content' => true,'received' => true})
|
1014
|
-
if query.
|
653
|
+
display_fields = %w[id name bytes_transferred]
|
654
|
+
query = option_url_query({'archived' => false, 'exclude_dropbox_packages' => true, 'has_content' => true, 'received' => true})
|
655
|
+
if query.key?('dropbox_name')
|
1015
656
|
# convenience: specify name instead of id
|
1016
|
-
raise 'not both dropbox_name and dropbox_id' if query.
|
1017
|
-
query['dropbox_id'] = aoc_api.lookup_entity_by_name('dropboxes',query['dropbox_name'])['id']
|
657
|
+
raise 'not both dropbox_name and dropbox_id' if query.key?('dropbox_id')
|
658
|
+
query['dropbox_id'] = aoc_api.lookup_entity_by_name('dropboxes', query['dropbox_name'])['id']
|
1018
659
|
query.delete('dropbox_name')
|
1019
660
|
end
|
1020
661
|
raise 'option must be Hash' unless query.is_a?(Hash)
|
1021
|
-
if
|
662
|
+
if current_workspace_info['id'].eql?(:undefined)
|
1022
663
|
display_fields.push('workspace_id')
|
1023
664
|
else
|
1024
|
-
query['workspace_id'] ||=
|
665
|
+
query['workspace_id'] ||= current_workspace_info['id']
|
1025
666
|
end
|
1026
|
-
packages = aoc_api.read('packages',query)[:data]
|
1027
|
-
return {type: :object_list,data: packages,fields: display_fields}
|
667
|
+
packages = aoc_api.read('packages', query)[:data]
|
668
|
+
return {type: :object_list, data: packages, fields: display_fields}
|
1028
669
|
when :delete
|
1029
670
|
list_or_one = instance_identifier
|
1030
|
-
return do_bulk_operation(list_or_one,'deleted') do |id|
|
671
|
+
return do_bulk_operation(list_or_one, 'deleted') do |id|
|
1031
672
|
raise 'expecting String identifier' unless id.is_a?(String) || id.is_a?(Integer)
|
1032
673
|
aoc_api.delete("packages/#{id}")[:data]
|
1033
674
|
end
|
1034
|
-
when *
|
675
|
+
when *Node::NODE4_READ_ACTIONS
|
1035
676
|
package_id = options.get_next_argument('package ID')
|
1036
|
-
#path = options.get_next_argument('path', mandatory: false) || '/'
|
1037
677
|
package_info = aoc_api.read("packages/#{package_id}")[:data]
|
1038
|
-
|
1039
|
-
node_info: aoc_api.read("nodes/#{package_info['node_id']}")[:data],
|
1040
|
-
file_id: package_info['file_id']
|
1041
|
-
}
|
1042
|
-
return execute_node_gen4_command(package_command,package_node_file)
|
678
|
+
return execute_nodegen4_command(package_command, package_info['node_id'], file_id: package_info['file_id'], scope: AoC::SCOPE_NODE_USER)
|
1043
679
|
end
|
1044
680
|
when :files
|
1045
|
-
|
1046
|
-
set_workspace_info
|
1047
|
-
set_home_node_file
|
1048
|
-
command_repo = options.get_next_command([NODE4_COMMANDS,:short_link].flatten)
|
681
|
+
command_repo = options.get_next_command([:short_link].concat(NODE4_EXT_COMMANDS))
|
1049
682
|
case command_repo
|
1050
|
-
when *
|
683
|
+
when *NODE4_EXT_COMMANDS
|
684
|
+
return execute_nodegen4_command(command_repo, home_info[:node_id], file_id: home_info[:file_id], scope: AoC::SCOPE_NODE_USER)
|
1051
685
|
when :short_link
|
686
|
+
# TODO: move to permissions ?
|
1052
687
|
folder_dest = options.get_option(:to_folder)
|
1053
688
|
value_option = options.get_option(:value)
|
1054
689
|
case value_option
|
1055
690
|
when 'public' then value_option = {'purpose' => 'token_auth_redirection'}
|
1056
691
|
when 'private' then value_option = {'purpose' => 'shared_folder_auth_link'}
|
1057
|
-
when NilClass,Hash then nil # keep value
|
692
|
+
when NilClass, Hash then nil # keep value
|
1058
693
|
else raise 'value must be either: public, private, Hash or nil'
|
1059
694
|
end
|
1060
695
|
create_params = nil
|
1061
|
-
|
696
|
+
shared_apfid = nil
|
1062
697
|
if !folder_dest.nil?
|
1063
|
-
|
698
|
+
home_node_api = aoc_api.node_id_to_api(
|
699
|
+
node_id: home_info[:node_id],
|
700
|
+
plugin: self,
|
701
|
+
scope: AoC::SCOPE_NODE_USER
|
702
|
+
)
|
703
|
+
shared_apfid = home_node_api.resolve_api_fid(home_info[:file_id], folder_dest)
|
1064
704
|
create_params = {
|
1065
|
-
file_id:
|
1066
|
-
node_id:
|
1067
|
-
workspace_id:
|
705
|
+
file_id: shared_apfid[:file_id],
|
706
|
+
node_id: shared_apfid[:api].app_info[:node_info]['id'],
|
707
|
+
workspace_id: current_workspace_info['id']
|
1068
708
|
}
|
1069
709
|
end
|
1070
710
|
if !value_option.nil? && !create_params.nil?
|
@@ -1085,30 +725,29 @@ module Aspera
|
|
1085
725
|
else
|
1086
726
|
raise 'purpose must be one of: token_auth_redirection or shared_folder_auth_link'
|
1087
727
|
end
|
1088
|
-
options.set_option(:value,value_option)
|
728
|
+
options.set_option(:value, value_option)
|
1089
729
|
end
|
1090
|
-
result = entity_action(
|
1091
|
-
if result[:data].is_a?(Hash) && result[:data].
|
1092
|
-
node_api = aoc_api.get_node_api(node_file[:node_info])
|
730
|
+
result = entity_action(aoc_api, 'short_links', id_default: 'self')
|
731
|
+
if result[:data].is_a?(Hash) && result[:data].key?('created_at') && result[:data]['resource_type'].eql?('UrlToken')
|
1093
732
|
# TODO: access level as arg
|
1094
|
-
access_levels = Aspera::Node::ACCESS_LEVELS #['delete','list','mkdir','preview','read','rename','write']
|
733
|
+
access_levels = Aspera::Node::ACCESS_LEVELS # ['delete','list','mkdir','preview','read','rename','write']
|
1095
734
|
perm_data = {
|
1096
|
-
'file_id' =>
|
735
|
+
'file_id' => shared_apfid[:file_id],
|
1097
736
|
'access_type' => 'user',
|
1098
737
|
'access_id' => result[:data]['resource_id'],
|
1099
738
|
'access_levels' => access_levels,
|
1100
739
|
'tags' => {
|
1101
740
|
'url_token' => true,
|
1102
|
-
'workspace_id' =>
|
1103
|
-
'workspace_name' =>
|
741
|
+
'workspace_id' => current_workspace_info['id'],
|
742
|
+
'workspace_name' => current_workspace_info['name'],
|
1104
743
|
'folder_name' => 'my folder',
|
1105
744
|
'created_by_name' => aoc_api.user_info['name'],
|
1106
745
|
'created_by_email' => aoc_api.user_info['email'],
|
1107
|
-
'access_key' =>
|
1108
|
-
'node' =>
|
746
|
+
'access_key' => shared_apfid[:api].app_info[:node_info]['access_key'],
|
747
|
+
'node' => shared_apfid[:api].app_info[:node_info]['host']
|
1109
748
|
}
|
1110
749
|
}
|
1111
|
-
|
750
|
+
shared_apfid[:api].create("permissions?file_id=#{shared_apfid[:file_id]}", perm_data)
|
1112
751
|
# TODO: event ?
|
1113
752
|
end
|
1114
753
|
return result
|
@@ -1118,49 +757,49 @@ module Aspera
|
|
1118
757
|
Log.log.warn('BETA: work under progress')
|
1119
758
|
# automation api is not in the same place
|
1120
759
|
automation_rest_params = aoc_api.params.clone
|
1121
|
-
automation_rest_params[:base_url].gsub!('/api/','/automation/')
|
760
|
+
automation_rest_params[:base_url].gsub!('/api/', '/automation/')
|
1122
761
|
automation_api = Rest.new(automation_rest_params)
|
1123
762
|
command_automation = options.get_next_command(%i[workflows instances])
|
1124
763
|
case command_automation
|
1125
764
|
when :instances
|
1126
|
-
return entity_action(
|
765
|
+
return entity_action(aoc_api, 'workflow_instances')
|
1127
766
|
when :workflows
|
1128
|
-
wf_command = options.get_next_command([
|
767
|
+
wf_command = options.get_next_command(%i[action launch].concat(Plugin::ALL_OPS))
|
1129
768
|
case wf_command
|
1130
769
|
when *Plugin::ALL_OPS
|
1131
|
-
return entity_command(wf_command,automation_api,'workflows',id_default: :id)
|
770
|
+
return entity_command(wf_command, automation_api, 'workflows', id_default: :id)
|
1132
771
|
when :launch
|
1133
772
|
wf_id = instance_identifier
|
1134
|
-
data = automation_api.create("workflows/#{wf_id}/launch",{})[:data]
|
1135
|
-
return {type: :single_object,data: data}
|
773
|
+
data = automation_api.create("workflows/#{wf_id}/launch", {})[:data]
|
774
|
+
return {type: :single_object, data: data}
|
1136
775
|
when :action
|
1137
|
-
#TODO: not complete
|
776
|
+
# TODO: not complete
|
1138
777
|
wf_id = instance_identifier
|
1139
778
|
wf_action_cmd = options.get_next_command(%i[list create show])
|
1140
|
-
Log.log.warn
|
1141
|
-
step = automation_api.create('steps',{'workflow_id' => wf_id})[:data]
|
1142
|
-
automation_api.update("workflows/#{wf_id}",{'step_order' => [step['id']]})
|
1143
|
-
action = automation_api.create('actions',{'step_id' => step['id'],'type' => 'manual'})[:data]
|
1144
|
-
automation_api.update("steps/#{step['id']}",{'action_order' => [action['id']]})
|
779
|
+
Log.log.warn{"Not implemented: #{wf_action_cmd}"}
|
780
|
+
step = automation_api.create('steps', {'workflow_id' => wf_id})[:data]
|
781
|
+
automation_api.update("workflows/#{wf_id}", {'step_order' => [step['id']]})
|
782
|
+
action = automation_api.create('actions', {'step_id' => step['id'], 'type' => 'manual'})[:data]
|
783
|
+
automation_api.update("steps/#{step['id']}", {'action_order' => [action['id']]})
|
1145
784
|
wf = automation_api.read("workflows/#{wf_id}")[:data]
|
1146
|
-
return {type: :single_object,data: wf}
|
785
|
+
return {type: :single_object, data: wf}
|
1147
786
|
end
|
1148
787
|
end
|
1149
788
|
when :admin
|
1150
789
|
return execute_admin_action
|
1151
790
|
when :gateway
|
1152
|
-
set_workspace_info
|
1153
791
|
require 'aspera/faspex_gw'
|
1154
|
-
FaspexGW.new(
|
792
|
+
return FaspexGW.new(aoc_api, current_workspace_info['id']).start_server
|
1155
793
|
else
|
1156
794
|
raise "internal error: #{command}"
|
1157
795
|
end # action
|
1158
796
|
raise 'internal error: command shall return'
|
1159
797
|
end
|
1160
798
|
|
1161
|
-
private :aoc_params
|
799
|
+
private :aoc_params,
|
800
|
+
:home_info,
|
801
|
+
:assert_public_link_types,
|
1162
802
|
:execute_admin_action
|
1163
|
-
private_constant :VAL_ALL,:NODE4_COMMANDS, :ID_AK_ADMIN
|
1164
803
|
end # AoC
|
1165
804
|
end # Plugins
|
1166
805
|
end # Cli
|