@sap/cli-core
Version:
Command-Line Interface (CLI) Core Module
106 lines (105 loc) • 5.21 kB
JavaScript
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;