aspera-cli 4.6.0 → 4.7.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
- data/README.md +427 -300
- data/bin/ascli +2 -1
- data/bin/asession +1 -0
- data/docs/test_env.conf +2 -0
- data/examples/aoc.rb +4 -3
- data/examples/faspex4.rb +21 -19
- data/examples/proxy.pac +1 -1
- data/examples/transfer.rb +15 -15
- data/lib/aspera/aoc.rb +135 -124
- data/lib/aspera/ascmd.rb +85 -75
- data/lib/aspera/ats_api.rb +11 -10
- data/lib/aspera/cli/basic_auth_plugin.rb +13 -14
- data/lib/aspera/cli/extended_value.rb +42 -33
- data/lib/aspera/cli/formater.rb +138 -111
- data/lib/aspera/cli/info.rb +17 -0
- data/lib/aspera/cli/listener/line_dump.rb +3 -2
- data/lib/aspera/cli/listener/logger.rb +2 -1
- data/lib/aspera/cli/listener/progress.rb +16 -18
- data/lib/aspera/cli/listener/progress_multi.rb +13 -16
- data/lib/aspera/cli/main.rb +122 -130
- data/lib/aspera/cli/manager.rb +146 -154
- data/lib/aspera/cli/plugin.rb +38 -34
- data/lib/aspera/cli/plugins/alee.rb +6 -6
- data/lib/aspera/cli/plugins/aoc.rb +273 -276
- data/lib/aspera/cli/plugins/ats.rb +82 -76
- data/lib/aspera/cli/plugins/bss.rb +14 -16
- data/lib/aspera/cli/plugins/config.rb +350 -306
- data/lib/aspera/cli/plugins/console.rb +23 -19
- data/lib/aspera/cli/plugins/cos.rb +18 -18
- data/lib/aspera/cli/plugins/faspex.rb +180 -159
- data/lib/aspera/cli/plugins/faspex5.rb +64 -54
- data/lib/aspera/cli/plugins/node.rb +147 -140
- data/lib/aspera/cli/plugins/orchestrator.rb +68 -66
- data/lib/aspera/cli/plugins/preview.rb +92 -96
- data/lib/aspera/cli/plugins/server.rb +79 -75
- data/lib/aspera/cli/plugins/shares.rb +23 -24
- data/lib/aspera/cli/plugins/sync.rb +20 -22
- data/lib/aspera/cli/transfer_agent.rb +40 -39
- data/lib/aspera/cli/version.rb +2 -1
- data/lib/aspera/colors.rb +35 -27
- data/lib/aspera/command_line_builder.rb +48 -34
- data/lib/aspera/cos_node.rb +29 -21
- data/lib/aspera/data_repository.rb +3 -2
- data/lib/aspera/environment.rb +50 -45
- data/lib/aspera/fasp/agent_base.rb +22 -20
- data/lib/aspera/fasp/agent_connect.rb +13 -11
- data/lib/aspera/fasp/agent_direct.rb +48 -59
- data/lib/aspera/fasp/agent_httpgw.rb +33 -39
- data/lib/aspera/fasp/agent_node.rb +15 -13
- data/lib/aspera/fasp/agent_trsdk.rb +12 -14
- data/lib/aspera/fasp/error.rb +2 -1
- data/lib/aspera/fasp/error_info.rb +68 -52
- data/lib/aspera/fasp/installation.rb +106 -94
- data/lib/aspera/fasp/listener.rb +1 -0
- data/lib/aspera/fasp/parameters.rb +83 -92
- data/lib/aspera/fasp/parameters.yaml +305 -249
- data/lib/aspera/fasp/resume_policy.rb +11 -14
- data/lib/aspera/fasp/transfer_spec.rb +26 -0
- data/lib/aspera/fasp/uri.rb +22 -21
- data/lib/aspera/faspex_gw.rb +55 -90
- data/lib/aspera/hash_ext.rb +4 -3
- data/lib/aspera/id_generator.rb +8 -7
- data/lib/aspera/keychain/encrypted_hash.rb +17 -16
- data/lib/aspera/keychain/macos_security.rb +6 -10
- data/lib/aspera/log.rb +25 -20
- data/lib/aspera/nagios.rb +13 -12
- data/lib/aspera/node.rb +30 -22
- data/lib/aspera/oauth.rb +175 -226
- data/lib/aspera/open_application.rb +4 -3
- data/lib/aspera/persistency_action_once.rb +6 -6
- data/lib/aspera/persistency_folder.rb +5 -9
- data/lib/aspera/preview/file_types.rb +6 -5
- data/lib/aspera/preview/generator.rb +25 -24
- data/lib/aspera/preview/options.rb +16 -14
- data/lib/aspera/preview/utils.rb +98 -98
- data/lib/aspera/{proxy_auto_config.erb.js → proxy_auto_config.js} +23 -31
- data/lib/aspera/proxy_auto_config.rb +111 -20
- data/lib/aspera/rest.rb +115 -113
- data/lib/aspera/rest_call_error.rb +2 -2
- data/lib/aspera/rest_error_analyzer.rb +23 -25
- data/lib/aspera/rest_errors_aspera.rb +15 -14
- data/lib/aspera/ssh.rb +12 -10
- data/lib/aspera/sync.rb +42 -41
- data/lib/aspera/temp_file_manager.rb +18 -14
- data/lib/aspera/timer_limiter.rb +2 -1
- data/lib/aspera/uri_reader.rb +7 -5
- data/lib/aspera/web_auth.rb +79 -76
- metadata +64 -21
- data/docs/Makefile +0 -65
- data/docs/README.erb.md +0 -4424
- data/docs/README.md +0 -13
- data/docs/diagrams.txt +0 -49
- data/docs/doc_tools.rb +0 -58
- data/lib/aspera/cli/plugins/shares2.rb +0 -114
- data/lib/aspera/fasp/default.rb +0 -17
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'aspera/cli/plugins/node'
|
|
2
3
|
require 'aspera/cli/plugins/ats'
|
|
3
4
|
require 'aspera/cli/basic_auth_plugin'
|
|
4
5
|
require 'aspera/cli/transfer_agent'
|
|
5
6
|
require 'aspera/fasp/agent_node'
|
|
7
|
+
require 'aspera/fasp/transfer_spec'
|
|
6
8
|
require 'aspera/aoc'
|
|
7
9
|
require 'aspera/node'
|
|
8
10
|
require 'aspera/persistency_action_once'
|
|
@@ -17,9 +19,10 @@ module Aspera
|
|
|
17
19
|
class << self
|
|
18
20
|
def detect(base_url)
|
|
19
21
|
api=Rest.new({base_url: base_url})
|
|
20
|
-
|
|
21
|
-
if
|
|
22
|
-
|
|
22
|
+
# either in standard domain, or product name in page
|
|
23
|
+
if URI.parse(base_url).host.end_with?(Aspera::AoC::PROD_DOMAIN) ||
|
|
24
|
+
api.call({operation: 'GET', redirect_max: 1, headers: {'Accept'=>'text/html'}})[:http].body.include?(Aspera::AoC::PRODUCT_NAME)
|
|
25
|
+
return {product: :aoc,version: 'SaaS' }
|
|
23
26
|
end
|
|
24
27
|
return nil
|
|
25
28
|
end
|
|
@@ -38,34 +41,34 @@ module Aspera
|
|
|
38
41
|
@api_aoc=nil
|
|
39
42
|
@url_token_data=nil
|
|
40
43
|
@api_aoc=nil
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
AoC.
|
|
44
|
+
options.add_opt_list(:auth,Oauth::STD_AUTH_TYPES,'OAuth type of authentication')
|
|
45
|
+
options.add_opt_list(:operation,[:push,:pull],'client operation for transfers')
|
|
46
|
+
options.add_opt_simple(:client_id,'OAuth API client identifier in application')
|
|
47
|
+
options.add_opt_simple(:client_secret,'OAuth API client passcode')
|
|
48
|
+
options.add_opt_simple(:redirect_uri,'OAuth API client redirect URI')
|
|
49
|
+
options.add_opt_simple(:private_key,'OAuth JWT RSA private key PEM value (prefix file path with @val:@file:)')
|
|
50
|
+
options.add_opt_simple(:workspace,'name of workspace')
|
|
51
|
+
options.add_opt_simple(:name,'resource name')
|
|
52
|
+
options.add_opt_simple(:path,'file or folder path')
|
|
53
|
+
options.add_opt_simple(:link,'public link to shared resource')
|
|
54
|
+
options.add_opt_simple(:new_user_option,'new user creation option')
|
|
55
|
+
options.add_opt_simple(:from_folder,'share to share source folder')
|
|
56
|
+
options.add_opt_simple(:scope,'OAuth scope for AoC API calls')
|
|
57
|
+
options.add_opt_boolean(:bulk,'bulk operation')
|
|
58
|
+
options.add_opt_boolean(:default_ports,'use standard FASP ports or get from node api')
|
|
59
|
+
options.set_option(:bulk,:no)
|
|
60
|
+
options.set_option(:default_ports,:yes)
|
|
61
|
+
options.set_option(:new_user_option,{'package_contact'=>true})
|
|
62
|
+
options.set_option(:operation,:push)
|
|
63
|
+
options.set_option(:auth,:jwt)
|
|
64
|
+
options.set_option(:scope,AoC::SCOPE_FILES_USER)
|
|
65
|
+
options.set_option(:private_key,'@file:'+env[:private_key_path]) if env[:private_key_path].is_a?(String)
|
|
66
|
+
options.parse_options!
|
|
67
|
+
AoC.use_standard_ports=options.get_option(:default_ports)
|
|
65
68
|
return if env[:man_only]
|
|
66
69
|
end
|
|
67
70
|
|
|
68
|
-
def
|
|
71
|
+
def aoc_api
|
|
69
72
|
if @api_aoc.nil?
|
|
70
73
|
@api_aoc=AoC.new(aoc_params(AoC::API_V1))
|
|
71
74
|
# add keychain for access key secrets
|
|
@@ -77,23 +80,23 @@ module Aspera
|
|
|
77
80
|
# starts transfer using transfer agent
|
|
78
81
|
def transfer_start(app,direction,node_file,ts_add)
|
|
79
82
|
ts_add.deep_merge!(AoC.analytics_ts(app,direction,@workspace_id,@workspace_name))
|
|
80
|
-
ts_add.deep_merge!(
|
|
81
|
-
return
|
|
83
|
+
ts_add.deep_merge!(aoc_api.console_ts(app))
|
|
84
|
+
return transfer.start(*aoc_api.tr_spec(app,direction,node_file,ts_add))
|
|
82
85
|
end
|
|
83
86
|
|
|
84
|
-
NODE4_COMMANDS=[
|
|
87
|
+
NODE4_COMMANDS=[:browse, :find, :mkdir, :rename, :delete, :upload, :download, :transfer, :http_node_download, :v3, :file, :bearer_token_node, :node_info].freeze
|
|
85
88
|
|
|
86
89
|
def execute_node_gen4_command(command_repo,top_node_file)
|
|
87
90
|
case command_repo
|
|
88
91
|
when :bearer_token_node
|
|
89
|
-
thepath=
|
|
90
|
-
node_file =
|
|
91
|
-
node_api
|
|
92
|
+
thepath=options.get_next_argument('path')
|
|
93
|
+
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
|
94
|
+
node_api=aoc_api.get_node_api(node_file[:node_info], use_secret: false)
|
|
92
95
|
return Main.result_status(node_api.oauth_token)
|
|
93
96
|
when :node_info
|
|
94
|
-
thepath=
|
|
95
|
-
node_file =
|
|
96
|
-
node_api
|
|
97
|
+
thepath=options.get_next_argument('path')
|
|
98
|
+
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
|
99
|
+
node_api=aoc_api.get_node_api(node_file[:node_info], use_secret: false)
|
|
97
100
|
return {type: :single_object,data: {
|
|
98
101
|
url: node_file[:node_info]['url'],
|
|
99
102
|
username: node_file[:node_info]['access_key'],
|
|
@@ -101,12 +104,12 @@ module Aspera
|
|
|
101
104
|
root_id: node_file[:file_id]
|
|
102
105
|
}}
|
|
103
106
|
when :browse
|
|
104
|
-
thepath=
|
|
105
|
-
node_file =
|
|
106
|
-
node_api
|
|
107
|
+
thepath=options.get_next_argument('path')
|
|
108
|
+
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
|
109
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
|
107
110
|
file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
|
|
108
111
|
if file_info['type'].eql?('folder')
|
|
109
|
-
result=node_api.read("files/#{node_file[:file_id]}/files",
|
|
112
|
+
result=node_api.read("files/#{node_file[:file_id]}/files",options.get_option(:value,:optional))
|
|
110
113
|
items=result[:data]
|
|
111
114
|
self.format.display_status("Items: #{result[:data].length}/#{result[:http]['X-Total-Count']}")
|
|
112
115
|
else
|
|
@@ -114,31 +117,31 @@ module Aspera
|
|
|
114
117
|
end
|
|
115
118
|
return {type: :object_list,data: items,fields: ['name','type','recursive_size','size','modified_time','access_level']}
|
|
116
119
|
when :find
|
|
117
|
-
thepath=
|
|
118
|
-
node_file
|
|
119
|
-
test_block=Aspera::Node.file_matcher(
|
|
120
|
-
return {type: :object_list,data:
|
|
120
|
+
thepath=options.get_next_argument('path')
|
|
121
|
+
node_file=aoc_api.resolve_node_file(top_node_file,thepath)
|
|
122
|
+
test_block=Aspera::Node.file_matcher(options.get_option(:value,:optional))
|
|
123
|
+
return {type: :object_list,data: aoc_api.find_files(node_file,test_block),fields: ['path']}
|
|
121
124
|
when :mkdir
|
|
122
|
-
thepath=
|
|
125
|
+
thepath=options.get_next_argument('path')
|
|
123
126
|
containing_folder_path = thepath.split(AoC::PATH_SEPARATOR)
|
|
124
127
|
new_folder=containing_folder_path.pop
|
|
125
|
-
node_file =
|
|
126
|
-
node_api
|
|
128
|
+
node_file = aoc_api.resolve_node_file(top_node_file,containing_folder_path.join(AoC::PATH_SEPARATOR))
|
|
129
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
|
127
130
|
result=node_api.create("files/#{node_file[:file_id]}/files",{name: new_folder,type: :folder})[:data]
|
|
128
131
|
return Main.result_status("created: #{result['name']} (id=#{result['id']})")
|
|
129
132
|
when :rename
|
|
130
|
-
thepath=
|
|
131
|
-
newname=
|
|
132
|
-
node_file =
|
|
133
|
-
node_api
|
|
133
|
+
thepath=options.get_next_argument('source path')
|
|
134
|
+
newname=options.get_next_argument('new name')
|
|
135
|
+
node_file = aoc_api.resolve_node_file(top_node_file,thepath)
|
|
136
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
|
134
137
|
result=node_api.update("files/#{node_file[:file_id]}",{name: newname})[:data]
|
|
135
138
|
return Main.result_status("renamed #{thepath} to #{newname}")
|
|
136
139
|
when :delete
|
|
137
|
-
thepath=
|
|
140
|
+
thepath=options.get_next_argument('path')
|
|
138
141
|
return do_bulk_operation(thepath,'deleted','path') do |l_path|
|
|
139
142
|
raise "expecting String (path), got #{l_path.class.name} (#{l_path})" unless l_path.is_a?(String)
|
|
140
|
-
node_file =
|
|
141
|
-
node_api
|
|
143
|
+
node_file = aoc_api.resolve_node_file(top_node_file,l_path)
|
|
144
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
|
142
145
|
result=node_api.delete("files/#{node_file[:file_id]}")[:data]
|
|
143
146
|
{'path'=>l_path}
|
|
144
147
|
end
|
|
@@ -148,26 +151,26 @@ module Aspera
|
|
|
148
151
|
# in same workspace
|
|
149
152
|
server_home_node_file=client_home_node_file=top_node_file
|
|
150
153
|
# default is push
|
|
151
|
-
case
|
|
154
|
+
case options.get_option(:operation,:mandatory)
|
|
152
155
|
when :push
|
|
153
|
-
client_tr_oper=
|
|
154
|
-
client_folder=
|
|
155
|
-
server_folder=
|
|
156
|
+
client_tr_oper=Fasp::TransferSpec::DIRECTION_SEND
|
|
157
|
+
client_folder=options.get_option(:from_folder,:mandatory)
|
|
158
|
+
server_folder=transfer.destination_folder(client_tr_oper)
|
|
156
159
|
when :pull
|
|
157
|
-
client_tr_oper=
|
|
158
|
-
client_folder=
|
|
159
|
-
server_folder=
|
|
160
|
+
client_tr_oper=Fasp::TransferSpec::DIRECTION_RECEIVE
|
|
161
|
+
client_folder=transfer.destination_folder(client_tr_oper)
|
|
162
|
+
server_folder=options.get_option(:from_folder,:mandatory)
|
|
160
163
|
end
|
|
161
|
-
client_node_file =
|
|
162
|
-
server_node_file =
|
|
164
|
+
client_node_file = aoc_api.resolve_node_file(client_home_node_file,client_folder)
|
|
165
|
+
server_node_file = aoc_api.resolve_node_file(server_home_node_file,server_folder)
|
|
163
166
|
# force node as transfer agent
|
|
164
|
-
client_node_api
|
|
165
|
-
@agents[:transfer].
|
|
167
|
+
client_node_api=aoc_api.get_node_api(client_node_file[:node_info], use_secret: false)
|
|
168
|
+
@agents[:transfer].agent_instance=Fasp::AgentNode.new({
|
|
166
169
|
url: client_node_api.params[:base_url],
|
|
167
170
|
username: client_node_file[:node_info]['access_key'],
|
|
168
171
|
password: client_node_api.oauth_token,
|
|
169
172
|
root_id: client_node_file[:file_id]
|
|
170
|
-
})
|
|
173
|
+
})
|
|
171
174
|
# additional node to node TS info
|
|
172
175
|
add_ts={
|
|
173
176
|
'remote_access_key' => server_node_file[:node_info]['access_key'],
|
|
@@ -176,11 +179,11 @@ module Aspera
|
|
|
176
179
|
}
|
|
177
180
|
return Main.result_transfer(transfer_start(AoC::FILES_APP,client_tr_oper,server_node_file,add_ts))
|
|
178
181
|
when :upload
|
|
179
|
-
node_file =
|
|
182
|
+
node_file = aoc_api.resolve_node_file(top_node_file,transfer.destination_folder(Fasp::TransferSpec::DIRECTION_SEND))
|
|
180
183
|
add_ts={'tags'=>{'aspera'=>{'files'=>{'parentCwd'=>"#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
|
|
181
|
-
return Main.result_transfer(transfer_start(AoC::FILES_APP,
|
|
184
|
+
return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_SEND,node_file,add_ts))
|
|
182
185
|
when :download
|
|
183
|
-
source_paths=
|
|
186
|
+
source_paths=transfer.ts_source_paths
|
|
184
187
|
# special case for AoC : all files must be in same folder
|
|
185
188
|
source_folder=source_paths.shift['source']
|
|
186
189
|
# if a single file: split into folder and path
|
|
@@ -189,13 +192,13 @@ module Aspera
|
|
|
189
192
|
source_paths=[{'source'=>source_folder.pop}]
|
|
190
193
|
source_folder=source_folder.join(AoC::PATH_SEPARATOR)
|
|
191
194
|
end
|
|
192
|
-
node_file =
|
|
195
|
+
node_file = aoc_api.resolve_node_file(top_node_file,source_folder)
|
|
193
196
|
# override paths with just filename
|
|
194
197
|
add_ts={'tags'=>{'aspera'=>{'files'=>{'parentCwd'=>"#{node_file[:node_info]['id']}:#{node_file[:file_id]}"}}}}
|
|
195
198
|
add_ts.merge!({'paths'=>source_paths})
|
|
196
|
-
return Main.result_transfer(transfer_start(AoC::FILES_APP,
|
|
199
|
+
return Main.result_transfer(transfer_start(AoC::FILES_APP,Fasp::TransferSpec::DIRECTION_RECEIVE,node_file,add_ts))
|
|
197
200
|
when :http_node_download
|
|
198
|
-
source_paths=
|
|
201
|
+
source_paths=transfer.ts_source_paths
|
|
199
202
|
source_folder=source_paths.shift['source']
|
|
200
203
|
if source_paths.empty?
|
|
201
204
|
source_folder=source_folder.split(AoC::PATH_SEPARATOR)
|
|
@@ -204,35 +207,37 @@ module Aspera
|
|
|
204
207
|
end
|
|
205
208
|
raise CliBadArgument,'one file at a time only in HTTP mode' if source_paths.length > 1
|
|
206
209
|
file_name = source_paths.first['source']
|
|
207
|
-
node_file =
|
|
208
|
-
node_api
|
|
209
|
-
node_api.call({operation: 'GET',subpath: "files/#{node_file[:file_id]}/content",
|
|
210
|
+
node_file = aoc_api.resolve_node_file(top_node_file,File.join(source_folder,file_name))
|
|
211
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
|
212
|
+
node_api.call({operation: 'GET',subpath: "files/#{node_file[:file_id]}/content",
|
|
213
|
+
save_to_file: File.join(transfer.destination_folder(Fasp::TransferSpec::DIRECTION_RECEIVE),file_name)})
|
|
210
214
|
return Main.result_status("downloaded: #{file_name}")
|
|
211
215
|
when :v3
|
|
212
216
|
# Note: other common actions are unauthorized with user scope
|
|
213
|
-
command_legacy=
|
|
217
|
+
command_legacy=options.get_next_command(Node::SIMPLE_ACTIONS)
|
|
214
218
|
# TODO: shall we support all methods here ? what if there is a link ?
|
|
215
|
-
node_api
|
|
219
|
+
node_api=aoc_api.get_node_api(top_node_file[:node_info])
|
|
216
220
|
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: node_api)).execute_action(command_legacy)
|
|
217
221
|
when :file
|
|
218
|
-
command_node_file=
|
|
219
|
-
file_path=
|
|
220
|
-
node_file =
|
|
221
|
-
|
|
222
|
+
command_node_file=options.get_next_command([:show,:permission,:modify])
|
|
223
|
+
file_path=options.get_option(:path,:optional)
|
|
224
|
+
node_file =
|
|
225
|
+
if !file_path.nil?
|
|
226
|
+
aoc_api.resolve_node_file(top_node_file,file_path) # TODO: allow follow link ?
|
|
222
227
|
else
|
|
223
|
-
{node_info: top_node_file[:node_info],file_id:
|
|
228
|
+
{node_info: top_node_file[:node_info],file_id: instance_identifier()}
|
|
224
229
|
end
|
|
225
|
-
node_api
|
|
230
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
|
226
231
|
case command_node_file
|
|
227
232
|
when :show
|
|
228
233
|
items=node_api.read("files/#{node_file[:file_id]}")[:data]
|
|
229
234
|
return {type: :single_object,data: items}
|
|
230
235
|
when :modify
|
|
231
|
-
update_param=
|
|
236
|
+
update_param=options.get_next_argument('update data (Hash)')
|
|
232
237
|
res=node_api.update("files/#{node_file[:file_id]}",update_param)[:data]
|
|
233
238
|
return {type: :single_object,data: res}
|
|
234
239
|
when :permission
|
|
235
|
-
command_perm=
|
|
240
|
+
command_perm=options.get_next_command([:list,:create])
|
|
236
241
|
case command_perm
|
|
237
242
|
when :list
|
|
238
243
|
# generic options : TODO: as arg ? option_url_query
|
|
@@ -258,10 +263,10 @@ module Aspera
|
|
|
258
263
|
'tags' =>{'aspera'=>{'files'=>{'workspace'=>{
|
|
259
264
|
'id' =>@workspace_id,
|
|
260
265
|
'workspace_name' =>@workspace_name,
|
|
261
|
-
'user_name'
|
|
262
|
-
'shared_by_user_id'
|
|
263
|
-
'shared_by_name'
|
|
264
|
-
'shared_by_email'
|
|
266
|
+
'user_name' =>aoc_api.user_info['name'],
|
|
267
|
+
'shared_by_user_id'=>aoc_api.user_info['id'],
|
|
268
|
+
'shared_by_name' =>aoc_api.user_info['name'],
|
|
269
|
+
'shared_by_email' =>aoc_api.user_info['email'],
|
|
265
270
|
'shared_with_name' =>access_id,
|
|
266
271
|
'access_key' =>node_file[:node_info]['access_key'],
|
|
267
272
|
'node' =>node_file[:node_info]['name']}}}}}
|
|
@@ -269,10 +274,8 @@ module Aspera
|
|
|
269
274
|
return {type: :single_object,data: item}
|
|
270
275
|
else raise "internal error:shall not reach here (#{command_perm})"
|
|
271
276
|
end
|
|
272
|
-
raise 'internal error:shall not reach here'
|
|
273
277
|
else raise "internal error:shall not reach here (#{command_node_file})"
|
|
274
278
|
end
|
|
275
|
-
raise 'internal error:shall not reach here'
|
|
276
279
|
end # command_repo
|
|
277
280
|
raise 'ERR'
|
|
278
281
|
end # execute_node_gen4_command
|
|
@@ -280,7 +283,7 @@ module Aspera
|
|
|
280
283
|
# build constructor option list for AoC based on options of CLI
|
|
281
284
|
def aoc_params(subpath)
|
|
282
285
|
# copy command line options to args
|
|
283
|
-
opt=[:link,:url,:auth,:client_id,:client_secret,:scope,:redirect_uri,:private_key,:username,:password].
|
|
286
|
+
opt=[:link,:url,:auth,:client_id,:client_secret,:scope,:redirect_uri,:private_key,:username,:password].each_with_object({}){|i,m|m[i]=options.get_option(i,:optional);}
|
|
284
287
|
opt[:subpath]=subpath
|
|
285
288
|
return opt
|
|
286
289
|
end
|
|
@@ -293,17 +296,16 @@ module Aspera
|
|
|
293
296
|
# @persist_ids
|
|
294
297
|
# returns nil
|
|
295
298
|
def set_workspace_info
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
@
|
|
299
|
+
@url_token_data=aoc_api.url_token_data
|
|
300
|
+
if @url_token_data.nil?
|
|
301
|
+
@default_workspace_id=aoc_api.user_info['default_workspace_id']
|
|
302
|
+
@persist_ids=[aoc_api.user_info['id']]
|
|
303
|
+
else
|
|
299
304
|
@default_workspace_id=@url_token_data['data']['workspace_id']
|
|
300
305
|
@persist_ids=[] # TODO : @url_token_data['id'] ?
|
|
301
|
-
else
|
|
302
|
-
@default_workspace_id=@api_aoc.user_info['default_workspace_id']
|
|
303
|
-
@persist_ids=[@api_aoc.user_info['id']]
|
|
304
306
|
end
|
|
305
307
|
|
|
306
|
-
ws_name=
|
|
308
|
+
ws_name=options.get_option(:workspace,:optional)
|
|
307
309
|
if ws_name.nil?
|
|
308
310
|
Log.log.debug('using default workspace'.green)
|
|
309
311
|
if @default_workspace_id.eql?(nil)
|
|
@@ -313,7 +315,7 @@ module Aspera
|
|
|
313
315
|
@workspace_id=@default_workspace_id
|
|
314
316
|
else
|
|
315
317
|
# lookup another workspace
|
|
316
|
-
wss
|
|
318
|
+
wss=aoc_api.read('workspaces',{'q'=>ws_name})[:data]
|
|
317
319
|
wss=wss.select { |i| i['name'].eql?(ws_name) }
|
|
318
320
|
case wss.length
|
|
319
321
|
when 0
|
|
@@ -324,7 +326,7 @@ module Aspera
|
|
|
324
326
|
raise 'unexpected case'
|
|
325
327
|
end
|
|
326
328
|
end
|
|
327
|
-
@workspace_data
|
|
329
|
+
@workspace_data=aoc_api.read("workspaces/#{@workspace_id}")[:data]
|
|
328
330
|
Log.log.debug("workspace_id=#{@workspace_id},@workspace_data=#{@workspace_data}".red)
|
|
329
331
|
|
|
330
332
|
@workspace_name||=@workspace_data['name']
|
|
@@ -346,16 +348,16 @@ module Aspera
|
|
|
346
348
|
home_file_id||=@workspace_data['home_file_id']
|
|
347
349
|
raise 'node_id must be defined' if home_node_id.to_s.empty?
|
|
348
350
|
@home_node_file={
|
|
349
|
-
node_info:
|
|
351
|
+
node_info: aoc_api.read("nodes/#{home_node_id}")[:data],
|
|
350
352
|
file_id: home_file_id
|
|
351
353
|
}
|
|
352
|
-
|
|
354
|
+
aoc_api.check_get_node_file(@home_node_file)
|
|
353
355
|
|
|
354
356
|
return nil
|
|
355
357
|
end
|
|
356
358
|
|
|
357
359
|
def do_bulk_operation(ids_or_one,success_msg,id_result='id',&do_action)
|
|
358
|
-
ids_or_one=[ids_or_one] unless
|
|
360
|
+
ids_or_one=[ids_or_one] unless options.get_option(:bulk)
|
|
359
361
|
raise 'expecting Array' unless ids_or_one.is_a?(Array)
|
|
360
362
|
result_list=[]
|
|
361
363
|
ids_or_one.each do |id|
|
|
@@ -364,7 +366,7 @@ module Aspera
|
|
|
364
366
|
res=do_action.call(id)
|
|
365
367
|
one=res if id.is_a?(Hash) # if block returns a has, let's use this
|
|
366
368
|
one['status']=success_msg
|
|
367
|
-
rescue => e
|
|
369
|
+
rescue StandardError => e
|
|
368
370
|
one['status']=e.to_s
|
|
369
371
|
end
|
|
370
372
|
result_list.push(one)
|
|
@@ -375,15 +377,15 @@ module Aspera
|
|
|
375
377
|
# get identifier or name from command line
|
|
376
378
|
# @return identifier
|
|
377
379
|
def get_resource_id_from_args(resource_class_path)
|
|
378
|
-
l_res_id=
|
|
379
|
-
l_res_name=
|
|
380
|
-
raise
|
|
380
|
+
l_res_id=options.get_option(:id)
|
|
381
|
+
l_res_name=options.get_option(:name)
|
|
382
|
+
raise 'Provide either option id or name, not both' unless l_res_id.nil? || l_res_name.nil?
|
|
381
383
|
# try to find item by name (single partial match or exact match)
|
|
382
|
-
l_res_id
|
|
384
|
+
l_res_id=aoc_api.lookup_entity_by_name(resource_class_path,l_res_name)['id'] unless l_res_name.nil?
|
|
383
385
|
# if no name or id option, taken on command line (after command)
|
|
384
386
|
if l_res_id.nil?
|
|
385
|
-
l_res_id=
|
|
386
|
-
l_res_id
|
|
387
|
+
l_res_id=options.get_next_argument('identifier')
|
|
388
|
+
l_res_id=aoc_api.lookup_entity_by_name(resource_class_path,options.get_next_argument('identifier'))['id'] if l_res_id.eql?('name')
|
|
387
389
|
end
|
|
388
390
|
return l_res_id
|
|
389
391
|
end
|
|
@@ -396,7 +398,7 @@ module Aspera
|
|
|
396
398
|
def resolve_package_recipients(package_data,recipient_list_field)
|
|
397
399
|
return unless package_data.has_key?(recipient_list_field)
|
|
398
400
|
raise CliBadArgument,"#{recipient_list_field} must be an Array" unless package_data[recipient_list_field].is_a?(Array)
|
|
399
|
-
new_user_option=
|
|
401
|
+
new_user_option=options.get_option(:new_user_option,:mandatory)
|
|
400
402
|
# list with resolved elements
|
|
401
403
|
resolved_list=[]
|
|
402
404
|
package_data[recipient_list_field].each do |short_recipient_info|
|
|
@@ -407,20 +409,13 @@ module Aspera
|
|
|
407
409
|
# email: user, else dropbox
|
|
408
410
|
entity_type=short_recipient_info.include?('@') ? 'contacts' : 'dropboxes'
|
|
409
411
|
begin
|
|
410
|
-
full_recipient_info
|
|
412
|
+
full_recipient_info=aoc_api.lookup_entity_by_name(entity_type,short_recipient_info,{'current_workspace_id'=>@workspace_id})
|
|
411
413
|
rescue RuntimeError => e
|
|
412
414
|
raise e unless e.message.eql?('not found')
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
else
|
|
416
|
-
raise "no such shared inbox in workspace #{@workspace_name}"
|
|
417
|
-
end
|
|
418
|
-
end
|
|
419
|
-
if entity_type.eql?('dropboxes')
|
|
420
|
-
short_recipient_info={'id'=>full_recipient_info['id'],'type'=>'dropbox'}
|
|
421
|
-
else
|
|
422
|
-
short_recipient_info={'id'=>full_recipient_info['source_id'],'type'=>full_recipient_info['source_type']}
|
|
415
|
+
raise "no such shared inbox in workspace #{@workspace_name}" unless entity_type.eql?('contacts')
|
|
416
|
+
full_recipient_info=aoc_api.create('contacts',{'current_workspace_id'=>@workspace_id,'email'=>short_recipient_info}.merge(new_user_option))[:data]
|
|
423
417
|
end
|
|
418
|
+
short_recipient_info=entity_type.eql?('dropboxes') ? {'id'=>full_recipient_info['id'],'type'=>'dropbox'} : {'id'=>full_recipient_info['source_id'],'type'=>full_recipient_info['source_type']}
|
|
424
419
|
else # unexpected extended value, must be String or Hash
|
|
425
420
|
raise "#{recipient_list_field} item must be a String (email, shared inbox) or Hash (id,type)"
|
|
426
421
|
end # type of recipient info
|
|
@@ -433,8 +428,8 @@ module Aspera
|
|
|
433
428
|
|
|
434
429
|
def normalize_metadata(pkg_data)
|
|
435
430
|
case pkg_data['metadata']
|
|
436
|
-
when NilClass
|
|
437
|
-
when Array
|
|
431
|
+
when NilClass then return
|
|
432
|
+
when Array then return
|
|
438
433
|
when Hash
|
|
439
434
|
api_meta=[]
|
|
440
435
|
pkg_data['metadata'].each do |k,v|
|
|
@@ -445,7 +440,6 @@ module Aspera
|
|
|
445
440
|
})
|
|
446
441
|
end
|
|
447
442
|
pkg_data['metadata']=api_meta
|
|
448
|
-
|
|
449
443
|
else raise "metadata field if not of expected type: #{pkg_meta.class}"
|
|
450
444
|
end
|
|
451
445
|
nil
|
|
@@ -453,27 +447,26 @@ module Aspera
|
|
|
453
447
|
|
|
454
448
|
# private
|
|
455
449
|
def option_url_query(default)
|
|
456
|
-
query=
|
|
450
|
+
query=options.get_option(:query,:optional)
|
|
457
451
|
query=default if query.nil?
|
|
458
452
|
Log.log.debug("Query=#{query}".bg_red)
|
|
459
453
|
begin
|
|
460
454
|
# check it is suitable
|
|
461
455
|
URI.encode_www_form(query) unless query.nil?
|
|
462
|
-
rescue => e
|
|
456
|
+
rescue StandardError => e
|
|
463
457
|
raise CliBadArgument,"query must be an extended value which can be encoded with URI.encode_www_form. Refer to manual. (#{e.message})"
|
|
464
458
|
end
|
|
465
459
|
return query
|
|
466
460
|
end
|
|
467
461
|
|
|
468
462
|
def assert_public_link_types(expected)
|
|
469
|
-
|
|
470
|
-
raise CliBadArgument,"public link type is #{@url_token_data['purpose']} but action requires one of #{expected.join(',')}"
|
|
471
|
-
end
|
|
463
|
+
raise CliBadArgument,"public link type is #{@url_token_data['purpose']} but action requires one of #{expected.join(',')}" unless expected.include?(@url_token_data['purpose'])
|
|
472
464
|
end
|
|
473
465
|
|
|
474
|
-
# Call
|
|
466
|
+
# Call aoc_api.read with same parameters.
|
|
467
|
+
# Use paging if necessary to get all results
|
|
475
468
|
def read_with_paging(resource_class_path,base_query)
|
|
476
|
-
raise
|
|
469
|
+
raise 'Query must be Hash' unless base_query.is_a?(Hash)
|
|
477
470
|
# set default large page if user does not specify own parameters. AoC Caps to 1000 anyway
|
|
478
471
|
base_query['per_page']=1000 unless base_query.has_key?('per_page')
|
|
479
472
|
max_items=base_query[MAX_ITEMS]
|
|
@@ -488,7 +481,7 @@ module Aspera
|
|
|
488
481
|
loop do
|
|
489
482
|
query=base_query.clone
|
|
490
483
|
query['page']=current_page
|
|
491
|
-
result
|
|
484
|
+
result=aoc_api.read(resource_class_path,query)
|
|
492
485
|
total_count=result[:http]['X-Total-Count']
|
|
493
486
|
page_count+=1
|
|
494
487
|
current_page+=1
|
|
@@ -496,26 +489,28 @@ module Aspera
|
|
|
496
489
|
break if add_items.empty?
|
|
497
490
|
# append new items to full list
|
|
498
491
|
item_list += add_items
|
|
499
|
-
break if !max_pages.nil?
|
|
500
|
-
break if !max_items.nil?
|
|
492
|
+
break if !max_pages.nil? && page_count > max_pages
|
|
493
|
+
break if !max_items.nil? && item_list.count > max_items
|
|
501
494
|
end
|
|
502
495
|
return item_list,total_count
|
|
503
496
|
end
|
|
504
497
|
|
|
505
498
|
def execute_admin_action
|
|
506
|
-
|
|
507
|
-
|
|
499
|
+
# upgrade scope to admin
|
|
500
|
+
aoc_api.oauth.params[:scope]=AoC::SCOPE_FILES_ADMIN
|
|
501
|
+
command_admin=options.get_next_command([:ats, :resource, :usage_reports, :analytics, :subscription, :auth_providers])
|
|
508
502
|
case command_admin
|
|
509
503
|
when :auth_providers
|
|
510
|
-
command_auth_prov=
|
|
504
|
+
command_auth_prov=options.get_next_command([:list, :update])
|
|
511
505
|
case command_auth_prov
|
|
512
506
|
when :list
|
|
513
|
-
providers
|
|
507
|
+
providers=aoc_api.read('admin/auth_providers')[:data]
|
|
514
508
|
return {type: :object_list,data: providers}
|
|
515
509
|
when :update
|
|
510
|
+
raise 'not implemented'
|
|
516
511
|
end
|
|
517
512
|
when :subscription
|
|
518
|
-
org
|
|
513
|
+
org=aoc_api.read('organization')[:data]
|
|
519
514
|
bss_api=AoC.new(aoc_params('bss/platform'))
|
|
520
515
|
graphql_query="
|
|
521
516
|
query ($organization_id: ID!) {
|
|
@@ -568,41 +563,41 @@ module Aspera
|
|
|
568
563
|
result=bss_api.create('graphql',{'variables'=>{'organization_id'=>org['id']},'query'=>graphql_query})[:data]['data']
|
|
569
564
|
return {type: :single_object,data: result['aoc']['bssSubscription']}
|
|
570
565
|
when :ats
|
|
571
|
-
ats_api = Rest.new(
|
|
572
|
-
base_url:
|
|
566
|
+
ats_api = Rest.new(aoc_api.params.deep_merge({
|
|
567
|
+
base_url: aoc_api.params[:base_url]+'/admin/ats/pub/v1',
|
|
573
568
|
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
|
574
569
|
}))
|
|
575
570
|
return Ats.new(@agents).execute_action_gen(ats_api)
|
|
576
571
|
when :analytics
|
|
577
|
-
analytics_api = Rest.new(
|
|
578
|
-
base_url:
|
|
572
|
+
analytics_api = Rest.new(aoc_api.params.deep_merge({
|
|
573
|
+
base_url: aoc_api.params[:base_url].gsub('/api/v1','')+'/analytics/v2',
|
|
579
574
|
auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
|
|
580
575
|
}))
|
|
581
|
-
command_analytics=
|
|
576
|
+
command_analytics=options.get_next_command([:application_events, :transfers])
|
|
582
577
|
case command_analytics
|
|
583
578
|
when :application_events
|
|
584
579
|
event_type=command_analytics.to_s
|
|
585
|
-
events=analytics_api.read("organizations/#{
|
|
580
|
+
events=analytics_api.read("organizations/#{aoc_api.user_info['organization_id']}/#{event_type}")[:data][event_type]
|
|
586
581
|
return {type: :object_list,data: events}
|
|
587
582
|
when :transfers
|
|
588
583
|
event_type=command_analytics.to_s
|
|
589
|
-
filter_resource=
|
|
590
|
-
filter_id=
|
|
591
|
-
|
|
592
|
-
when '
|
|
593
|
-
when '
|
|
584
|
+
filter_resource=options.get_option(:name,:optional) || 'organizations'
|
|
585
|
+
filter_id=options.get_option(:id,:optional) ||
|
|
586
|
+
case filter_resource
|
|
587
|
+
when 'organizations' then aoc_api.user_info['organization_id']
|
|
588
|
+
when 'users' then aoc_api.user_info['id']
|
|
589
|
+
when 'nodes' then aoc_api.user_info['id']
|
|
594
590
|
else raise 'organizations or users for option --name'
|
|
595
591
|
end
|
|
596
|
-
|
|
597
|
-
filter=self.options.get_option(:query,:optional) || {}
|
|
592
|
+
filter=options.get_option(:query,:optional) || {}
|
|
598
593
|
raise 'query must be Hash' unless filter.is_a?(Hash)
|
|
599
594
|
filter['limit']||=100
|
|
600
|
-
if
|
|
595
|
+
if options.get_option(:once_only,:mandatory)
|
|
601
596
|
saved_date=[]
|
|
602
597
|
startdate_persistency=PersistencyActionOnce.new(
|
|
603
598
|
manager: @agents[:persistency],
|
|
604
599
|
data: saved_date,
|
|
605
|
-
ids: IdGenerator.from_list(['aoc_ana_date',
|
|
600
|
+
ids: IdGenerator.from_list(['aoc_ana_date',options.get_option(:url,:mandatory),@workspace_name].push(filter_resource,filter_id)))
|
|
606
601
|
start_datetime=saved_date.first
|
|
607
602
|
stop_datetime=Time.now.utc.strftime('%FT%T.%LZ')
|
|
608
603
|
#Log.log().error("start: #{start_datetime}")
|
|
@@ -613,23 +608,26 @@ module Aspera
|
|
|
613
608
|
end
|
|
614
609
|
events=analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}",option_url_query(filter))[:data][event_type]
|
|
615
610
|
startdate_persistency.save unless startdate_persistency.nil?
|
|
616
|
-
if !
|
|
611
|
+
if !options.get_option(:notif_to,:optional).nil?
|
|
617
612
|
events.each do |tr_event|
|
|
618
|
-
|
|
613
|
+
config.send_email_template({ev: tr_event})
|
|
619
614
|
end
|
|
620
615
|
end
|
|
621
616
|
return {type: :object_list,data: events}
|
|
622
617
|
end
|
|
623
618
|
when :resource
|
|
624
|
-
resource_type=
|
|
619
|
+
resource_type=options.get_next_argument('resource',
|
|
620
|
+
[:self,:organization,:user,:group,:client,:contact,:dropbox,:node,:operation,:package,:saml_configuration, :workspace, :dropbox_membership,:short_link,:workspace_membership,
|
|
621
|
+
:application,:client_registration_token,:client_access_key,:kms_profile])
|
|
625
622
|
# get path on API, resource type is singular, but api is plural
|
|
626
|
-
resource_class_path=
|
|
623
|
+
resource_class_path=
|
|
624
|
+
case resource_type
|
|
627
625
|
# special cases: singleton, in admin, with x
|
|
628
|
-
when :self,:organization
|
|
629
|
-
when :client_registration_token,:client_access_key
|
|
630
|
-
when :application
|
|
631
|
-
when :dropbox
|
|
632
|
-
when :kms_profile
|
|
626
|
+
when :self,:organization then resource_type
|
|
627
|
+
when :client_registration_token,:client_access_key then "admin/#{resource_type}s"
|
|
628
|
+
when :application then 'admin/apps_new'
|
|
629
|
+
when :dropbox then resource_type.to_s+'es'
|
|
630
|
+
when :kms_profile then "integrations/#{resource_type}s"
|
|
633
631
|
else resource_type.to_s+'s'
|
|
634
632
|
end
|
|
635
633
|
# build list of supported operations
|
|
@@ -640,9 +638,9 @@ module Aspera
|
|
|
640
638
|
supported_operations.push(:v4,:v3) if resource_type.eql?(:node)
|
|
641
639
|
supported_operations.push(:set_pub_key) if resource_type.eql?(:client)
|
|
642
640
|
supported_operations.push(:shared_folders,:shared_create) if [:node,:workspace].include?(resource_type)
|
|
643
|
-
command=
|
|
641
|
+
command=options.get_next_command(supported_operations)
|
|
644
642
|
# require identifier for non global commands
|
|
645
|
-
if !singleton_object
|
|
643
|
+
if !singleton_object && !global_operations.include?(command)
|
|
646
644
|
res_id=get_resource_id_from_args(resource_class_path)
|
|
647
645
|
resource_instance_path="#{resource_class_path}/#{res_id}"
|
|
648
646
|
end
|
|
@@ -653,23 +651,24 @@ module Aspera
|
|
|
653
651
|
id_result='token' if resource_class_path.eql?('admin/client_registration_tokens')
|
|
654
652
|
# TODO: report inconsistency: creation url is !=, and does not return id.
|
|
655
653
|
resource_class_path='admin/client_registration/token' if resource_class_path.eql?('admin/client_registration_tokens')
|
|
656
|
-
list_or_one=
|
|
657
|
-
return do_bulk_operation(list_or_one,'created',id_result)do|params|
|
|
654
|
+
list_or_one=options.get_next_argument('creation data (Hash)')
|
|
655
|
+
return do_bulk_operation(list_or_one,'created',id_result) do |params|
|
|
658
656
|
raise 'expecting Hash' unless params.is_a?(Hash)
|
|
659
|
-
|
|
657
|
+
aoc_api.create(resource_class_path,params)[:data]
|
|
660
658
|
end
|
|
661
659
|
when :list
|
|
662
660
|
default_fields=['id']
|
|
663
661
|
default_query={}
|
|
664
662
|
case resource_type
|
|
665
|
-
when :application
|
|
666
|
-
|
|
667
|
-
when :
|
|
668
|
-
when :
|
|
669
|
-
when :
|
|
670
|
-
when :
|
|
671
|
-
when :
|
|
672
|
-
when :
|
|
663
|
+
when :application then default_query={organization_apps: true};
|
|
664
|
+
default_fields.push('app_type','app_name','available','direct_authorizations_allowed','workspace_authorizations_allowed')
|
|
665
|
+
when :client,:client_access_key,:dropbox,:group,:package,:saml_configuration,:workspace then default_fields.push('name')
|
|
666
|
+
when :client_registration_token then default_fields.push('value','data.client_subject_scopes','created_at')
|
|
667
|
+
when :contact then default_fields=['email','name','source_id','source_type']
|
|
668
|
+
when :node then default_fields.push('name','host','access_key')
|
|
669
|
+
when :operation then default_fields=nil
|
|
670
|
+
when :short_link then default_fields.push('short_url','data.url_token_data.purpose')
|
|
671
|
+
when :user then default_fields.push('name','email')
|
|
673
672
|
end
|
|
674
673
|
item_list,total_count=read_with_paging(resource_class_path,option_url_query(default_query))
|
|
675
674
|
count_msg="Items: #{item_list.length}/#{total_count}"
|
|
@@ -677,52 +676,54 @@ module Aspera
|
|
|
677
676
|
self.format.display_status(count_msg)
|
|
678
677
|
return {type: :object_list,data: item_list,fields: default_fields}
|
|
679
678
|
when :show
|
|
680
|
-
object
|
|
681
|
-
fields=object.keys.
|
|
679
|
+
object=aoc_api.read(resource_instance_path)[:data]
|
|
680
|
+
fields=object.keys.reject{|k|k.eql?('certificate')}
|
|
682
681
|
return { type: :single_object, data: object, fields: fields }
|
|
683
682
|
when :modify
|
|
684
|
-
changes=
|
|
685
|
-
|
|
683
|
+
changes=options.get_next_argument('modified parameters (hash)')
|
|
684
|
+
aoc_api.update(resource_instance_path,changes)
|
|
686
685
|
return Main.result_status('modified')
|
|
687
686
|
when :delete
|
|
688
|
-
return do_bulk_operation(res_id,'deleted')do|one_id|
|
|
689
|
-
|
|
687
|
+
return do_bulk_operation(res_id,'deleted') do |one_id|
|
|
688
|
+
aoc_api.delete("#{resource_class_path}/#{one_id}")
|
|
690
689
|
{'id'=>one_id}
|
|
691
690
|
end
|
|
692
691
|
when :set_pub_key
|
|
693
692
|
# special : reads private and generate public
|
|
694
|
-
the_private_key=
|
|
693
|
+
the_private_key=options.get_next_argument('private_key')
|
|
695
694
|
the_public_key=OpenSSL::PKey::RSA.new(the_private_key).public_key.to_s
|
|
696
|
-
|
|
695
|
+
aoc_api.update(resource_instance_path,{jwt_grant_enabled: true, public_key: the_public_key})
|
|
697
696
|
return Main.result_success
|
|
698
697
|
when :v3,:v4
|
|
699
|
-
res_data
|
|
700
|
-
api_node
|
|
698
|
+
res_data=aoc_api.read(resource_instance_path)[:data]
|
|
699
|
+
api_node=aoc_api.get_node_api(res_data)
|
|
701
700
|
return Node.new(@agents.merge(skip_basic_auth_options: true, node_api: api_node)).execute_action if command.eql?(:v3)
|
|
702
701
|
ak_data=api_node.call({operation: 'GET',subpath: "access_keys/#{res_data['access_key']}",headers: {'Accept'=>'application/json'}})[:data]
|
|
703
|
-
command_repo=
|
|
702
|
+
command_repo=options.get_next_command(NODE4_COMMANDS)
|
|
704
703
|
return execute_node_gen4_command(command_repo,{node_info: res_data, file_id: ak_data['root_file_id']})
|
|
705
704
|
when :shared_folders
|
|
706
|
-
read_params
|
|
707
|
-
|
|
708
|
-
when :
|
|
705
|
+
read_params=
|
|
706
|
+
case resource_type
|
|
707
|
+
when :workspace then{'access_id'=>"#{ID_AK_ADMIN}_WS_#{res_id}",'access_type'=>'user'}
|
|
708
|
+
when :node then{'include'=>['[]','access_level','permission_count'],'created_by_id'=>ID_AK_ADMIN}
|
|
709
709
|
else raise 'error'
|
|
710
710
|
end
|
|
711
|
-
res_data
|
|
712
|
-
fields=
|
|
713
|
-
|
|
714
|
-
when :
|
|
711
|
+
res_data=aoc_api.read("#{resource_instance_path}/permissions",read_params)[:data]
|
|
712
|
+
fields=
|
|
713
|
+
case resource_type
|
|
714
|
+
when :node then['id','file_id','file.path','access_type']
|
|
715
|
+
when :workspace then['id','node_id','file_id','node_name','file.path','tags.aspera.files.workspace.share_as']
|
|
715
716
|
else raise "unexpected resource type #{resource_type}"
|
|
716
717
|
end
|
|
717
|
-
return { type: :object_list, data: res_data
|
|
718
|
+
return { type: :object_list, data: res_data, fields: fields}
|
|
718
719
|
when :shared_create
|
|
719
720
|
# TODO: finish implementation
|
|
720
|
-
folder_path=
|
|
721
|
-
user_create_data=
|
|
722
|
-
res_data
|
|
723
|
-
node_file =
|
|
721
|
+
folder_path=options.get_next_argument('folder path in node')
|
|
722
|
+
user_create_data=options.get_next_argument('creation data (Hash)')
|
|
723
|
+
res_data=aoc_api.read(resource_instance_path)[:data]
|
|
724
|
+
node_file = aoc_api.resolve_node_file({node_info: res_data, file_id: ak_data['root_file_id']},folder_path)
|
|
724
725
|
|
|
725
|
-
#node_api
|
|
726
|
+
#node_api=aoc_api.get_node_api(node_file[:node_info])
|
|
726
727
|
#file_info = node_api.read("files/#{node_file[:file_id]}")[:data]
|
|
727
728
|
|
|
728
729
|
access_id="#{ID_AK_ADMIN}_WS_#{@workspace_id}"
|
|
@@ -735,10 +736,10 @@ module Aspera
|
|
|
735
736
|
'id' =>@workspace_id,
|
|
736
737
|
'workspace_name' =>@workspace_name,
|
|
737
738
|
'share_as' =>File.basename(folder_path),
|
|
738
|
-
'user_name'
|
|
739
|
-
'shared_by_user_id'
|
|
740
|
-
'shared_by_name'
|
|
741
|
-
'shared_by_email'
|
|
739
|
+
'user_name' =>aoc_api.user_info['name'],
|
|
740
|
+
'shared_by_user_id'=>aoc_api.user_info['id'],
|
|
741
|
+
'shared_by_name' =>aoc_api.user_info['name'],
|
|
742
|
+
'shared_by_email' =>aoc_api.user_info['email'],
|
|
742
743
|
'shared_with_name' =>access_id,
|
|
743
744
|
'access_key' =>node_file[:node_info]['access_key'],
|
|
744
745
|
'node' =>node_file[:node_info]['name']}
|
|
@@ -749,17 +750,15 @@ module Aspera
|
|
|
749
750
|
else raise 'unknown command'
|
|
750
751
|
end
|
|
751
752
|
when :usage_reports
|
|
752
|
-
return {type: :object_list,data:
|
|
753
|
+
return {type: :object_list,data: aoc_api.read('usage_reports',{workspace_id: @workspace_id})[:data]}
|
|
753
754
|
end
|
|
754
755
|
end
|
|
755
756
|
|
|
756
757
|
# must be public
|
|
757
|
-
ACTIONS=[
|
|
758
|
+
ACTIONS=[:reminder, :servers, :bearer_token, :organization, :tier_restrictions, :user, :packages, :files, :admin, :automation, :gateway].freeze
|
|
758
759
|
|
|
759
760
|
def execute_action
|
|
760
|
-
command=
|
|
761
|
-
# all commands require to login, but those 2
|
|
762
|
-
get_api unless [:reminder,:servers].include?(command)
|
|
761
|
+
command=options.get_next_command(ACTIONS)
|
|
763
762
|
case command
|
|
764
763
|
when :reminder
|
|
765
764
|
# send an email reminder with list of orgs
|
|
@@ -769,48 +768,48 @@ module Aspera
|
|
|
769
768
|
when :servers
|
|
770
769
|
return {type: :object_list,data: Rest.new(base_url: "#{AoC.api_base_url}/#{AoC::API_V1}").read('servers')[:data]}
|
|
771
770
|
when :bearer_token
|
|
772
|
-
return {type: :text,data:
|
|
771
|
+
return {type: :text,data: aoc_api.oauth_token}
|
|
773
772
|
when :organization
|
|
774
|
-
return { type: :single_object, data:
|
|
773
|
+
return { type: :single_object, data: aoc_api.read('organization')[:data] }
|
|
775
774
|
when :tier_restrictions
|
|
776
|
-
return { type: :single_object, data:
|
|
775
|
+
return { type: :single_object, data: aoc_api.read('tier_restrictions')[:data] }
|
|
777
776
|
when :user
|
|
778
|
-
case
|
|
777
|
+
case options.get_next_command([:workspaces,:profile])
|
|
779
778
|
# when :settings
|
|
780
|
-
# return {type: :object_list,data:
|
|
779
|
+
# return {type: :object_list,data: aoc_api.read('client_settings/')[:data]}
|
|
781
780
|
when :workspaces
|
|
782
|
-
case
|
|
781
|
+
case options.get_next_command([:list,:current])
|
|
783
782
|
when :list
|
|
784
|
-
return {type: :object_list,data:
|
|
783
|
+
return {type: :object_list,data: aoc_api.read('workspaces')[:data],fields: ['id','name']}
|
|
785
784
|
when :current
|
|
786
785
|
set_workspace_info
|
|
787
786
|
return { type: :single_object, data: @workspace_data }
|
|
788
787
|
end
|
|
789
788
|
when :profile
|
|
790
|
-
case
|
|
789
|
+
case options.get_next_command([:show,:modify])
|
|
791
790
|
when :show
|
|
792
|
-
return { type: :single_object, data:
|
|
791
|
+
return { type: :single_object, data: aoc_api.user_info }
|
|
793
792
|
when :modify
|
|
794
|
-
|
|
793
|
+
aoc_api.update("users/#{aoc_api.user_info['id']}",options.get_next_argument('modified parameters (hash)'))
|
|
795
794
|
return Main.result_status('modified')
|
|
796
795
|
end
|
|
797
796
|
end
|
|
798
797
|
when :packages
|
|
799
798
|
set_workspace_info if @url_token_data.nil?
|
|
800
|
-
case
|
|
799
|
+
case options.get_next_command([:shared_inboxes, :send, :recv, :list, :show, :delete])
|
|
801
800
|
when :shared_inboxes
|
|
802
|
-
case
|
|
801
|
+
case options.get_next_command([:list, :show])
|
|
803
802
|
when :list
|
|
804
803
|
query=option_url_query(nil)
|
|
805
804
|
if query.nil?
|
|
806
805
|
query={'embed[]'=>'dropbox','workspace_id'=>@workspace_id,'aggregate_permissions_by_dropbox'=>true,'sort'=>'dropbox_name'}
|
|
807
806
|
end
|
|
808
|
-
return {type: :object_list,data:
|
|
807
|
+
return {type: :object_list,data: aoc_api.read('dropbox_memberships',query)[:data],fields: ['dropbox_id','dropbox.name']}
|
|
809
808
|
when :show
|
|
810
|
-
return {type: :single_object,data:
|
|
809
|
+
return {type: :single_object,data: aoc_api.read(get_resource_path_from_args('dropboxes'),query)[:data]}
|
|
811
810
|
end
|
|
812
811
|
when :send
|
|
813
|
-
package_data=
|
|
812
|
+
package_data=options.get_option(:value,:mandatory)
|
|
814
813
|
raise CliBadArgument,'value must be hash, refer to doc' unless package_data.is_a?(Hash)
|
|
815
814
|
|
|
816
815
|
if !@url_token_data.nil?
|
|
@@ -831,56 +830,56 @@ module Aspera
|
|
|
831
830
|
normalize_metadata(package_data)
|
|
832
831
|
|
|
833
832
|
# create a new package container
|
|
834
|
-
package_info
|
|
833
|
+
package_info=aoc_api.create('packages',package_data)[:data]
|
|
835
834
|
|
|
836
835
|
# get node information for the node on which package must be created
|
|
837
|
-
node_info
|
|
836
|
+
node_info=aoc_api.read("nodes/#{package_info['node_id']}")[:data]
|
|
838
837
|
|
|
839
838
|
# tell AoC what to expect in package: 1 transfer (can also be done after transfer)
|
|
840
839
|
# TODO: if multisession was used we should probably tell
|
|
841
840
|
# also, currently no "multi-source" , i.e. only from client-side files, unless "node" agent is used
|
|
842
|
-
|
|
841
|
+
aoc_api.update("packages/#{package_info['id']}",{'sent'=>true,'transfers_expected'=>1})[:data]
|
|
843
842
|
|
|
844
843
|
# get destination: package folder
|
|
845
844
|
node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
|
|
846
845
|
# execute transfer, raise exception if at least one error
|
|
847
|
-
Main.result_transfer(transfer_start(AoC::PACKAGES_APP,
|
|
846
|
+
Main.result_transfer(transfer_start(AoC::PACKAGES_APP,Fasp::TransferSpec::DIRECTION_SEND,node_file,AoC.package_tags(package_info,'upload')))
|
|
848
847
|
# return all info on package
|
|
849
848
|
return { type: :single_object, data: package_info}
|
|
850
849
|
when :recv
|
|
851
850
|
if !@url_token_data.nil?
|
|
852
851
|
assert_public_link_types(['view_received_package'])
|
|
853
|
-
|
|
852
|
+
options.set_option(:id,@url_token_data['data']['package_id'])
|
|
854
853
|
end
|
|
855
854
|
# scalar here
|
|
856
|
-
ids_to_download=
|
|
855
|
+
ids_to_download=instance_identifier()
|
|
857
856
|
skip_ids_data=[]
|
|
858
857
|
skip_ids_persistency=nil
|
|
859
|
-
if
|
|
858
|
+
if options.get_option(:once_only,:mandatory)
|
|
860
859
|
skip_ids_persistency=PersistencyActionOnce.new(
|
|
861
860
|
manager: @agents[:persistency],
|
|
862
861
|
data: skip_ids_data,
|
|
863
|
-
id: IdGenerator.from_list(['aoc_recv',
|
|
862
|
+
id: IdGenerator.from_list(['aoc_recv',options.get_option(:url,:mandatory),@workspace_id].push(*@persist_ids)))
|
|
864
863
|
end
|
|
865
864
|
if ids_to_download.eql?(VAL_ALL)
|
|
866
865
|
# get list of packages in inbox
|
|
867
|
-
package_info
|
|
866
|
+
package_info=aoc_api.read('packages',{'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true,'workspace_id'=>@workspace_id})[:data]
|
|
868
867
|
# remove from list the ones already downloaded
|
|
869
868
|
ids_to_download=package_info.map{|e|e['id']}
|
|
870
869
|
# array here
|
|
871
|
-
ids_to_download.
|
|
870
|
+
ids_to_download.reject!{|id|skip_ids_data.include?(id)}
|
|
872
871
|
end # ALL
|
|
873
872
|
# list here
|
|
874
873
|
ids_to_download = [ids_to_download] unless ids_to_download.is_a?(Array)
|
|
875
874
|
result_transfer=[]
|
|
876
875
|
self.format.display_status("found #{ids_to_download.length} package(s).")
|
|
877
876
|
ids_to_download.each do |package_id|
|
|
878
|
-
package_info
|
|
879
|
-
node_info
|
|
877
|
+
package_info=aoc_api.read("packages/#{package_id}")[:data]
|
|
878
|
+
node_info=aoc_api.read("nodes/#{package_info['node_id']}")[:data]
|
|
880
879
|
self.format.display_status("downloading package: #{package_info['name']}")
|
|
881
880
|
add_ts={'paths'=>[{'source'=>'.'}]}
|
|
882
881
|
node_file = {node_info: node_info, file_id: package_info['contents_file_id']}
|
|
883
|
-
statuses=transfer_start(AoC::PACKAGES_APP,
|
|
882
|
+
statuses=transfer_start(AoC::PACKAGES_APP,Fasp::TransferSpec::DIRECTION_RECEIVE,node_file,AoC.package_tags(package_info,'download').merge(add_ts))
|
|
884
883
|
result_transfer.push({'package'=>package_id,Main::STATUS_FIELD=>statuses})
|
|
885
884
|
# update skip list only if all transfer sessions completed
|
|
886
885
|
if TransferAgent.session_status(statuses).eql?(:success)
|
|
@@ -890,57 +889,55 @@ module Aspera
|
|
|
890
889
|
end
|
|
891
890
|
return Main.result_transfer_multiple(result_transfer)
|
|
892
891
|
when :show
|
|
893
|
-
package_id=
|
|
894
|
-
package_info
|
|
892
|
+
package_id=options.get_next_argument('package ID')
|
|
893
|
+
package_info=aoc_api.read("packages/#{package_id}")[:data]
|
|
895
894
|
return { type: :single_object, data: package_info }
|
|
896
895
|
when :list
|
|
897
896
|
query=option_url_query({'archived'=>false,'exclude_dropbox_packages'=>true,'has_content'=>true,'received'=>true})
|
|
898
897
|
if query.has_key?('dropbox_name')
|
|
899
898
|
# convenience: specify name instead of id
|
|
900
899
|
raise 'not both dropbox_name and dropbox_id' if query.has_key?('dropbox_id')
|
|
901
|
-
query['dropbox_id']
|
|
900
|
+
query['dropbox_id']=aoc_api.lookup_entity_by_name('dropboxes',query['dropbox_name'])['id']
|
|
902
901
|
query.delete('dropbox_name')
|
|
903
902
|
end
|
|
904
903
|
raise 'option must be Hash' unless query.is_a?(Hash)
|
|
905
904
|
query['workspace_id']||=@workspace_id
|
|
906
|
-
packages
|
|
905
|
+
packages=aoc_api.read('packages',query)[:data]
|
|
907
906
|
return {type: :object_list,data: packages,fields: ['id','name','bytes_transferred']}
|
|
908
907
|
when :delete
|
|
909
|
-
list_or_one=
|
|
910
|
-
return do_bulk_operation(list_or_one,'deleted')do|id|
|
|
911
|
-
raise 'expecting String identifier' unless id.is_a?(String)
|
|
912
|
-
|
|
908
|
+
list_or_one=instance_identifier()
|
|
909
|
+
return do_bulk_operation(list_or_one,'deleted') do |id|
|
|
910
|
+
raise 'expecting String identifier' unless id.is_a?(String) || id.is_a?(Integer)
|
|
911
|
+
aoc_api.delete("packages/#{id}")[:data]
|
|
913
912
|
end
|
|
914
913
|
end
|
|
915
914
|
when :files
|
|
916
915
|
# get workspace related information
|
|
917
916
|
set_workspace_info
|
|
918
917
|
set_home_node_file
|
|
919
|
-
command_repo=
|
|
918
|
+
command_repo=options.get_next_command([NODE4_COMMANDS,:short_link].flatten)
|
|
920
919
|
case command_repo
|
|
921
|
-
when *NODE4_COMMANDS
|
|
920
|
+
when *NODE4_COMMANDS then return execute_node_gen4_command(command_repo,@home_node_file)
|
|
922
921
|
when :short_link
|
|
923
|
-
folder_dest=
|
|
924
|
-
value_option=
|
|
922
|
+
folder_dest=options.get_option(:to_folder,:optional)
|
|
923
|
+
value_option=options.get_option(:value,:optional)
|
|
925
924
|
case value_option
|
|
926
|
-
when 'public'
|
|
927
|
-
|
|
928
|
-
when
|
|
929
|
-
value_option={'purpose'=>'shared_folder_auth_link'}
|
|
930
|
-
when NilClass,Hash
|
|
925
|
+
when 'public' then value_option={'purpose'=>'token_auth_redirection'}
|
|
926
|
+
when 'private' then value_option={'purpose'=>'shared_folder_auth_link'}
|
|
927
|
+
when NilClass,Hash then nil # keep value
|
|
931
928
|
else raise 'value must be either: public, private, Hash or nil'
|
|
932
929
|
end
|
|
933
930
|
create_params=nil
|
|
934
931
|
node_file=nil
|
|
935
932
|
if !folder_dest.nil?
|
|
936
|
-
node_file =
|
|
933
|
+
node_file = aoc_api.resolve_node_file(@home_node_file,folder_dest)
|
|
937
934
|
create_params={
|
|
938
935
|
file_id: node_file[:file_id],
|
|
939
936
|
node_id: node_file[:node_info]['id'],
|
|
940
937
|
workspace_id: @workspace_id
|
|
941
938
|
}
|
|
942
939
|
end
|
|
943
|
-
if !value_option.nil?
|
|
940
|
+
if !value_option.nil? && !create_params.nil?
|
|
944
941
|
case value_option['purpose']
|
|
945
942
|
when 'shared_folder_auth_link'
|
|
946
943
|
value_option['data']=create_params
|
|
@@ -958,11 +955,11 @@ module Aspera
|
|
|
958
955
|
else
|
|
959
956
|
raise 'purpose must be one of: token_auth_redirection or shared_folder_auth_link'
|
|
960
957
|
end
|
|
961
|
-
|
|
958
|
+
options.set_option(:value,value_option)
|
|
962
959
|
end
|
|
963
|
-
result=
|
|
964
|
-
if result[:data].is_a?(Hash)
|
|
965
|
-
node_api
|
|
960
|
+
result=entity_action(@api_aoc,'short_links',id_default: 'self')
|
|
961
|
+
if result[:data].is_a?(Hash) && result[:data].has_key?('created_at') && result[:data]['resource_type'].eql?('UrlToken')
|
|
962
|
+
node_api=aoc_api.get_node_api(node_file[:node_info])
|
|
966
963
|
# TODO: access level as arg
|
|
967
964
|
access_levels=Aspera::Node::ACCESS_LEVELS #['delete','list','mkdir','preview','read','rename','write']
|
|
968
965
|
perm_data={
|
|
@@ -975,8 +972,8 @@ module Aspera
|
|
|
975
972
|
'workspace_id' =>@workspace_id,
|
|
976
973
|
'workspace_name' =>@workspace_name,
|
|
977
974
|
'folder_name' =>'my folder',
|
|
978
|
-
'created_by_name'
|
|
979
|
-
'created_by_email'
|
|
975
|
+
'created_by_name' =>aoc_api.user_info['name'],
|
|
976
|
+
'created_by_email'=>aoc_api.user_info['email'],
|
|
980
977
|
'access_key' =>node_file[:node_info]['access_key'],
|
|
981
978
|
'node' =>node_file[:node_info]['host']
|
|
982
979
|
}
|
|
@@ -990,26 +987,27 @@ module Aspera
|
|
|
990
987
|
when :automation
|
|
991
988
|
Log.log.warn('BETA: work under progress')
|
|
992
989
|
# automation api is not in the same place
|
|
993
|
-
automation_rest_params
|
|
990
|
+
automation_rest_params=aoc_api.params.clone
|
|
994
991
|
automation_rest_params[:base_url].gsub!('/api/','/automation/')
|
|
995
992
|
automation_api=Rest.new(automation_rest_params)
|
|
996
|
-
command_automation=
|
|
993
|
+
command_automation=options.get_next_command([:workflows, :instances])
|
|
997
994
|
case command_automation
|
|
998
995
|
when :instances
|
|
999
|
-
return
|
|
996
|
+
return entity_action(@api_aoc,'workflow_instances')
|
|
1000
997
|
when :workflows
|
|
1001
|
-
|
|
1002
|
-
wf_command=self.options.get_next_command(wF_COMMANDS)
|
|
998
|
+
wf_command=options.get_next_command([Plugin::ALL_OPS,:action,:launch].flatten)
|
|
1003
999
|
case wf_command
|
|
1004
1000
|
when *Plugin::ALL_OPS
|
|
1005
|
-
return
|
|
1001
|
+
return entity_command(wf_command,automation_api,'workflows',id_default: :id)
|
|
1006
1002
|
when :launch
|
|
1007
|
-
wf_id=
|
|
1003
|
+
wf_id=instance_identifier()
|
|
1008
1004
|
data=automation_api.create("workflows/#{wf_id}/launch",{})[:data]
|
|
1009
1005
|
return {type: :single_object,data: data}
|
|
1010
1006
|
when :action
|
|
1011
|
-
|
|
1012
|
-
wf_id=
|
|
1007
|
+
#TODO: not complete
|
|
1008
|
+
wf_id=instance_identifier()
|
|
1009
|
+
wf_action_cmd=options.get_next_command([:list,:create,:show])
|
|
1010
|
+
Log.log.warn("Not implemented: #{wf_action_cmd}")
|
|
1013
1011
|
step=automation_api.create('steps',{'workflow_id'=>wf_id})[:data]
|
|
1014
1012
|
automation_api.update("workflows/#{wf_id}",{'step_order'=>[step['id']]})
|
|
1015
1013
|
action=automation_api.create('actions',{'step_id'=>step['id'],'type'=>'manual'})[:data]
|
|
@@ -1027,12 +1025,11 @@ module Aspera
|
|
|
1027
1025
|
else
|
|
1028
1026
|
raise "internal error: #{command}"
|
|
1029
1027
|
end # action
|
|
1030
|
-
raise
|
|
1028
|
+
raise 'internal error: command shall return'
|
|
1031
1029
|
end
|
|
1032
1030
|
|
|
1033
1031
|
private :aoc_params,:set_workspace_info,:set_home_node_file,:do_bulk_operation,:resolve_package_recipients,:option_url_query,:assert_public_link_types,:execute_admin_action
|
|
1034
1032
|
private_constant :VAL_ALL,:NODE4_COMMANDS, :ID_AK_ADMIN
|
|
1035
|
-
|
|
1036
1033
|
end # AoC
|
|
1037
1034
|
end # Plugins
|
|
1038
1035
|
end # Cli
|