aspera-cli 4.14.0 → 4.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +54 -3
  4. data/CONTRIBUTING.md +7 -7
  5. data/README.md +1457 -880
  6. data/bin/ascli +18 -9
  7. data/bin/asession +12 -14
  8. data/examples/proxy.pac +1 -1
  9. data/lib/aspera/aoc.rb +198 -127
  10. data/lib/aspera/ascmd.rb +24 -14
  11. data/lib/aspera/cli/basic_auth_plugin.rb +9 -6
  12. data/lib/aspera/cli/error.rb +17 -0
  13. data/lib/aspera/cli/extended_value.rb +47 -12
  14. data/lib/aspera/cli/formatter.rb +260 -171
  15. data/lib/aspera/cli/hints.rb +80 -0
  16. data/lib/aspera/cli/main.rb +101 -147
  17. data/lib/aspera/cli/manager.rb +160 -124
  18. data/lib/aspera/cli/plugin.rb +70 -59
  19. data/lib/aspera/cli/plugins/alee.rb +0 -1
  20. data/lib/aspera/cli/plugins/aoc.rb +239 -273
  21. data/lib/aspera/cli/plugins/ats.rb +8 -5
  22. data/lib/aspera/cli/plugins/bss.rb +2 -2
  23. data/lib/aspera/cli/plugins/config.rb +516 -375
  24. data/lib/aspera/cli/plugins/console.rb +40 -0
  25. data/lib/aspera/cli/plugins/cos.rb +4 -5
  26. data/lib/aspera/cli/plugins/faspex.rb +99 -84
  27. data/lib/aspera/cli/plugins/faspex5.rb +179 -148
  28. data/lib/aspera/cli/plugins/node.rb +219 -153
  29. data/lib/aspera/cli/plugins/orchestrator.rb +52 -17
  30. data/lib/aspera/cli/plugins/preview.rb +46 -32
  31. data/lib/aspera/cli/plugins/server.rb +57 -17
  32. data/lib/aspera/cli/plugins/shares.rb +34 -12
  33. data/lib/aspera/cli/sync_actions.rb +68 -0
  34. data/lib/aspera/cli/transfer_agent.rb +45 -55
  35. data/lib/aspera/cli/transfer_progress.rb +74 -0
  36. data/lib/aspera/cli/version.rb +1 -1
  37. data/lib/aspera/colors.rb +3 -1
  38. data/lib/aspera/command_line_builder.rb +14 -11
  39. data/lib/aspera/cos_node.rb +3 -2
  40. data/lib/aspera/environment.rb +17 -6
  41. data/lib/aspera/fasp/agent_aspera.rb +126 -0
  42. data/lib/aspera/fasp/agent_base.rb +31 -77
  43. data/lib/aspera/fasp/agent_connect.rb +21 -22
  44. data/lib/aspera/fasp/agent_direct.rb +88 -102
  45. data/lib/aspera/fasp/agent_httpgw.rb +196 -192
  46. data/lib/aspera/fasp/agent_node.rb +41 -34
  47. data/lib/aspera/fasp/agent_trsdk.rb +75 -34
  48. data/lib/aspera/fasp/error_info.rb +2 -2
  49. data/lib/aspera/fasp/faux_file.rb +52 -0
  50. data/lib/aspera/fasp/installation.rb +43 -184
  51. data/lib/aspera/fasp/management.rb +244 -0
  52. data/lib/aspera/fasp/parameters.rb +59 -26
  53. data/lib/aspera/fasp/parameters.yaml +75 -8
  54. data/lib/aspera/fasp/products.rb +162 -0
  55. data/lib/aspera/fasp/transfer_spec.rb +1 -1
  56. data/lib/aspera/fasp/uri.rb +4 -4
  57. data/lib/aspera/faspex_gw.rb +2 -2
  58. data/lib/aspera/faspex_postproc.rb +2 -2
  59. data/lib/aspera/hash_ext.rb +2 -2
  60. data/lib/aspera/json_rpc.rb +49 -0
  61. data/lib/aspera/line_logger.rb +23 -0
  62. data/lib/aspera/log.rb +57 -16
  63. data/lib/aspera/node.rb +97 -14
  64. data/lib/aspera/oauth.rb +36 -18
  65. data/lib/aspera/open_application.rb +4 -4
  66. data/lib/aspera/persistency_folder.rb +2 -2
  67. data/lib/aspera/preview/file_types.rb +4 -2
  68. data/lib/aspera/preview/generator.rb +22 -35
  69. data/lib/aspera/preview/options.rb +2 -0
  70. data/lib/aspera/preview/terminal.rb +24 -13
  71. data/lib/aspera/preview/utils.rb +19 -26
  72. data/lib/aspera/rest.rb +103 -72
  73. data/lib/aspera/rest_call_error.rb +1 -1
  74. data/lib/aspera/rest_error_analyzer.rb +15 -14
  75. data/lib/aspera/rest_errors_aspera.rb +37 -34
  76. data/lib/aspera/secret_hider.rb +14 -16
  77. data/lib/aspera/ssh.rb +4 -1
  78. data/lib/aspera/sync.rb +128 -122
  79. data/lib/aspera/temp_file_manager.rb +10 -3
  80. data/lib/aspera/web_auth.rb +10 -7
  81. data/lib/aspera/web_server_simple.rb +9 -4
  82. data.tar.gz.sig +0 -0
  83. metadata +33 -15
  84. metadata.gz.sig +0 -0
  85. data/lib/aspera/cli/listener/line_dump.rb +0 -19
  86. data/lib/aspera/cli/listener/logger.rb +0 -22
  87. data/lib/aspera/cli/listener/progress.rb +0 -50
  88. data/lib/aspera/cli/listener/progress_multi.rb +0 -84
  89. data/lib/aspera/cli/plugins/sync.rb +0 -44
  90. data/lib/aspera/fasp/listener.rb +0 -13
@@ -17,18 +17,130 @@ module Aspera
17
17
  module Cli
18
18
  module Plugins
19
19
  class Aoc < Aspera::Cli::BasicAuthPlugin
20
+ AOC_PATH_API_CLIENTS = 'admin/api-clients'
21
+ # default redirect for AoC web auth
22
+ DEFAULT_REDIRECT = 'http://localhost:12345'
23
+ private_constant :AOC_PATH_API_CLIENTS, :DEFAULT_REDIRECT
20
24
  class << self
25
+ def application_name
26
+ 'Aspera on Cloud'
27
+ end
28
+
21
29
  def detect(base_url)
22
- api = Rest.new({base_url: base_url})
30
+ # no protocol ?
31
+ base_url = "https://#{base_url}" unless base_url.match?(%r{^[a-z]{1,6}://})
32
+ # only org provided ?
33
+ base_url = "#{base_url}.#{Aspera::AoC::PROD_DOMAIN}" unless base_url.include?('.')
34
+ # AoC is only https
35
+ return nil unless base_url.start_with?('https://')
36
+ result = Rest.new({base_url: base_url, redirect_max: 10}).read('')
37
+ # Any AoC is on this domain
38
+ return nil unless result[:http].uri.host.end_with?(Aspera::AoC::PROD_DOMAIN)
39
+ Log.log.debug{'AoC Main page: #{result[:http].body.include?(Aspera::AoC::PRODUCT_NAME)}'}
40
+ base_url = result[:http].uri.to_s if result[:http].uri.path.include?('/public')
23
41
  # 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)
42
+ return {
43
+ version: 'SaaS',
44
+ url: base_url
45
+ }
46
+ end
47
+
48
+ def private_key_required?(url)
49
+ # pub link do not need private key
50
+ return AoC.link_info(url)[:token].nil?
51
+ end
52
+
53
+ # @param [Hash] env : options, formatter
54
+ # @param [Hash] params : plugin_sym, instance_url
55
+ # @return [Hash] :preset_value, :test_args
56
+ def wizard(object:, private_key_path: nil, pub_key_pem: nil)
57
+ # set vars to look like object
58
+ options = object.options
59
+ formatter = object.formatter
60
+ options.declare(:use_generic_client, 'Wizard: AoC: use global or org specific jwt client id', values: :bool, default: true)
61
+ options.parse_options!
62
+ instance_url = options.get_option(:url, mandatory: true)
63
+ pub_link_info = AoC.link_info(instance_url)
64
+ if !pub_link_info[:token].nil?
65
+ pub_api = Rest.new({base_url: "https://#{URI.parse(pub_link_info[:url]).host}/api/v1"})
66
+ pub_info = pub_api.read('env/url_token_check', {token: pub_link_info[:token]})[:data]
67
+ preset_value = {
68
+ link: instance_url
69
+ }
70
+ preset_value[:password] = options.get_option(:password, mandatory: true) if pub_info['password_protected']
26
71
  return {
27
- version: 'SaaS',
28
- name: 'Aspera on Cloud'
72
+ preset_value: preset_value,
73
+ test_args: 'organization'
29
74
  }
30
75
  end
31
- return nil
76
+ # make username mandatory for jwt, this triggers interactive input
77
+ wiz_username = options.get_option(:username, mandatory: true)
78
+ raise "Username shall be an email in AoC: #{wiz_username}" if !(wiz_username =~ /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i)
79
+ # Set the pub key and jwt tag in the user's profile automatically
80
+ auto_set_pub_key = false
81
+ auto_set_jwt = false
82
+ # use browser authentication to bootstrap
83
+ use_browser_authentication = false
84
+ if options.get_option(:use_generic_client)
85
+ formatter.display_status('Using global client_id.')
86
+ formatter.display_status('Please Login to your Aspera on Cloud instance.')
87
+ formatter.display_status('Navigate to: 👤 → Account Settings → Profile → Public Key')
88
+ formatter.display_status('Check or update the value to:'.red.blink)
89
+ formatter.display_status(pub_key_pem)
90
+ if !options.get_option(:test_mode)
91
+ formatter.display_status('Once updated or validated, press enter.')
92
+ OpenApplication.instance.uri(instance_url)
93
+ $stdin.gets
94
+ end
95
+ else
96
+ formatter.display_status('Using organization specific client_id.')
97
+ if options.get_option(:client_id).nil? || options.get_option(:client_secret).nil?
98
+ formatter.display_status('Please login to your Aspera on Cloud instance.'.red)
99
+ formatter.display_status('Navigate to: 𓃑 → Admin → Integrations → API Clients')
100
+ formatter.display_status('Check or create in integration:')
101
+ formatter.display_status("- name: #{@info[:name]}")
102
+ formatter.display_status("- redirect uri: #{DEFAULT_REDIRECT}")
103
+ formatter.display_status('- origin: localhost')
104
+ formatter.display_status('Use the generated client id and secret in the following prompts.'.red)
105
+ end
106
+ OpenApplication.instance.uri("#{instance_url}/#{AOC_PATH_API_CLIENTS}")
107
+ options.get_option(:client_id, mandatory: true)
108
+ options.get_option(:client_secret, mandatory: true)
109
+ use_browser_authentication = true
110
+ end
111
+ if use_browser_authentication
112
+ formatter.display_status('We will use web authentication to bootstrap.')
113
+ auto_set_pub_key = true
114
+ auto_set_jwt = true
115
+ aoc_api.oauth.generic_parameters[:grant_method] = :web
116
+ aoc_api.oauth.generic_parameters[:scope] = AoC::SCOPE_FILES_ADMIN
117
+ aoc_api.oauth.specific_parameters[:redirect_uri] = DEFAULT_REDIRECT
118
+ end
119
+ myself = object.aoc_api.read('self')[:data]
120
+ if auto_set_pub_key
121
+ raise Cli::Error, 'Public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? || option_override
122
+ formatter.display_status('Updating profile with the public key.')
123
+ aoc_api.update("users/#{myself['id']}", {'public_key' => pub_key_pem})
124
+ end
125
+ if auto_set_jwt
126
+ formatter.display_status('Enabling JWT for client')
127
+ aoc_api.update("clients/#{options.get_option(:client_id)}", {'jwt_grant_enabled' => true, 'explicit_authorization_required' => false})
128
+ end
129
+ preset_result = {
130
+ url: instance_url,
131
+ username: myself['email'],
132
+ auth: :jwt.to_s,
133
+ private_key: "@file:#{private_key_path}"
134
+ }
135
+ # set only if non nil
136
+ %i[client_id client_secret].each do |s|
137
+ o = options.get_option(s)
138
+ preset_result[s.to_s] = o unless o.nil?
139
+ end
140
+ return {
141
+ preset_value: preset_result,
142
+ test_args: 'user profile show'
143
+ }
32
144
  end
33
145
  end
34
146
  # special value for package id
@@ -53,8 +165,6 @@ module Aspera
53
165
  client_registration_token
54
166
  client_access_key
55
167
  kms_profile].freeze
56
- # TODO: remove this and use %name: instead
57
- ENTITY_NAME_SPECIFIER = 'name'
58
168
  PACKAGE_QUERY_DEFAULT = {'archived' => false, 'exclude_dropbox_packages' => true, 'has_content' => true, 'received' => true}.freeze
59
169
 
60
170
  def initialize(env)
@@ -63,124 +173,51 @@ module Aspera
63
173
  @cache_home_node_file = nil
64
174
  @cache_api_aoc = nil
65
175
  options.declare(:auth, 'OAuth type of authentication', values: Oauth::STD_AUTH_TYPES, default: :jwt)
66
- options.declare(:operation, 'Client operation for transfers', values: %i[push pull], default: :push)
67
176
  options.declare(:client_id, 'OAuth API client identifier')
68
177
  options.declare(:client_secret, 'OAuth API client secret')
178
+ options.declare(:scope, 'OAuth scope for AoC API calls', default: AoC::SCOPE_FILES_USER)
69
179
  options.declare(:redirect_uri, 'OAuth API client redirect URI')
70
180
  options.declare(:private_key, 'OAuth JWT RSA private key PEM value (prefix file path with @file:)')
71
- options.declare(:scope, 'OAuth scope for AoC API calls', default: AoC::SCOPE_FILES_USER)
72
181
  options.declare(:passphrase, 'RSA private key passphrase')
73
- options.declare(:workspace, 'Name of workspace', default: :default)
74
- # TODO: remove this and use %name: instead
75
- options.declare(:name, "Resource name (prefer to use keyword #{ENTITY_NAME_SPECIFIER})")
76
- options.declare(:link, 'Public link to shared resource')
182
+ options.declare(:workspace, 'Name of workspace', types: [String, NilClass], default: Aspera::AoC::DEFAULT_WORKSPACE)
77
183
  options.declare(:new_user_option, 'New user creation option for unknown package recipients')
78
- options.declare(:from_folder, 'Source folder for Folder-to-Folder transfer')
79
184
  options.declare(:validate_metadata, 'Validate shared inbox metadata', values: :bool, default: true)
80
185
  options.parse_options!
81
- # add node plugin options (TODO: check needed ? if yes, tell why)
82
- Node.new(env.merge({man_only: true, skip_basic_auth_options: true}))
186
+ # add node plugin options (for manual)
187
+ Node.declare_options(options)
83
188
  end
84
189
 
85
- # build list of options for AoC API, based on options of CLI
86
- def aoc_params(subpath)
87
- # copy command line options to args
88
- return Aspera::AoC::OPTIONS_NEW.each_with_object({subpath: subpath}){|i, m|m[i] = options.get_option(i)}
89
- end
90
-
91
- def aoc_api
92
- if @cache_api_aoc.nil?
93
- @cache_api_aoc = AoC.new(aoc_params(AoC::API_V1))
94
- # add keychain for access key secrets
95
- @cache_api_aoc.secret_finder = @agents[:config]
96
- end
97
- return @cache_api_aoc
98
- end
190
+ OPTIONS_NEW = %i[url auth client_id client_secret scope redirect_uri private_key passphrase username password workspace].freeze
99
191
 
100
- # @return [Hash] current workspace information,
101
- def current_workspace_info
102
- return @cache_workspace_info unless @cache_workspace_info.nil?
103
- default_workspace_id = if aoc_api.url_token_data.nil?
104
- aoc_api.current_user_info['default_workspace_id']
105
- else
106
- aoc_api.url_token_data['data']['workspace_id']
192
+ def api_from_options(new_base_path)
193
+ create_values = {subpath: new_base_path, secret_finder: @agents[:config]}
194
+ # create an API object with the same options, but with a different subpath
195
+ return Aspera::AoC.new(**OPTIONS_NEW.each_with_object(create_values) { |i, m|m[i] = options.get_option(i) unless options.get_option(i).nil?})
196
+ rescue ArgumentError => e
197
+ if (m = e.message.match(/missing keyword: :(.*)$/))
198
+ raise Cli::Error, "Missing option: #{m[1]}"
107
199
  end
108
-
109
- ws_name = options.get_option(:workspace)
110
- ws_id =
111
- case ws_name
112
- when :default
113
- Log.log.debug('Using default workspace'.green)
114
- raise CliError, 'No default workspace defined for user, please specify workspace' if default_workspace_id.nil?
115
- default_workspace_id
116
- when String then aoc_api.lookup_by_name('workspaces', ws_name)['id']
117
- when NilClass then nil
118
- else raise CliError, 'unexpected value type for workspace'
119
- end
120
- @cache_workspace_info =
121
- begin
122
- aoc_api.read("workspaces/#{ws_id}")[:data]
123
- rescue Aspera::RestCallError => e
124
- Log.log.debug(e.message)
125
- { 'id' => :undefined, 'name' => :undefined }
126
- end
127
- Log.dump(:current_workspace_info, @cache_workspace_info)
128
- # display workspace
129
- default_flag = @cache_workspace_info['id'] == default_workspace_id ? ' (default)' : ''
130
- formatter.display_status("Current Workspace: #{@cache_workspace_info['name'].to_s.red}#{default_flag}")
131
- return @cache_workspace_info
200
+ raise
132
201
  end
133
202
 
134
- # @return [Hash] with :node_id and :file_id
135
- def home_info
136
- return @cache_home_node_file unless @cache_home_node_file.nil?
137
- if !aoc_api.url_token_data.nil?
138
- assert_public_link_types(['view_shared_file'])
139
- home_node_id = aoc_api.url_token_data['data']['node_id']
140
- home_file_id = aoc_api.url_token_data['data']['file_id']
141
- end
142
- home_node_id ||= current_workspace_info['home_node_id'] || current_workspace_info['node_id']
143
- home_file_id ||= current_workspace_info['home_file_id']
144
- if home_node_id.to_s.empty?
145
- # not part of any workspace, but has some folder shared
146
- user_info = aoc_api.current_user_info(exception: true)
147
- home_node_id = user_info['read_only_home_node_id']
148
- home_file_id = user_info['read_only_home_file_id']
149
- end
150
-
151
- raise "Cannot get user's home node id, check your default workspace or specify one" if home_node_id.to_s.empty?
152
- @cache_home_node_file = {
153
- node_id: home_node_id,
154
- file_id: home_file_id
155
- }
156
- return @cache_home_node_file
203
+ def aoc_api
204
+ @cache_api_aoc = api_from_options(AoC::API_V1) if @cache_api_aoc.nil?
205
+ return @cache_api_aoc
157
206
  end
158
207
 
159
208
  # get identifier or name from command line
160
209
  # @return identifier
161
210
  def get_resource_id_from_args(resource_class_path)
162
- l_res_id = options.get_option(:id)
163
- l_res_name = options.get_option(:name)
164
- raise 'Provide either option id or name, not both' unless l_res_id.nil? || l_res_name.nil?
165
- # try to find item by name (single partial match or exact match)
166
- l_res_id = aoc_api.lookup_by_name(resource_class_path, l_res_name)['id'] unless l_res_name.nil?
167
- # if no name or id option, taken on command line (after command)
168
- if l_res_id.nil?
169
- l_res_id = options.get_next_argument('identifier')
170
- l_res_id = aoc_api.lookup_by_name(resource_class_path, options.get_next_argument('identifier'))['id'] if l_res_id.eql?(ENTITY_NAME_SPECIFIER)
211
+ return instance_identifier do |field, value|
212
+ raise Cli::BadArgument, 'only selection by name is supported' unless field.eql?('name')
213
+ aoc_api.lookup_by_name(resource_class_path, value)['id']
171
214
  end
172
- return l_res_id
173
215
  end
174
216
 
175
217
  def get_resource_path_from_args(resource_class_path)
176
218
  return "#{resource_class_path}/#{get_resource_id_from_args(resource_class_path)}"
177
219
  end
178
220
 
179
- def assert_public_link_types(expected)
180
- raise CliBadArgument, "public link type is #{aoc_api.url_token_data['purpose']} but action requires one of #{expected.join(',')}" \
181
- unless expected.include?(aoc_api.url_token_data['purpose'])
182
- end
183
-
184
221
  # Call aoc_api.read with same parameters.
185
222
  # Use paging if necessary to get all results
186
223
  # @return [Hash] {list: , total: }
@@ -188,10 +225,8 @@ module Aspera
188
225
  raise 'Query must be Hash' unless base_query.is_a?(Hash)
189
226
  # set default large page if user does not specify own parameters. AoC Caps to 1000 anyway
190
227
  base_query['per_page'] = 1000 unless base_query.key?('per_page')
191
- max_items = base_query[MAX_ITEMS]
192
- base_query.delete(MAX_ITEMS)
193
- max_pages = base_query[MAX_PAGES]
194
- base_query.delete(MAX_PAGES)
228
+ max_items = base_query.delete(MAX_ITEMS)
229
+ max_pages = base_query.delete(MAX_PAGES)
195
230
  item_list = []
196
231
  total_count = nil
197
232
  current_page = base_query['page']
@@ -208,9 +243,10 @@ module Aspera
208
243
  break if add_items.empty?
209
244
  # append new items to full list
210
245
  item_list += add_items
211
- break if !max_pages.nil? && page_count > max_pages
212
- break if !max_items.nil? && item_list.count > max_items
246
+ break if !max_items.nil? && item_list.count >= max_items
247
+ break if !max_pages.nil? && page_count >= max_pages
213
248
  end
249
+ item_list = item_list[0..max_items - 1] if !max_items.nil? && item_list.count > max_items
214
250
  return {list: item_list, total: total_count}
215
251
  end
216
252
 
@@ -221,33 +257,32 @@ module Aspera
221
257
  # @param scope [String] node scope, or nil (admin)
222
258
  def execute_nodegen4_command(command_repo, node_id, file_id: nil, scope: nil)
223
259
  top_node_api = aoc_api.node_api_from(
224
- node_id: node_id,
225
- workspace_id: current_workspace_info['id'],
226
- workspace_name: current_workspace_info['name'],
227
- scope: scope
260
+ node_id: node_id,
261
+ workspace_id: aoc_api.context[:workspace_id],
262
+ workspace_name: aoc_api.context[:workspace_name],
263
+ scope: scope
228
264
  )
229
265
  file_id = top_node_api.read("access_keys/#{top_node_api.app_info[:node_info]['access_key']}")[:data]['root_file_id'] if file_id.nil?
230
- node_plugin = Node.new(@agents.merge(
231
- skip_basic_auth_options: true,
232
- skip_node_options: true,
233
- node_api: top_node_api))
266
+ node_plugin = Node.new(@agents, api: top_node_api)
234
267
  case command_repo
235
268
  when *Node::COMMANDS_GEN4
236
269
  return node_plugin.execute_command_gen4(command_repo, file_id)
237
270
  when :transfer
238
271
  # client side is agent
239
- # server side is protocol server
272
+ # server side is transfer server
240
273
  # in same workspace
241
- # default is push
242
- case options.get_option(:operation, mandatory: true)
274
+ push_pull = options.get_next_argument('direction', expected: %i[push pull])
275
+ source_folder = options.get_next_argument('folder of source files', type: String)
276
+ case push_pull
243
277
  when :push
244
278
  client_direction = Fasp::TransferSpec::DIRECTION_SEND
245
- client_folder = options.get_option(:from_folder, mandatory: true)
279
+ client_folder = source_folder
246
280
  server_folder = transfer.destination_folder(client_direction)
247
281
  when :pull
248
282
  client_direction = Fasp::TransferSpec::DIRECTION_RECEIVE
249
283
  client_folder = transfer.destination_folder(client_direction)
250
- server_folder = options.get_option(:from_folder, mandatory: true)
284
+ server_folder = source_folder
285
+ else raise 'internal error'
251
286
  end
252
287
  client_apfid = top_node_api.resolve_api_fid(file_id, client_folder)
253
288
  server_apfid = top_node_api.resolve_api_fid(file_id, server_folder)
@@ -289,7 +324,8 @@ module Aspera
289
324
  end
290
325
  when :subscription
291
326
  org = aoc_api.read('organization')[:data]
292
- bss_api = AoC.new(aoc_params('bss/platform'))
327
+ bss_api = api_from_options('bss/platform')
328
+ # cspell:disable
293
329
  graphql_query = "
294
330
  query ($organization_id: ID!) {
295
331
  aoc (organization_id: $organization_id) {
@@ -338,17 +374,18 @@ module Aspera
338
374
  }
339
375
  }
340
376
  "
377
+ # cspell:enable
341
378
  result = bss_api.create('graphql', {'variables' => {'organization_id' => org['id']}, 'query' => graphql_query})[:data]['data']
342
379
  return {type: :single_object, data: result['aoc']['bssSubscription']}
343
380
  when :ats
344
381
  ats_api = Rest.new(aoc_api.params.deep_merge({
345
- base_url: aoc_api.params[:base_url] + '/admin/ats/pub/v1',
382
+ base_url: "#{aoc_api.params[:base_url]}/admin/ats/pub/v1",
346
383
  auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
347
384
  }))
348
- return Ats.new(@agents.merge(skip_node_options: true)).execute_action_gen(ats_api)
385
+ return Ats.new(@agents).execute_action_gen(ats_api)
349
386
  when :analytics
350
387
  analytics_api = Rest.new(aoc_api.params.deep_merge({
351
- base_url: aoc_api.params[:base_url].gsub('/api/v1', '') + '/analytics/v2',
388
+ base_url: "#{aoc_api.params[:base_url].gsub('/api/v1', '')}/analytics/v2",
352
389
  auth: {scope: AoC::SCOPE_FILES_ADMIN_USER}
353
390
  }))
354
391
  command_analytics = options.get_next_command(%i[application_events transfers])
@@ -359,24 +396,23 @@ module Aspera
359
396
  return {type: :object_list, data: events}
360
397
  when :transfers
361
398
  event_type = command_analytics.to_s
362
- filter_resource = options.get_option(:name) || 'organizations'
363
- filter_id = options.get_option(:id) ||
399
+ filter_resource = options.get_next_argument('resource', expected: %i[organizations users nodes])
400
+ filter_id = options.get_next_argument('identifier', mandatory: false) ||
364
401
  case filter_resource
365
- when 'organizations' then aoc_api.current_user_info['organization_id']
366
- when 'users' then aoc_api.current_user_info['id']
367
- when 'nodes' then aoc_api.current_user_info['id'] # TODO: consistent ? # rubocop:disable Lint/DuplicateBranch
368
- else raise 'organizations or users for option --name'
402
+ when :organizations then aoc_api.current_user_info['organization_id']
403
+ when :users then aoc_api.current_user_info['id']
404
+ when :nodes then aoc_api.current_user_info['id'] # TODO: consistent ? # rubocop:disable Lint/DuplicateBranch
405
+ else raise 'Internal error'
369
406
  end
370
407
  filter = options.get_option(:query) || {}
371
- raise 'query must be Hash' unless filter.is_a?(Hash)
372
408
  filter['limit'] ||= 100
373
409
  if options.get_option(:once_only, mandatory: true)
374
410
  saved_date = []
375
411
  start_date_persistency = PersistencyActionOnce.new(
376
412
  manager: @agents[:persistency],
377
413
  data: saved_date,
378
- ids: IdGenerator.from_list(['aoc_ana_date', options.get_option(:url, mandatory: true), current_workspace_info['name']].push(
379
- filter_resource,
414
+ ids: IdGenerator.from_list(['aoc_ana_date', options.get_option(:url, mandatory: true), aoc_api.context[:workspace_name]].push(
415
+ filter_resource.to_s,
380
416
  filter_id)))
381
417
  start_date_time = saved_date.first
382
418
  stop_date_time = Time.now.utc.strftime('%FT%T.%LZ')
@@ -388,7 +424,7 @@ module Aspera
388
424
  end
389
425
  events = analytics_api.read("#{filter_resource}/#{filter_id}/#{event_type}", query_read_delete(default: filter))[:data][event_type]
390
426
  start_date_persistency&.save
391
- if !options.get_option(:notif_to).nil?
427
+ if !options.get_option(:notify_to).nil?
392
428
  events.each do |tr_event|
393
429
  config.send_email_template(values: {ev: tr_event})
394
430
  end
@@ -404,7 +440,7 @@ module Aspera
404
440
  when :self, :organization then resource_type
405
441
  when :client_registration_token, :client_access_key then "admin/#{resource_type}s"
406
442
  when :application then 'admin/apps_new'
407
- when :dropbox then resource_type.to_s + 'es'
443
+ when :dropbox then "#{resource_type}es"
408
444
  when :kms_profile then "integrations/#{resource_type}s"
409
445
  else "#{resource_type}s"
410
446
  end
@@ -428,9 +464,7 @@ module Aspera
428
464
  id_result = 'token' if resource_class_path.eql?('admin/client_registration_tokens')
429
465
  # TODO: report inconsistency: creation url is !=, and does not return id.
430
466
  resource_class_path = 'admin/client_registration/token' if resource_class_path.eql?('admin/client_registration_tokens')
431
- list_or_one = options.get_next_argument('creation data', type: Hash)
432
- return do_bulk_operation(list_or_one, 'created', id_result: id_result) do |params|
433
- raise 'expecting Hash' unless params.is_a?(Hash)
467
+ return do_bulk_operation(command: command, descr: 'creation data', id_result: id_result) do |params|
434
468
  aoc_api.create(resource_class_path, params)[:data]
435
469
  end
436
470
  when :list
@@ -455,30 +489,34 @@ module Aspera
455
489
  return {type: :object_list, data: items[:list], fields: default_fields}
456
490
  when :show
457
491
  object = aoc_api.read(resource_instance_path)[:data]
492
+ # default: show all, but certificate
458
493
  fields = object.keys.reject{|k|k.eql?('certificate')}
459
494
  return { type: :single_object, data: object, fields: fields }
460
495
  when :modify
461
- changes = options.get_next_argument('modified parameters (hash)')
462
- aoc_api.update(resource_instance_path, changes)
463
- return Main.result_status('modified')
496
+ changes = options.get_next_argument('properties', type: Hash)
497
+ return do_bulk_operation(command: command, descr: 'identifier', values: res_id) do |one_id|
498
+ aoc_api.update("#{resource_class_path}/#{one_id}", changes)
499
+ {'id' => one_id}
500
+ end
464
501
  when :delete
465
- return do_bulk_operation(res_id, 'deleted') do |one_id|
502
+ return do_bulk_operation(command: command, descr: 'identifier', values: res_id) do |one_id|
466
503
  aoc_api.delete("#{resource_class_path}/#{one_id}")
467
504
  {'id' => one_id}
468
505
  end
469
506
  when :set_pub_key
470
507
  # special : reads private and generate public
471
- the_private_key = options.get_next_argument('private_key')
508
+ the_private_key = options.get_next_argument('private_key PEM value', type: String)
472
509
  the_public_key = OpenSSL::PKey::RSA.new(the_private_key).public_key.to_s
473
510
  aoc_api.update(resource_instance_path, {jwt_grant_enabled: true, public_key: the_public_key})
474
511
  return Main.result_success
475
512
  when :do
476
513
  command_repo = options.get_next_command(NODE4_EXT_COMMANDS)
514
+ aoc_api.context(:none)
477
515
  return execute_nodegen4_command(command_repo, res_id)
478
516
  else raise 'unknown command'
479
517
  end
480
518
  when :usage_reports
481
- return {type: :object_list, data: aoc_api.read('usage_reports', {workspace_id: current_workspace_info['id']})[:data]}
519
+ return {type: :object_list, data: aoc_api.read('usage_reports', {workspace_id: aoc_api.context(:none)[:workspace_id]})[:data]}
482
520
  end
483
521
  end
484
522
 
@@ -487,6 +525,15 @@ module Aspera
487
525
 
488
526
  def execute_action
489
527
  command = options.get_next_command(ACTIONS)
528
+ if %i[files packages].include?(command)
529
+ default_flag = ' (default)' if options.get_option(:workspace).eql?(:default)
530
+ app_context = aoc_api.context(command)
531
+ formatter.display_status("Workspace: #{app_context[:workspace_name].to_s.red}#{default_flag}")
532
+ if !aoc_api.private_link.nil?
533
+ folder_name = aoc_api.node_api_from(node_id: app_context[:home_node_id]).read("files/#{app_context[:home_file_id]}")[:data]['name']
534
+ formatter.display_status("Private Folder: #{folder_name}")
535
+ end
536
+ end
490
537
  case command
491
538
  when :reminder
492
539
  # send an email reminder with list of orgs
@@ -510,14 +557,14 @@ module Aspera
510
557
  when :list
511
558
  return {type: :object_list, data: aoc_api.read('workspaces')[:data], fields: %w[id name]}
512
559
  when :current
513
- return { type: :single_object, data: current_workspace_info }
560
+ return { type: :single_object, data: aoc_api.read("workspaces/#{aoc_api.context(:none)[:workspace_id]}")[:data] }
514
561
  end
515
562
  when :profile
516
563
  case options.get_next_command(%i[show modify])
517
564
  when :show
518
565
  return { type: :single_object, data: aoc_api.current_user_info(exception: true) }
519
566
  when :modify
520
- aoc_api.update("users/#{aoc_api.current_user_info(exception: true)['id']}", options.get_next_argument('modified parameters (hash)'))
567
+ aoc_api.update("users/#{aoc_api.current_user_info(exception: true)['id']}", options.get_next_argument('properties', type: Hash))
521
568
  return Main.result_status('modified')
522
569
  end
523
570
  end
@@ -530,25 +577,25 @@ module Aspera
530
577
  query = query_read_delete
531
578
  if query.nil?
532
579
  query = {'embed[]' => 'dropbox', 'aggregate_permissions_by_dropbox' => true, 'sort' => 'dropbox_name'}
533
- query['workspace_id'] = current_workspace_info['id'] unless current_workspace_info['id'].eql?(:undefined)
580
+ query['workspace_id'] = aoc_api.context[:workspace_id] unless aoc_api.context[:workspace_id].eql?(:undefined)
534
581
  end
535
582
  return {type: :object_list, data: aoc_api.read('dropbox_memberships', query)[:data], fields: ['dropbox_id', 'dropbox.name']}
536
583
  when :show
537
584
  return {type: :single_object, data: aoc_api.read(get_resource_path_from_args('dropboxes'), query)[:data]}
538
585
  end
539
586
  when :send
540
- package_data = value_create_modify(command: package_command, type: Hash)
587
+ package_data = value_create_modify(command: package_command)
541
588
  new_user_option = options.get_option(:new_user_option)
542
589
  option_validate = options.get_option(:validate_metadata)
543
590
  # works for both normal usr auth and link auth
544
- package_data['workspace_id'] ||= current_workspace_info['id']
591
+ package_data['workspace_id'] ||= aoc_api.context[:workspace_id]
545
592
 
546
- if !aoc_api.url_token_data.nil?
547
- assert_public_link_types(%w[send_package_to_user send_package_to_dropbox])
548
- box_type = aoc_api.url_token_data['purpose'].split('_').last
549
- package_data['recipients'] = [{'id' => aoc_api.url_token_data['data']["#{box_type}_id"], 'type' => box_type}]
593
+ if !aoc_api.public_link.nil?
594
+ aoc_api.assert_public_link_types(%w[send_package_to_user send_package_to_dropbox])
595
+ box_type = aoc_api.public_link['purpose'].split('_').last
596
+ package_data['recipients'] = [{'id' => aoc_api.public_link['data']["#{box_type}_id"], 'type' => box_type}]
550
597
  # enforce workspace id from link (should be already ok, but in case user wanted to override)
551
- package_data['workspace_id'] = aoc_api.url_token_data['data']['workspace_id']
598
+ package_data['workspace_id'] = aoc_api.public_link['data']['workspace_id']
552
599
  end
553
600
 
554
601
  # transfer may raise an error
@@ -557,22 +604,27 @@ module Aspera
557
604
  # return all info on package (especially package id)
558
605
  return { type: :single_object, data: created_package[:info]}
559
606
  when :recv
560
- if !aoc_api.url_token_data.nil?
561
- assert_public_link_types(['view_received_package'])
562
- options.set_option(:id, aoc_api.url_token_data['data']['package_id'])
607
+ ids_to_download = nil
608
+ if !aoc_api.public_link.nil?
609
+ aoc_api.assert_public_link_types(['view_received_package'])
610
+ # set the package id, it will
611
+ ids_to_download = aoc_api.public_link['data']['package_id']
563
612
  end
564
- # scalar here
565
- ids_to_download = instance_identifier
613
+ # get from command line unless it was a public link
614
+ ids_to_download ||= instance_identifier
566
615
  skip_ids_data = []
567
616
  skip_ids_persistency = nil
568
617
  if options.get_option(:once_only, mandatory: true)
569
618
  skip_ids_persistency = PersistencyActionOnce.new(
570
619
  manager: @agents[:persistency],
571
620
  data: skip_ids_data,
572
- id: IdGenerator.from_list(['aoc_recv', options.get_option(:url, mandatory: true),
573
- current_workspace_info['id']].concat(aoc_api.additional_persistence_ids)))
621
+ id: IdGenerator.from_list(
622
+ ['aoc_recv',
623
+ options.get_option(:url, mandatory: true),
624
+ aoc_api.context[:workspace_id]
625
+ ].concat(aoc_api.additional_persistence_ids)))
574
626
  end
575
- if VAL_ALL.eql?(ids_to_download)
627
+ if ExtendedValue::ALL.eql?(ids_to_download)
576
628
  query = query_read_delete(default: PACKAGE_QUERY_DEFAULT)
577
629
  raise 'option query must be Hash' unless query.is_a?(Hash)
578
630
  if query.key?('dropbox_name')
@@ -581,14 +633,14 @@ module Aspera
581
633
  query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query['dropbox_name'])['id']
582
634
  query.delete('dropbox_name')
583
635
  end
584
- query['workspace_id'] ||= current_workspace_info['id'] unless current_workspace_info['id'].eql?(:undefined)
636
+ query['workspace_id'] ||= aoc_api.context[:workspace_id] unless aoc_api.context[:workspace_id].eql?(:undefined)
585
637
  # get list of packages in inbox
586
638
  package_info = aoc_api.read('packages', query)[:data]
587
639
  # remove from list the ones already downloaded
588
640
  ids_to_download = package_info.map{|e|e['id']}
589
641
  # array here
590
642
  ids_to_download.reject!{|id|skip_ids_data.include?(id)}
591
- end # VAL_ALL
643
+ end # ExtendedValue::ALL
592
644
  # list here
593
645
  ids_to_download = [ids_to_download] unless ids_to_download.is_a?(Array)
594
646
  result_transfer = []
@@ -598,8 +650,8 @@ module Aspera
598
650
  formatter.display_status("downloading package: #{package_info['name']}")
599
651
  package_node_api = aoc_api.node_api_from(
600
652
  node_id: package_info['node_id'],
601
- workspace_id: current_workspace_info['id'],
602
- workspace_name: current_workspace_info['name'],
653
+ workspace_id: aoc_api.context[:workspace_id],
654
+ workspace_name: aoc_api.context[:workspace_name],
603
655
  package_info: package_info)
604
656
  statuses = transfer.start(
605
657
  package_node_api.transfer_spec_gen4(
@@ -616,7 +668,7 @@ module Aspera
616
668
  end
617
669
  return Main.result_transfer_multiple(result_transfer)
618
670
  when :show
619
- package_id = options.get_next_argument('package ID')
671
+ package_id = instance_identifier
620
672
  package_info = aoc_api.read("packages/#{package_id}")[:data]
621
673
  return { type: :single_object, data: package_info }
622
674
  when :list
@@ -629,43 +681,41 @@ module Aspera
629
681
  query['dropbox_id'] = aoc_api.lookup_by_name('dropboxes', query['dropbox_name'])['id']
630
682
  query.delete('dropbox_name')
631
683
  end
632
- if current_workspace_info['id'].eql?(:undefined)
684
+ if aoc_api.context[:workspace_id].eql?(:undefined)
633
685
  display_fields.push('workspace_id')
634
686
  else
635
- query['workspace_id'] ||= current_workspace_info['id']
687
+ query['workspace_id'] ||= aoc_api.context[:workspace_id]
636
688
  end
637
689
  packages = aoc_api.read('packages', query)[:data]
638
690
  return {type: :object_list, data: packages, fields: display_fields}
639
691
  when :delete
640
- list_or_one = instance_identifier
641
- return do_bulk_operation(list_or_one, 'deleted') do |id|
692
+ return do_bulk_operation(command: package_command, descr: 'identifier', values: identifier) do |id|
642
693
  raise 'expecting String identifier' unless id.is_a?(String) || id.is_a?(Integer)
643
694
  aoc_api.delete("packages/#{id}")[:data]
644
695
  end
645
696
  when *Node::NODE4_READ_ACTIONS
646
- package_id = options.get_next_argument('package ID')
697
+ package_id = instance_identifier
647
698
  package_info = aoc_api.read("packages/#{package_id}")[:data]
648
- return execute_nodegen4_command(package_command, package_info['node_id'], file_id: package_info['file_id'], scope: AoC::SCOPE_NODE_USER)
699
+ return execute_nodegen4_command(package_command, package_info['node_id'], file_id: package_info['file_id'], scope: Aspera::Node::SCOPE_USER)
649
700
  end
650
701
  when :files
651
702
  command_repo = options.get_next_command([:short_link].concat(NODE4_EXT_COMMANDS))
652
703
  case command_repo
653
704
  when *NODE4_EXT_COMMANDS
654
- return execute_nodegen4_command(command_repo, home_info[:node_id], file_id: home_info[:file_id], scope: AoC::SCOPE_NODE_USER)
705
+ return execute_nodegen4_command(command_repo, aoc_api.context[:home_node_id], file_id: aoc_api.context[:home_file_id], scope: Aspera::Node::SCOPE_USER)
655
706
  when :short_link
656
- # execute action on AoC API
657
- short_link_command = options.get_next_command(%i[create delete list])
658
- folder_dest = options.get_next_argument('path')
659
707
  link_type = options.get_next_argument('link type', expected: %i[public private])
708
+ short_link_command = options.get_next_command(%i[create delete list])
709
+ folder_dest = options.get_next_argument('path', type: String)
660
710
  home_node_api = aoc_api.node_api_from(
661
- node_id: home_info[:node_id],
662
- workspace_id: current_workspace_info['id'],
663
- workspace_name: current_workspace_info['name'])
664
- shared_apfid = home_node_api.resolve_api_fid(home_info[:file_id], folder_dest)
711
+ node_id: aoc_api.context[:home_node_id],
712
+ workspace_id: aoc_api.context[:workspace_id],
713
+ workspace_name: aoc_api.context[:workspace_name])
714
+ shared_apfid = home_node_api.resolve_api_fid(aoc_api.context[:home_file_id], folder_dest)
665
715
  folder_info = {
666
716
  node_id: shared_apfid[:api].app_info[:node_info]['id'],
667
717
  file_id: shared_apfid[:file_id],
668
- workspace_id: current_workspace_info['id']
718
+ workspace_id: aoc_api.context[:workspace_id]
669
719
  }
670
720
  purpose = case link_type
671
721
  when :public then 'token_auth_redirection'
@@ -699,14 +749,13 @@ module Aspera
699
749
  end
700
750
  list_params = {
701
751
  json_query: query.to_json,
702
- edit_access: true,
703
752
  purpose: purpose,
753
+ edit_access: true,
704
754
  # embed: 'updated_by_user',
705
755
  sort: '-created_at'
706
756
  }
707
757
  result = aoc_api.read('short_links', list_params)[:data]
708
- result.each{|i|i.delete('data')}
709
- return {type: :object_list, data: result}
758
+ return {type: :object_list, data: result, fields: Formatter.all_but('data')}
710
759
  when :create
711
760
  creation_params = {
712
761
  purpose: purpose,
@@ -741,8 +790,8 @@ module Aspera
741
790
  'access_levels' => access_levels,
742
791
  'tags' => {
743
792
  'url_token' => true,
744
- 'workspace_id' => current_workspace_info['id'],
745
- 'workspace_name' => current_workspace_info['name'],
793
+ 'workspace_id' => aoc_api.context[:workspace_id],
794
+ 'workspace_name' => aoc_api.context[:workspace_name],
746
795
  'folder_name' => folder_name,
747
796
  'created_by_name' => aoc_api.current_user_info['name'],
748
797
  'created_by_email' => aoc_api.current_user_info['email'],
@@ -772,7 +821,7 @@ module Aspera
772
821
  wf_command = options.get_next_command(%i[action launch].concat(Plugin::ALL_OPS))
773
822
  case wf_command
774
823
  when *Plugin::ALL_OPS
775
- return entity_command(wf_command, automation_api, 'workflows', id_default: :id)
824
+ return entity_command(wf_command, automation_api, 'workflows')
776
825
  when :launch
777
826
  wf_id = instance_identifier
778
827
  data = automation_api.create("workflows/#{wf_id}/launch", {})[:data]
@@ -794,10 +843,10 @@ module Aspera
794
843
  return execute_admin_action
795
844
  when :gateway
796
845
  require 'aspera/faspex_gw'
797
- url = value_create_modify(type: String)
846
+ url = value_create_modify(command: command, type: String)
798
847
  uri = URI.parse(url)
799
848
  server = WebServerSimple.new(uri)
800
- server.mount(uri.path, Faspex4GWServlet, aoc_api, current_workspace_info['id'])
849
+ server.mount(uri.path, Faspex4GWServlet, aoc_api, aoc_api.context(:none)[:workspace_id])
801
850
  trap('INT') { server.shutdown }
802
851
  formatter.display_status("Faspex 4 gateway listening on #{url}")
803
852
  Log.log.info("Listening on #{url}")
@@ -810,90 +859,7 @@ module Aspera
810
859
  raise 'internal error: command shall return'
811
860
  end
812
861
 
813
- # @param [Hash] params : plugin_sym, instance_url
814
- # @return [Hash] :preset_value, :test_args
815
- def wizard(params)
816
- if params[:prepare]
817
- organization = AoC.parse_url(params[:instance_url]).first
818
- # if not defined by user, generate name
819
- params[:preset_name] ||= [params[:plugin_sym], organization].join('_')
820
- params[:need_private_key] = true
821
- return
822
- end
823
- options.set_option(:private_key, '@file:' + params[:private_key_path])
824
- # make username mandatory for jwt, this triggers interactive input
825
- options.get_option(:username, mandatory: true)
826
- auto_set_pub_key = false
827
- auto_set_jwt = false
828
- use_browser_authentication = false
829
- if options.get_option(:use_generic_client)
830
- formatter.display_status('Using global client_id.')
831
- formatter.display_status('Please Login to your Aspera on Cloud instance.'.red)
832
- formatter.display_status('Navigate to your "Account Settings"'.red)
833
- formatter.display_status('Check or update the value of "Public Key" to be:'.red.blink)
834
- formatter.display_status(params[:pub_key_pem])
835
- if !options.get_option(:test_mode)
836
- formatter.display_status('Once updated or validated, press enter.')
837
- OpenApplication.instance.uri(params[:instance_url])
838
- $stdin.gets
839
- end
840
- else
841
- formatter.display_status('Using organization specific client_id.')
842
- if options.get_option(:client_id).nil? || options.get_option(:client_secret).nil?
843
- formatter.display_status('Please login to your Aspera on Cloud instance.'.red)
844
- formatter.display_status('Go to: Apps->Admin->Organization->Integrations')
845
- formatter.display_status('Create or check if there is an existing integration named:')
846
- formatter.display_status("- name: #{@info[:name]}")
847
- formatter.display_status("- redirect uri: #{DEFAULT_REDIRECT}")
848
- formatter.display_status('- origin: localhost')
849
- formatter.display_status('Once created or identified,')
850
- formatter.display_status('Please enter:'.red)
851
- end
852
- OpenApplication.instance.uri("#{params[:instance_url]}/#{AOC_PATH_API_CLIENTS}")
853
- options.get_option(:client_id, mandatory: true)
854
- options.get_option(:client_secret, mandatory: true)
855
- use_browser_authentication = true
856
- end
857
- if use_browser_authentication
858
- formatter.display_status('We will use web authentication to bootstrap.')
859
- auto_set_pub_key = true
860
- auto_set_jwt = true
861
- aoc_api.oauth.generic_parameters[:grant_method] = :web
862
- aoc_api.oauth.generic_parameters[:scope] = AoC::SCOPE_FILES_ADMIN
863
- aoc_api.oauth.specific_parameters[:redirect_uri] = DEFAULT_REDIRECT
864
- end
865
- myself = aoc_api.read('self')[:data]
866
- if auto_set_pub_key
867
- raise CliError, 'Public key is already set in profile (use --override=yes)' unless myself['public_key'].empty? || option_override
868
- formatter.display_status('Updating profile with new key')
869
- aoc_api.update("users/#{myself['id']}", {'public_key' => params[:pub_key_pem]})
870
- end
871
- if auto_set_jwt
872
- formatter.display_status('Enabling JWT for client')
873
- aoc_api.update("clients/#{options.get_option(:client_id)}", {'jwt_grant_enabled' => true, 'explicit_authorization_required' => false})
874
- end
875
- formatter.display_status("Creating new config preset: #{params[:preset_name]}")
876
- preset_result = {
877
- url: params[:instance_url],
878
- username: myself['email'],
879
- auth: :jwt.to_s,
880
- private_key: '@file:' + params[:private_key_path]
881
- }.stringify_keys
882
- # set only if non nil
883
- %i[client_id client_secret].each do |s|
884
- o = options.get_option(s)
885
- preset_result[s.to_s] = o unless o.nil?
886
- end
887
- return {
888
- preset_value: preset_result,
889
- test_args: "#{params[:plugin_sym]} user profile show"
890
- }
891
- end
892
-
893
- private :aoc_params,
894
- :home_info,
895
- :assert_public_link_types,
896
- :execute_admin_action
862
+ private :execute_admin_action
897
863
  end # AoC
898
864
  end # Plugins
899
865
  end # Cli