UNPKG

@zowe/imperative

Version:
214 lines 12.1 kB
"use strict"; /* * This program and the accompanying materials are made available under the terms of the * Eclipse Public License v2.0 which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-v20.html * * SPDX-License-Identifier: EPL-2.0 * * Copyright Contributors to the Zowe Project. * */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseAuthHandler = void 0; const rest_1 = require("../../../../rest"); const error_1 = require("../../../../error"); const utilities_1 = require("../../../../utilities"); const ConfigUtils_1 = require("../../../../config/src/ConfigUtils"); const AbstractAuthHandler_1 = require("./AbstractAuthHandler"); /** * This class is used by the auth command handlers as the base class for their implementation. */ class BaseAuthHandler extends AbstractAuthHandler_1.AbstractAuthHandler { /** * Returns auth handler API that provides convenient functions to create a * session from args, and use it to login or logout of an auth service. */ getAuthHandlerApi() { return { promptParams: { defaultTokenType: this.mDefaultTokenType, serviceDescription: this.mServiceDescription }, createSessCfg: this.createSessCfgFromArgs, sessionLogin: this.doLogin, sessionLogout: this.doLogout }; } /** * Performs the login operation. Builds a session to connect to the auth * service, sends a login request to it to obtain a token, and stores the * resulting token in the profile of type `mProfileType`. * @param {IHandlerParameters} params Command parameters sent by imperative. */ processLogin(params) { return __awaiter(this, void 0, void 0, function* () { const sessCfg = this.createSessCfgFromArgs(params.arguments); const sessCfgWithCreds = yield rest_1.ConnectionPropsForSessCfg.addPropsOrPrompt(sessCfg, params.arguments, { requestToken: true, defaultTokenType: this.mDefaultTokenType, parms: params, autoStore: false }); this.mSession = new rest_1.Session(sessCfgWithCreds); this.mSession.ISession.storeCookie = true; // login to obtain a token. const tokenValue = yield this.doLogin(this.mSession); this.mSession.ISession.storeCookie = false; // validate a token was returned if (tokenValue == null) { throw new error_1.ImperativeError({ msg: "A token value was not returned from the login handler." }); } if (params.arguments.showToken) { // show token instead of updating profile this.showToken(params.response, tokenValue); } else if (utilities_1.ImperativeConfig.instance.config.api.secure.loadFailed) { throw ConfigUtils_1.ConfigUtils.secureSaveError(`Instead of secure storage, ` + `rerun this command with the "--show-token" flag to print the token to console. ` + `Store the token in an environment variable ${utilities_1.ImperativeConfig.instance.loadedConfig.envVariablePrefix}_OPT_TOKEN_VALUE to use it ` + `in future commands.`); } else { // update the profile given // TODO Should config be added to IHandlerParameters? const config = utilities_1.ImperativeConfig.instance.config; const profileName = this.getBaseProfileName(params); const profileProps = Object.keys(config.api.profiles.get(profileName, false)); const profileExists = config.api.profiles.exists(profileName); profileProps.push(...config.api.secure.securePropsForProfile(profileName)); const beforeLayer = config.api.layers.get(); // If base profile is null or empty, prompt user before saving token to disk if (!profileExists) { const ok = yield this.promptForBaseProfile(params, profileName); if (!ok) { this.showToken(params.response, tokenValue); return; } config.api.profiles.set(profileName, { type: this.mProfileType, properties: { host: this.mSession.ISession.hostname, port: this.mSession.ISession.port } }); config.api.profiles.defaultSet(this.mProfileType, profileName); } else { const layer = config.api.layers.find(profileName); if (layer != null) { const { user, global } = layer; config.api.layers.activate(user, global); } } const profilePath = config.api.profiles.getProfilePathFromName(profileName); config.set(`${profilePath}.properties.tokenType`, this.mSession.ISession.tokenType); config.set(`${profilePath}.properties.tokenValue`, tokenValue, { secure: true }); yield config.save(); // Restore original active layer config.api.layers.activate(beforeLayer.user, beforeLayer.global); params.response.console.log(`\n` + `Login successful. The authentication token is stored in the '${profileName}' ` + `${this.mProfileType} profile for future use. To revoke this token and remove it from your profile, review the ` + `'zowe auth logout' command.`); } }); } getBaseProfileName(params) { return ConfigUtils_1.ConfigUtils.getActiveProfileName(this.mProfileType, params.arguments, `${this.mProfileType}`); } promptForBaseProfile(params, profileName) { return __awaiter(this, void 0, void 0, function* () { const answer = yield params.response.console.prompt(`Do you want to store the host, port, and token on disk for use with future commands? If you answer Yes, the credentials will ` + `be saved to a ${this.mProfileType} profile named '${profileName}'. If you answer No, the token will be printed to the ` + `terminal and will not be stored on disk. [y/N]: `); return answer != null && (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes"); }); } showToken(response, tokenValue) { response.console.log(`\n` + `Received a token of type = ${this.mSession.ISession.tokenType}.\n` + `The following token was retrieved and will not be stored in your profile:\n` + `${tokenValue}\n\n` + `Login successful. To revoke this token, review the 'zowe auth logout' command.`); response.data.setObj({ tokenType: this.mSession.ISession.tokenType, tokenValue }); } /** * Performs the logout operation. Deletes the token and token type from the profile, * and rebuilds the session. * @param {IHandlerParameters} params Command parameters sent by imperative. */ processLogout(params) { return __awaiter(this, void 0, void 0, function* () { // Force the use of token value, in case user and/or password are also provided. if (params.arguments.tokenValue != null && (params.arguments.user != null || params.arguments.password != null)) { params.arguments.user = undefined; params.arguments.password = undefined; } if (params.arguments.tokenType == null) { params.arguments.tokenType = this.mDefaultTokenType; } const sessCfg = this.createSessCfgFromArgs(params.arguments); const sessCfgWithCreds = yield rest_1.ConnectionPropsForSessCfg.addPropsOrPrompt(sessCfg, params.arguments, { requestToken: false, doPrompting: false, parms: params }); let logoutError; if (params.arguments.tokenValue != null) { this.mSession = new rest_1.Session(sessCfgWithCreds); try { yield this.doLogout(this.mSession); } catch (err) { logoutError = err; } } const config = utilities_1.ImperativeConfig.instance.config; const profileName = this.getBaseProfileName(params); const profileProps = config.api.profiles.get(profileName, false); let profileWithToken = null; let noDeleteReason = ""; // If you specified a token on the command line, then don't delete the one in the profile if it doesn't match if (Object.keys(profileProps).length > 0 && profileProps.tokenType != null && profileProps.tokenValue != null && profileProps.tokenType === params.arguments.tokenType && profileProps.tokenValue === params.arguments.tokenValue) { const profilePath = config.api.profiles.getProfilePathFromName(profileName); config.delete(`${profilePath}.properties.tokenType`); config.delete(`${profilePath}.properties.tokenValue`); yield config.save(); profileWithToken = profileName; } else { if (Object.keys(profileProps).length === 0) noDeleteReason = "Empty profile was provided."; else if (profileProps.tokenType == null) noDeleteReason = "Token type was not provided."; else if (profileProps.tokenValue == null) noDeleteReason = "Token value was not provided."; else if (profileProps.tokenType !== params.arguments.tokenType) noDeleteReason = "Token type does not match the authentication service"; else if (profileProps.tokenValue !== params.arguments.tokenValue) noDeleteReason = "Token value does not match the securely stored value"; } if (params.arguments.tokenValue != null) { let logoutMessage = "Logout successful. The authentication token has been revoked."; if ((logoutError === null || logoutError === void 0 ? void 0 : logoutError.errorCode) === rest_1.RestConstants.HTTP_STATUS_401.toString()) { logoutMessage = "Token is not valid or expired."; } logoutMessage += `\nToken was${profileWithToken == null ? " not" : ""} removed from ` + `your '${profileName}' ${this.mProfileType} profile.`; logoutMessage += `${!noDeleteReason ? "" : "\nReason: " + noDeleteReason}`; params.response.console.log(logoutMessage); } else { params.response.console.errorHeader("Command Error"); params.response.console.error("Token was not provided, so can't log out." + "\nYou need to authenticate first using `zowe auth login`."); params.response.data.setExitCode(1); } }); } } exports.BaseAuthHandler = BaseAuthHandler; //# sourceMappingURL=BaseAuthHandler.js.map