# frozen_string_literal: true require 'sinatra' require 'launchy' module Chronicle module ETL module CLI # CLI commands for authorizing chronicle-etl with third-party services class Authorizations < SubcommandBase default_task 'new' namespace :authorizations desc 'authorize', 'Authorize with a third-party provider' option :port, desc: 'Port to run authorization server on', type: :numeric, default: 4567 option :credentials, desc: 'Secrets namespace for where to read credentials from (default: PROVIDER)', type: :string, banner: 'NAMESPACE' option :secrets, desc: 'Secrets namespace for where authorization should be saved to (default: PROVIDER)', type: :string, banner: 'NAMESPACE' option :print, desc: 'Show authorization results (instead of just saving secrets)', type: :boolean, default: false def new(provider) authorizer_klass = find_authorizer_klass(provider) credentials = load_credentials(provider: provider, credentials_source: options[:credentials]) authorizer = authorizer_klass.new(port: options[:port], credentials: credentials) secrets = authorizer.authorize! secrets_namespace = options[:secrets] || provider Chronicle::ETL::Secrets.set_all(secrets_namespace, secrets) pp secrets if options[:print] cli_exit(message: "Authorization saved to '#{secrets_namespace}' secrets") rescue StandardError => e cli_fail(message: "Authorization not successful.\n#{e.message}", exception: e) end private def find_authorizer_klass(provider) # TODO: this assumes provider:plugin one-to-one unless Chronicle::ETL::Registry::Plugins.installed?(provider) cli_fail(message: "Plugin for #{provider} is not installed.") end begin Chronicle::ETL::Registry::Plugins.activate(provider) rescue PluginError => e cli_fail(message: "Could not load plugin '#{provider}'.\n" + e.message, exception: e) end Authorizer.find_by_provider(provider.to_sym) || cli_fail(message: "No authorizer available for '#{provider}'") end def load_credentials(provider:, credentials_source: nil) if credentials_source && !Chronicle::ETL::Secrets.exists?(credentials_source) cli_fail(message: "OAuth credentials specified as '#{credentials_source}' but a secrets namespace with that name does not exist.") end Chronicle::ETL::Secrets.read(credentials_source || provider) end end end end end