UNPKG

@sap/cli-core

Version:

Command-Line Interface (CLI) Core Module

106 lines (105 loc) 5.21 kB
import { SecretsStorageSingleton } from "../cache/secrets/SecretsStorageSingleton.js"; import { getTenantUrl } from "../cache/secrets/utils.js"; import { OPTION_ACCESS_TOKEN, OPTION_AUTHORIZATION_FLOW, OPTION_AUTHORIZATION_URL, OPTION_BROWSER, OPTION_CLIENT_ID, OPTION_CLIENT_SECRET, OPTION_CODE, OPTION_HOST, OPTION_OPTIONS_FILE, OPTION_REFRESH_TOKEN, OPTION_SECRETS_FILE, OPTION_TLS_VERSION, OPTION_TOKEN_URL, OPTION_VERBOSE, ROOT_COMMAND, } from "../constants.js"; import { get } from "../logger/index.js"; import { logVerbose } from "../logger/utils.js"; import { getDefaultBrowser, getSupportedBrowsers } from "../utils/openUtils.js"; import { getOptionValueFromConfig } from "../utils/options.js"; import { buildOptionName } from "../utils/utils.js"; import { init } from "./config.command/cache.command/init.command/index.js"; import { createMandatoryOptionsHandler, createNextHandler, createOauthHandler, createOptionsHandler, createOrHandler, createParseArgumentsHandler, } from "./handler/index.js"; import { promptForValue } from "./handler/options/utils.js"; const getLogger = () => get("commands.login"); export const verifyHost = async () => async () => { const logger = getLogger(); try { const url = getTenantUrl(); logger.debug(`url defined as ${url}`); } catch (err) { logger.error("tenant URL not defined. use option -H, --host"); logVerbose(logger, "specify the tenant URL using option --host"); throw new Error("tenant URL not defined. use option -H, --host"); } }; const confirmSecretsOverwrite = async (tenantUrl) => { const promptResponse = await promptForValue({ prompts: { type: "confirm", message: `Secret for tenant ${tenantUrl} already exists. Do you want to overwrite it?`, initial: true, }, longName: "overwrite-secrets", description: `overwrite existing secrets`, }); return promptResponse; }; const initializeCache = async () => async () => { const { warn, info } = getLogger(); info("initializing cache after successful login"); try { getOptionValueFromConfig(OPTION_HOST); await (await init())(); } catch (err) { warn(`option ${buildOptionName(ROOT_COMMAND, OPTION_HOST)} not defined, skipping cache init`); } }; const fetchSupportedBrowsers = async () => { const list = await getSupportedBrowsers(); return list.map(({ name }) => name); }; const saveSecrets = async () => async () => { await SecretsStorageSingleton.SINGLETON.synchronizeSecretsToStorage(); }; const warnIfSecretExistsInCache = async () => { return async () => { const logger = getLogger(); const tenantUrl = getTenantUrl(); const secretsStorage = SecretsStorageSingleton.SINGLETON; // Default secret is from cache since secrets file and options aren't loaded yet const cachedSecret = await secretsStorage.getDefaultSecret(); if (cachedSecret) { const shouldOverwrite = await confirmSecretsOverwrite(tenantUrl); logger.debug(`user response for overwriting secrets for tenant ${tenantUrl}: ${shouldOverwrite}`); if (!shouldOverwrite) { const message = `Aborted: Secret for tenant ${tenantUrl} already exists and will not be overwritten.`; logger.warn(message); // Stop proceeding with the login process as a secret for the tenant already exists return; } logger.info(`Overwriting existing secret for tenant ${tenantUrl}. Proceeding with login.`); // Remove the cached secret to allow the new one to be created secretsStorage.deleteSecretById(cachedSecret.id); logger.debug(`Existing secret for tenant ${tenantUrl} has been removed.`); } throw new Error(`Login secret for tenant ${tenantUrl} must be loaded.`); }; }; const loginCommand = { type: "command", command: "login", description: "log in to your account using interactive OAuth authentication", options: [], handler: createNextHandler("login.command", createParseArgumentsHandler(), createOptionsHandler([ { ...OPTION_HOST, hidden: false, required: true }, OPTION_VERBOSE, OPTION_OPTIONS_FILE, { ...OPTION_AUTHORIZATION_URL, hidden: false }, { ...OPTION_TOKEN_URL, hidden: false }, { ...OPTION_CLIENT_ID, hidden: false }, { ...OPTION_CLIENT_SECRET, hidden: false }, { ...OPTION_ACCESS_TOKEN, hidden: false }, { ...OPTION_CODE, hidden: false }, { ...OPTION_REFRESH_TOKEN, hidden: false }, { ...OPTION_SECRETS_FILE, hidden: false }, { ...OPTION_TLS_VERSION, hidden: false }, { ...OPTION_BROWSER, choices: fetchSupportedBrowsers, default: getDefaultBrowser, }, { ...OPTION_AUTHORIZATION_FLOW, hidden: false }, ]), createMandatoryOptionsHandler(), verifyHost, createOrHandler("commands.login", warnIfSecretExistsInCache, createNextHandler("commands.login", createOauthHandler(), initializeCache, saveSecrets))), }; export default loginCommand;