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