From f684063675b2688f40e2d6fe5de97e7bb077068e Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Wed, 9 Aug 2023 12:17:22 -0400 Subject: [PATCH 1/6] Initial PoC of auth provider for base profile Signed-off-by: Timothy Johnson --- packages/zowe-explorer/package.json | 6 + .../zowe-explorer/src/ApimlAuthProvider.ts | 187 ++++++++++++++++++ packages/zowe-explorer/src/extension.ts | 2 + 3 files changed, 195 insertions(+) create mode 100644 packages/zowe-explorer/src/ApimlAuthProvider.ts diff --git a/packages/zowe-explorer/package.json b/packages/zowe-explorer/package.json index 506ccb2698..1139bfe2db 100644 --- a/packages/zowe-explorer/package.json +++ b/packages/zowe-explorer/package.json @@ -762,6 +762,12 @@ "command": "zowe.jobs.downloadSingleSpoolBinary", "title": "%downloadSingleSpoolBinary%", "category": "Zowe Explorer" + }, + { + "command": "zowe.apimlLogin", + "title": "Log in to API Mediation Layer", + "category": "Zowe Explorer", + "icon": "$(sign-in)" } ], "menus": { diff --git a/packages/zowe-explorer/src/ApimlAuthProvider.ts b/packages/zowe-explorer/src/ApimlAuthProvider.ts new file mode 100644 index 0000000000..cc9482e4c2 --- /dev/null +++ b/packages/zowe-explorer/src/ApimlAuthProvider.ts @@ -0,0 +1,187 @@ +/** + * 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. + * + */ + +/* eslint-disable */ +import * as url from "url"; +import { + authentication, + AuthenticationProvider, + AuthenticationProviderAuthenticationSessionsChangeEvent, + AuthenticationSession, + commands, + Disposable, + EventEmitter, + ExtensionContext, + window, +} from "vscode"; +import * as zowe from "@zowe/cli"; +import { Gui } from "@zowe/zowe-explorer-api"; +import { Profiles } from "./Profiles"; + +export class ApimlAuthenticationProvider implements AuthenticationProvider, Disposable { + private _disposable: Disposable; + private _sessionChangeEmitter = new EventEmitter(); + + public static readonly authId = "zoweapiml"; + public static readonly authName = "Zowe API ML"; + + public constructor(private readonly context: ExtensionContext) { + this._disposable = Disposable.from( + authentication.registerAuthenticationProvider(ApimlAuthenticationProvider.authId, ApimlAuthenticationProvider.authName, this, { + supportsMultipleAccounts: false, + }), + authentication.onDidChangeSessions(async (e) => { + if (e.provider.id === ApimlAuthenticationProvider.authId) { + // TODO handle session added/removed/changed + } + }), + commands.registerCommand("zowe.apimlLogin", async () => { + await this.createSession([]); + }) + ); + } + + public static async getApimlSession(): Promise { + const session = await authentication.getSession(ApimlAuthenticationProvider.authId, [], { createIfNone: false }); + if (session) { + window.showInformationMessage(`Welcome back ${session.account.label}`); + } + } + + public get onDidChangeSessions() { + return this._sessionChangeEmitter.event; + } + + public async getSessions(scopes?: string[]): Promise { + const allSessions: AuthenticationSession[] = []; + const profiles = Profiles.getInstance(); + for (const baseProfile of await profiles.fetchAllProfilesByType("base")) { + if (baseProfile.profile.tokenType === zowe.imperative.SessConstants.TOKEN_TYPE_APIML && baseProfile.profile.tokenValue != null) { + allSessions.push({ + id: `${baseProfile.name}_${baseProfile.type}`, + accessToken: baseProfile.profile.tokenValue, + account: { + label: baseProfile.name, + id: baseProfile.profile.tokenType, + }, + scopes: [], + }); + } + } + return allSessions; + } + + public async createSession(scopes: string[]): Promise { + const profiles = Profiles.getInstance(); + const baseProfile = await profiles.fetchBaseProfile(); + const defaultApimlUrlStr = "https://" + (baseProfile.profile.host || "example.com") + ":" + (baseProfile.profile.port || 7554).toString(); + const apimlUrlStr = await Gui.showInputBox({ + prompt: "Enter the URL for your API ML instance:", + value: defaultApimlUrlStr, + }); + if (apimlUrlStr == null) { + return Promise.reject(); + } + const apimlUrl = new url.URL(apimlUrlStr); + baseProfile.profile.host = apimlUrl.hostname; + baseProfile.profile.port = parseInt(apimlUrl.port); + const apimlUser = await Gui.showInputBox({ + prompt: "Enter the username for your API ML instance:", + value: baseProfile.profile.user, + }); + if (apimlUser == null) { + return Promise.reject(); + } + const apimlPass = await Gui.showInputBox({ + prompt: "Enter the password for your API ML instance:", + value: baseProfile.profile.password, + password: true, + }); + if (apimlPass == null) { + return Promise.reject(); + } + const apimlSession = new zowe.imperative.Session({ + hostname: baseProfile.profile.host, + port: baseProfile.profile.port, + user: apimlUser, + password: apimlPass, + rejectUnauthorized: baseProfile.profile.rejectUnauthorized, + tokenType: zowe.imperative.SessConstants.TOKEN_TYPE_APIML, + type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, + }); + const tokenValue = await zowe.Login.apimlLogin(apimlSession); + baseProfile.profile.tokenType = apimlSession.ISession.tokenType; + baseProfile.profile.tokenValue = apimlSession.ISession.tokenValue; + try { + const profInfo = await profiles.getProfileInfo(); + for (const property of Object.keys(baseProfile.profile)) { + await profInfo.updateProperty({ + profileType: baseProfile.type, + profileName: baseProfile.name, + property, + value: baseProfile.profile[property], + }); + } + } catch (err) { + window.showErrorMessage(err.stack); + return; + } + const session: AuthenticationSession = { + id: `${baseProfile.name}_${baseProfile.type}`, + accessToken: tokenValue, + account: { + label: baseProfile.name, + id: apimlSession.ISession.tokenType, + }, + scopes: [], + }; + this._sessionChangeEmitter.fire({ added: [session], removed: [], changed: [] }); + return session; + } + + public async removeSession(sessionId: string): Promise { + const session = (await this.getSessions()).find((s) => s.id === sessionId); + const profiles = Profiles.getInstance(); + const baseProfile = await profiles.fetchBaseProfile(); + const apimlSession = new zowe.imperative.Session({ + hostname: baseProfile.profile.host, + port: baseProfile.profile.port, + rejectUnauthorized: baseProfile.profile.rejectUnauthorized, + tokenType: baseProfile.profile.tokenType, + tokenValue: baseProfile.profile.tokenValue, + type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, + }); + await zowe.Logout.apimlLogout(apimlSession); + try { + const profInfo = await profiles.getProfileInfo(); + await profInfo.updateProperty({ + profileType: baseProfile.type, + profileName: baseProfile.name, + property: "tokenValue", + value: undefined, + }); + } catch (err) { + window.showErrorMessage(err.stack); + return; + } + this._sessionChangeEmitter.fire({ added: [], removed: [session], changed: [] }); + } + + public dispose() { + this._disposable.dispose(); + } + + public async login(session: zowe.imperative.Session): Promise { + return ""; + } + + public async logout(session: zowe.imperative.Session): Promise {} +} diff --git a/packages/zowe-explorer/src/extension.ts b/packages/zowe-explorer/src/extension.ts index ae87926932..b28a729ecc 100644 --- a/packages/zowe-explorer/src/extension.ts +++ b/packages/zowe-explorer/src/extension.ts @@ -26,6 +26,7 @@ import { IZoweProviders, registerCommonCommands, registerRefreshCommand, watchCo import { ZoweLogger } from "./utils/LoggerUtils"; import { ZoweSaveQueue } from "./abstract/ZoweSaveQueue"; import { PollDecorator } from "./utils/DecorationProviders"; +import { ApimlAuthenticationProvider } from "./ApimlAuthProvider"; /** * The function that runs when the extension is loaded @@ -59,6 +60,7 @@ export async function activate(context: vscode.ExtensionContext): Promise Date: Wed, 9 Aug 2023 17:08:25 -0400 Subject: [PATCH 2/6] Move context menu items into quickpick Signed-off-by: Timothy Johnson --- packages/zowe-explorer/package.json | 36 ------------------- .../zowe-explorer/src/ApimlAuthProvider.ts | 11 ------ .../zowe-explorer/src/utils/ProfilesUtils.ts | 10 +++++- 3 files changed, 9 insertions(+), 48 deletions(-) diff --git a/packages/zowe-explorer/package.json b/packages/zowe-explorer/package.json index 1139bfe2db..bce298c8be 100644 --- a/packages/zowe-explorer/package.json +++ b/packages/zowe-explorer/package.json @@ -762,12 +762,6 @@ "command": "zowe.jobs.downloadSingleSpoolBinary", "title": "%downloadSingleSpoolBinary%", "category": "Zowe Explorer" - }, - { - "command": "zowe.apimlLogin", - "title": "Log in to API Mediation Layer", - "category": "Zowe Explorer", - "icon": "$(sign-in)" } ], "menus": { @@ -949,16 +943,6 @@ "command": "zowe.promptCredentials", "group": "098_zowe_ussProfileAuthentication@3" }, - { - "when": "view == zowe.uss.explorer && viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", - "command": "zowe.uss.ssoLogin", - "group": "098_zowe_ussProfileAuthentication@4" - }, - { - "when": "view == zowe.uss.explorer && viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", - "command": "zowe.uss.ssoLogout", - "group": "098_zowe_ussProfileAuthentication@5" - }, { "when": "viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", "command": "zowe.uss.editSession", @@ -1159,16 +1143,6 @@ "command": "zowe.promptCredentials", "group": "098_zowe_dsProfileAuthentication@8" }, - { - "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", - "command": "zowe.ds.ssoLogin", - "group": "098_zowe_dsProfileAuthentication@9" - }, - { - "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", - "command": "zowe.ds.ssoLogout", - "group": "098_zowe_dsProfileAuthentication@10" - }, { "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", "command": "zowe.ds.editSession", @@ -1324,16 +1298,6 @@ "command": "zowe.promptCredentials", "group": "098_zowe_jobsProfileAuthentication@5" }, - { - "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", - "command": "zowe.jobs.ssoLogin", - "group": "098_zowe_jobsProfileAuthentication@6" - }, - { - "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", - "command": "zowe.jobs.ssoLogout", - "group": "098_zowe_jobsProfileAuthentication@7" - }, { "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", "command": "zowe.jobs.editSession", diff --git a/packages/zowe-explorer/src/ApimlAuthProvider.ts b/packages/zowe-explorer/src/ApimlAuthProvider.ts index cc9482e4c2..b82a4196aa 100644 --- a/packages/zowe-explorer/src/ApimlAuthProvider.ts +++ b/packages/zowe-explorer/src/ApimlAuthProvider.ts @@ -16,7 +16,6 @@ import { AuthenticationProvider, AuthenticationProviderAuthenticationSessionsChangeEvent, AuthenticationSession, - commands, Disposable, EventEmitter, ExtensionContext, @@ -42,20 +41,10 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp if (e.provider.id === ApimlAuthenticationProvider.authId) { // TODO handle session added/removed/changed } - }), - commands.registerCommand("zowe.apimlLogin", async () => { - await this.createSession([]); }) ); } - public static async getApimlSession(): Promise { - const session = await authentication.getSession(ApimlAuthenticationProvider.authId, [], { createIfNone: false }); - if (session) { - window.showInformationMessage(`Welcome back ${session.account.label}`); - } - } - public get onDidChangeSessions() { return this._sessionChangeEmitter.event; } diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index c7d6911a01..fe80001c2e 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -23,6 +23,7 @@ import { imperative, getImperativeConfig } from "@zowe/cli"; import { ZoweExplorerExtender } from "../ZoweExplorerExtender"; import { ZoweLogger } from "./LoggerUtils"; import { SettingsConfig } from "./SettingsConfig"; +import { ApimlAuthenticationProvider } from "../ApimlAuthProvider"; // Set up localization nls.config({ @@ -329,7 +330,14 @@ export class ProfilesUtils { } } - const creds = await Profiles.getInstance().promptCredentials(profile, true); + const authTypeOptions = ["User and password", "Auth token"]; + const authType = await Gui.showQuickPick(authTypeOptions, { title: "Select an authentication method" }); + let creds; + if (authType === authTypeOptions[0]) { + creds = await Profiles.getInstance().promptCredentials(profile, true); + } else if (authType === authTypeOptions[1]) { + creds = await vscode.authentication.getSession(ApimlAuthenticationProvider.authId, [], { forceNewSession: true }); + } if (creds != null) { const successMsg = localize( From 0dd9137766a4ff8e33d97749447d74bff1b3093e Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Thu, 10 Aug 2023 19:33:42 -0400 Subject: [PATCH 3/6] Fix extender support for logging in/out of profile Signed-off-by: Timothy Johnson --- packages/zowe-explorer/package.json | 36 +++--- .../zowe-explorer/src/ApimlAuthProvider.ts | 11 +- packages/zowe-explorer/src/Profiles.ts | 104 +++++++++--------- packages/zowe-explorer/src/extension.ts | 2 +- .../zowe-explorer/src/utils/ProfilesUtils.ts | 37 ++++--- 5 files changed, 104 insertions(+), 86 deletions(-) diff --git a/packages/zowe-explorer/package.json b/packages/zowe-explorer/package.json index bce298c8be..398087b8d5 100644 --- a/packages/zowe-explorer/package.json +++ b/packages/zowe-explorer/package.json @@ -929,18 +929,18 @@ "group": "099_zowe_ussModification:@4" }, { - "when": "view == zowe.uss.explorer && viewItem =~ /_validate/ && !listMultiSelection", - "command": "zowe.uss.disableValidation", + "when": "view == zowe.uss.explorer && viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", + "command": "zowe.promptCredentials", "group": "098_zowe_ussProfileAuthentication@1" }, { - "when": "view == zowe.uss.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", - "command": "zowe.uss.enableValidation", + "when": "view == zowe.uss.explorer && viewItem =~ /_validate/ && !listMultiSelection", + "command": "zowe.uss.disableValidation", "group": "098_zowe_ussProfileAuthentication@2" }, { - "when": "view == zowe.uss.explorer && viewItem =~ /^(?!.*_fav.*)ussSession.*/ && !listMultiSelection", - "command": "zowe.promptCredentials", + "when": "view == zowe.uss.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", + "command": "zowe.uss.enableValidation", "group": "098_zowe_ussProfileAuthentication@3" }, { @@ -1129,18 +1129,18 @@ "group": "099_zowe_dsModification@5" }, { - "when": "view == zowe.ds.explorer && viewItem =~ /_validate/ && !listMultiSelection", - "command": "zowe.ds.disableValidation", + "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", + "command": "zowe.promptCredentials", "group": "098_zowe_dsProfileAuthentication@6" }, { - "when": "view == zowe.ds.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", - "command": "zowe.ds.enableValidation", + "when": "view == zowe.ds.explorer && viewItem =~ /_validate/ && !listMultiSelection", + "command": "zowe.ds.disableValidation", "group": "098_zowe_dsProfileAuthentication@7" }, { - "when": "view == zowe.ds.explorer && viewItem =~ /^(?!.*_fav.*)session.*/ && !listMultiSelection", - "command": "zowe.promptCredentials", + "when": "view == zowe.ds.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", + "command": "zowe.ds.enableValidation", "group": "098_zowe_dsProfileAuthentication@8" }, { @@ -1284,18 +1284,18 @@ "group": "099_zowe_jobsModification" }, { - "when": "view == zowe.jobs.explorer && viewItem =~ /_validate/ && !listMultiSelection", - "command": "zowe.jobs.disableValidation", + "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", + "command": "zowe.promptCredentials", "group": "098_zowe_jobsProfileAuthentication@3" }, { - "when": "view == zowe.jobs.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", - "command": "zowe.jobs.enableValidation", + "when": "view == zowe.jobs.explorer && viewItem =~ /_validate/ && !listMultiSelection", + "command": "zowe.jobs.disableValidation", "group": "098_zowe_jobsProfileAuthentication@4" }, { - "when": "view == zowe.jobs.explorer && viewItem =~ /^(?!.*_fav.*)server.*/ && !listMultiSelection", - "command": "zowe.promptCredentials", + "when": "view == zowe.jobs.explorer && viewItem =~ /_noValidate/ && !listMultiSelection", + "command": "zowe.jobs.enableValidation", "group": "098_zowe_jobsProfileAuthentication@5" }, { diff --git a/packages/zowe-explorer/src/ApimlAuthProvider.ts b/packages/zowe-explorer/src/ApimlAuthProvider.ts index b82a4196aa..d6d8f8ff6b 100644 --- a/packages/zowe-explorer/src/ApimlAuthProvider.ts +++ b/packages/zowe-explorer/src/ApimlAuthProvider.ts @@ -18,7 +18,6 @@ import { AuthenticationSession, Disposable, EventEmitter, - ExtensionContext, window, } from "vscode"; import * as zowe from "@zowe/cli"; @@ -28,11 +27,12 @@ import { Profiles } from "./Profiles"; export class ApimlAuthenticationProvider implements AuthenticationProvider, Disposable { private _disposable: Disposable; private _sessionChangeEmitter = new EventEmitter(); + private static mInstance: ApimlAuthenticationProvider; public static readonly authId = "zoweapiml"; public static readonly authName = "Zowe API ML"; - public constructor(private readonly context: ExtensionContext) { + private constructor() { this._disposable = Disposable.from( authentication.registerAuthenticationProvider(ApimlAuthenticationProvider.authId, ApimlAuthenticationProvider.authName, this, { supportsMultipleAccounts: false, @@ -45,6 +45,13 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp ); } + public static get instance(): ApimlAuthenticationProvider { + if (this.mInstance == null) { + this.mInstance = new ApimlAuthenticationProvider(); + } + return this.mInstance; + } + public get onDidChangeSessions() { return this._sessionChangeEmitter.event; } diff --git a/packages/zowe-explorer/src/Profiles.ts b/packages/zowe-explorer/src/Profiles.ts index fbda781b9e..a42987e1ff 100644 --- a/packages/zowe-explorer/src/Profiles.ts +++ b/packages/zowe-explorer/src/Profiles.ts @@ -37,6 +37,7 @@ import * as globals from "./globals"; import * as nls from "vscode-nls"; import { SettingsConfig } from "./utils/SettingsConfig"; import { ZoweLogger } from "./utils/LoggerUtils"; +import { ApimlAuthenticationProvider } from "./ApimlAuthProvider"; // Set up localization nls.config({ @@ -1191,41 +1192,42 @@ export class Profiles extends ProfilesCache { return; } } else { - const baseProfile = await this.fetchBaseProfile(); - if (baseProfile) { - creds = await this.loginCredentialPrompt(); - if (!creds) { - return; - } - try { - const updSession = new zowe.imperative.Session({ - hostname: serviceProfile.profile.host, - port: serviceProfile.profile.port, - user: creds[0], - password: creds[1], - rejectUnauthorized: serviceProfile.profile.rejectUnauthorized, - tokenType: loginTokenType, - type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, - }); - loginToken = await ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).login(updSession); - const updBaseProfile: zowe.imperative.IProfile = { - tokenType: loginTokenType, - tokenValue: loginToken, - }; - await this.updateBaseProfileFileLogin(baseProfile, updBaseProfile); - const baseIndex = this.allProfiles.findIndex((profile) => profile.name === baseProfile.name); - this.allProfiles[baseIndex] = { ...baseProfile, profile: { ...baseProfile.profile, ...updBaseProfile } }; - node.setProfileToChoice({ - ...node.getProfile(), - profile: { ...node.getProfile().profile, ...updBaseProfile }, - }); - } catch (error) { - const errMsg = localize("ssoLogin.unableToLogin", "Unable to log in with {0}. {1}", serviceProfile.name, error?.message); - ZoweLogger.error(errMsg); - Gui.errorMessage(errMsg); - return; - } - } + await vscode.authentication.getSession(ApimlAuthenticationProvider.authId, [], { forceNewSession: true }); + // const baseProfile = await this.fetchBaseProfile(); + // if (baseProfile) { + // creds = await this.loginCredentialPrompt(); + // if (!creds) { + // return; + // } + // try { + // const updSession = new zowe.imperative.Session({ + // hostname: serviceProfile.profile.host, + // port: serviceProfile.profile.port, + // user: creds[0], + // password: creds[1], + // rejectUnauthorized: serviceProfile.profile.rejectUnauthorized, + // tokenType: loginTokenType, + // type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, + // }); + // loginToken = await ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).login(updSession); + // const updBaseProfile: zowe.imperative.IProfile = { + // tokenType: loginTokenType, + // tokenValue: loginToken, + // }; + // await this.updateBaseProfileFileLogin(baseProfile, updBaseProfile); + // const baseIndex = this.allProfiles.findIndex((profile) => profile.name === baseProfile.name); + // this.allProfiles[baseIndex] = { ...baseProfile, profile: { ...baseProfile.profile, ...updBaseProfile } }; + // node.setProfileToChoice({ + // ...node.getProfile(), + // profile: { ...node.getProfile().profile, ...updBaseProfile }, + // }); + // } catch (error) { + // const errMsg = localize("ssoLogin.unableToLogin", "Unable to log in with {0}. {1}", serviceProfile.name, error?.message); + // ZoweLogger.error(errMsg); + // Gui.errorMessage(errMsg); + // return; + // } + // } } Gui.showMessage(localize("ssoLogin.successful", "Login to authentication service was successful.")); } @@ -1245,20 +1247,24 @@ export class Profiles extends ProfilesCache { .getCommonApi(serviceProfile) .logout(await node.getSession()); } else { - // this will handle base profile apiml tokens - const baseProfile = await this.fetchBaseProfile(); - const loginTokenType = ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).getTokenTypeName(); - const updSession = new zowe.imperative.Session({ - hostname: serviceProfile.profile.host, - port: serviceProfile.profile.port, - rejectUnauthorized: serviceProfile.profile.rejectUnauthorized, - tokenType: loginTokenType, - tokenValue: serviceProfile.profile.tokenValue, - type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, - }); - await ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).logout(updSession); - - await this.updateBaseProfileFileLogout(baseProfile); + const apimlSession = await vscode.authentication.getSession(ApimlAuthenticationProvider.authId, []); + if (apimlSession != null) { + await ApimlAuthenticationProvider.instance.removeSession(apimlSession.id); + } + // // this will handle base profile apiml tokens + // const baseProfile = await this.fetchBaseProfile(); + // const loginTokenType = ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).getTokenTypeName(); + // const updSession = new zowe.imperative.Session({ + // hostname: serviceProfile.profile.host, + // port: serviceProfile.profile.port, + // rejectUnauthorized: serviceProfile.profile.rejectUnauthorized, + // tokenType: loginTokenType, + // tokenValue: serviceProfile.profile.tokenValue, + // type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, + // }); + // await ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).logout(updSession); + + // await this.updateBaseProfileFileLogout(baseProfile); } Gui.showMessage(localize("ssoLogout.successful", "Logout from authentication service was successful for {0}.", serviceProfile.name)); } catch (error) { diff --git a/packages/zowe-explorer/src/extension.ts b/packages/zowe-explorer/src/extension.ts index b28a729ecc..b7454464de 100644 --- a/packages/zowe-explorer/src/extension.ts +++ b/packages/zowe-explorer/src/extension.ts @@ -60,7 +60,7 @@ export async function activate(context: vscode.ExtensionContext): Promise Date: Fri, 11 Aug 2023 17:36:28 -0400 Subject: [PATCH 4/6] Test support for multiple linked APIML profiles Signed-off-by: Timothy Johnson --- .../src/profiles/ProfilesCache.ts | 18 ++++++++++++++++-- .../i18n/sample/package.i18n.json | 2 +- packages/zowe-explorer/package.nls.json | 2 +- .../zowe-explorer/src/ApimlAuthProvider.ts | 14 ++++++++------ packages/zowe-explorer/src/Profiles.ts | 6 ++++-- .../zowe-explorer/src/utils/ProfilesUtils.ts | 13 ++++++------- 6 files changed, 36 insertions(+), 19 deletions(-) diff --git a/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts b/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts index ca57331240..82dc1ce44f 100644 --- a/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts +++ b/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts @@ -377,9 +377,14 @@ export class ProfilesCache { } // This will retrieve the base profile from imperative - public async fetchBaseProfile(): Promise { + public async fetchBaseProfile(profileName?: string): Promise { const mProfileInfo = await this.getProfileInfo(); - const baseProfileAttrs = mProfileInfo.getDefaultProfile("base"); + let baseProfileAttrs: zowe.imperative.IProfAttrs; + if (profileName == null) { + baseProfileAttrs = mProfileInfo.getDefaultProfile("base"); + } else { + baseProfileAttrs = mProfileInfo.getAllProfiles("base").find((p) => p.profName === profileName); + } if (baseProfileAttrs == null) { return undefined; } @@ -499,6 +504,15 @@ export class ProfilesCache { for (const arg of mergedArgs.knownArgs) { profile[arg.argName] = arg.argValue; } + if (profile.apimlProfile != null) { + const apimlProfAttrs = mProfileInfo.getAllProfiles("base").find((p) => p.profName === profile.apimlProfile); + if (apimlProfAttrs != null) { + const apimlMergedArgs = mProfileInfo.mergeArgsForProfile(apimlProfAttrs, { getSecureVals: true }); + for (const arg of apimlMergedArgs.knownArgs) { + profile[arg.argName] = arg.argValue; + } + } + } } return profile; } diff --git a/packages/zowe-explorer/i18n/sample/package.i18n.json b/packages/zowe-explorer/i18n/sample/package.i18n.json index a33832f610..27e9fb497a 100644 --- a/packages/zowe-explorer/i18n/sample/package.i18n.json +++ b/packages/zowe-explorer/i18n/sample/package.i18n.json @@ -2,7 +2,7 @@ "displayName": "Zowe Explorer", "description": "VS Code extension, powered by Zowe CLI, that streamlines interaction with mainframe data sets, USS files, and jobs", "viewsContainers.activitybar": "Zowe Explorer", - "zowe.promptCredentials": "Update Credentials", + "zowe.promptCredentials": "Manage Credentials", "zowe.extRefresh": "Refresh Zowe Explorer", "zowe.ds.explorer": "Data Sets", "zowe.uss.explorer": "Unix System Services (USS)", diff --git a/packages/zowe-explorer/package.nls.json b/packages/zowe-explorer/package.nls.json index a33832f610..27e9fb497a 100644 --- a/packages/zowe-explorer/package.nls.json +++ b/packages/zowe-explorer/package.nls.json @@ -2,7 +2,7 @@ "displayName": "Zowe Explorer", "description": "VS Code extension, powered by Zowe CLI, that streamlines interaction with mainframe data sets, USS files, and jobs", "viewsContainers.activitybar": "Zowe Explorer", - "zowe.promptCredentials": "Update Credentials", + "zowe.promptCredentials": "Manage Credentials", "zowe.extRefresh": "Refresh Zowe Explorer", "zowe.ds.explorer": "Data Sets", "zowe.uss.explorer": "Unix System Services (USS)", diff --git a/packages/zowe-explorer/src/ApimlAuthProvider.ts b/packages/zowe-explorer/src/ApimlAuthProvider.ts index d6d8f8ff6b..b63f813a09 100644 --- a/packages/zowe-explorer/src/ApimlAuthProvider.ts +++ b/packages/zowe-explorer/src/ApimlAuthProvider.ts @@ -66,9 +66,9 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp accessToken: baseProfile.profile.tokenValue, account: { label: baseProfile.name, - id: baseProfile.profile.tokenType, + id: `${baseProfile.name}_${baseProfile.profile.tokenType}`, }, - scopes: [], + scopes: [baseProfile.name], }); } } @@ -76,8 +76,9 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp } public async createSession(scopes: string[]): Promise { + const profileName = scopes[0]; const profiles = Profiles.getInstance(); - const baseProfile = await profiles.fetchBaseProfile(); + const baseProfile = await profiles.fetchBaseProfile(profileName); const defaultApimlUrlStr = "https://" + (baseProfile.profile.host || "example.com") + ":" + (baseProfile.profile.port || 7554).toString(); const apimlUrlStr = await Gui.showInputBox({ prompt: "Enter the URL for your API ML instance:", @@ -135,9 +136,9 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp accessToken: tokenValue, account: { label: baseProfile.name, - id: apimlSession.ISession.tokenType, + id: `${baseProfile.name}_${apimlSession.ISession.tokenType}`, }, - scopes: [], + scopes, }; this._sessionChangeEmitter.fire({ added: [session], removed: [], changed: [] }); return session; @@ -145,8 +146,9 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp public async removeSession(sessionId: string): Promise { const session = (await this.getSessions()).find((s) => s.id === sessionId); + const profileName = session.scopes[0]; const profiles = Profiles.getInstance(); - const baseProfile = await profiles.fetchBaseProfile(); + const baseProfile = await profiles.fetchBaseProfile(profileName); const apimlSession = new zowe.imperative.Session({ hostname: baseProfile.profile.host, port: baseProfile.profile.port, diff --git a/packages/zowe-explorer/src/Profiles.ts b/packages/zowe-explorer/src/Profiles.ts index a42987e1ff..d32093a5e4 100644 --- a/packages/zowe-explorer/src/Profiles.ts +++ b/packages/zowe-explorer/src/Profiles.ts @@ -1192,7 +1192,8 @@ export class Profiles extends ProfilesCache { return; } } else { - await vscode.authentication.getSession(ApimlAuthenticationProvider.authId, [], { forceNewSession: true }); + const apimlProfileName = serviceProfile.profile.apimlProfile ?? "base"; + await vscode.authentication.getSession(ApimlAuthenticationProvider.authId, [apimlProfileName], { forceNewSession: true }); // const baseProfile = await this.fetchBaseProfile(); // if (baseProfile) { // creds = await this.loginCredentialPrompt(); @@ -1247,7 +1248,8 @@ export class Profiles extends ProfilesCache { .getCommonApi(serviceProfile) .logout(await node.getSession()); } else { - const apimlSession = await vscode.authentication.getSession(ApimlAuthenticationProvider.authId, []); + const apimlProfileName = serviceProfile.profile.apimlProfile ?? "base"; + const apimlSession = await vscode.authentication.getSession(ApimlAuthenticationProvider.authId, [apimlProfileName]); if (apimlSession != null) { await ApimlAuthenticationProvider.instance.removeSession(apimlSession.id); } diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index 18434f0634..9c7fe817f5 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -330,12 +330,11 @@ export class ProfilesUtils { } } - const authTypeOptions: vscode.QuickPickItem[] = [ - { label: "User and Password" }, - { label: "Authentication Token" }, - globals.SEPARATORS.BLANK, - { label: "Log out of Authentication Service" }, - ]; + const hasTokenValue = typeof profile === "string" || profile.profile?.tokenValue != null; + const authTypeOptions: vscode.QuickPickItem[] = [{ label: "User and Password" }, { label: "Authentication Token" }]; + if (hasTokenValue) { + authTypeOptions.push(globals.SEPARATORS.BLANK, { label: "Log out of Authentication Service" }); + } const authType = await Gui.showQuickPick(authTypeOptions, { title: "Select an authentication method" }); if (authType === authTypeOptions[0]) { const creds = await Profiles.getInstance().promptCredentials(profile, true); @@ -352,7 +351,7 @@ export class ProfilesUtils { } } else if (authType === authTypeOptions[1]) { await Profiles.getInstance().ssoLogin(node); - } else if (authType === authTypeOptions[3]) { + } else if (hasTokenValue && authType === authTypeOptions[3]) { await Profiles.getInstance().ssoLogout(node); } } From 57b7327ea622fefc28131e089e72f00c0ed518e6 Mon Sep 17 00:00:00 2001 From: Timothy Johnson Date: Mon, 14 Aug 2023 17:58:09 -0400 Subject: [PATCH 5/6] Refactor auth provider to integrate with Profiles API Signed-off-by: Timothy Johnson --- .../src/profiles/ProfilesCache.ts | 18 +- .../zowe-explorer/src/ApimlAuthProvider.ts | 219 +++++++++--------- packages/zowe-explorer/src/Profiles.ts | 124 +++++----- packages/zowe-explorer/src/extension.ts | 2 - packages/zowe-explorer/src/shared/init.ts | 3 + 5 files changed, 182 insertions(+), 184 deletions(-) diff --git a/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts b/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts index 82dc1ce44f..c314107531 100644 --- a/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts +++ b/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts @@ -504,15 +504,15 @@ export class ProfilesCache { for (const arg of mergedArgs.knownArgs) { profile[arg.argName] = arg.argValue; } - if (profile.apimlProfile != null) { - const apimlProfAttrs = mProfileInfo.getAllProfiles("base").find((p) => p.profName === profile.apimlProfile); - if (apimlProfAttrs != null) { - const apimlMergedArgs = mProfileInfo.mergeArgsForProfile(apimlProfAttrs, { getSecureVals: true }); - for (const arg of apimlMergedArgs.knownArgs) { - profile[arg.argName] = arg.argValue; - } - } - } + // if (profile.apimlProfile != null) { + // const apimlProfAttrs = mProfileInfo.getAllProfiles("base").find((p) => p.profName === profile.apimlProfile); + // if (apimlProfAttrs != null) { + // const apimlMergedArgs = mProfileInfo.mergeArgsForProfile(apimlProfAttrs, { getSecureVals: true }); + // for (const arg of apimlMergedArgs.knownArgs) { + // profile[arg.argName] = arg.argValue; + // } + // } + // } } return profile; } diff --git a/packages/zowe-explorer/src/ApimlAuthProvider.ts b/packages/zowe-explorer/src/ApimlAuthProvider.ts index b63f813a09..444228cb05 100644 --- a/packages/zowe-explorer/src/ApimlAuthProvider.ts +++ b/packages/zowe-explorer/src/ApimlAuthProvider.ts @@ -9,38 +9,31 @@ * */ -/* eslint-disable */ -import * as url from "url"; import { authentication, AuthenticationProvider, AuthenticationProviderAuthenticationSessionsChangeEvent, AuthenticationSession, Disposable, + Event, EventEmitter, - window, } from "vscode"; import * as zowe from "@zowe/cli"; -import { Gui } from "@zowe/zowe-explorer-api"; import { Profiles } from "./Profiles"; export class ApimlAuthenticationProvider implements AuthenticationProvider, Disposable { private _disposable: Disposable; private _sessionChangeEmitter = new EventEmitter(); + private _sessionCache: AuthenticationSession[]; private static mInstance: ApimlAuthenticationProvider; - public static readonly authId = "zoweapiml"; + public static readonly authId = "zowe.apiml"; public static readonly authName = "Zowe API ML"; private constructor() { this._disposable = Disposable.from( authentication.registerAuthenticationProvider(ApimlAuthenticationProvider.authId, ApimlAuthenticationProvider.authName, this, { supportsMultipleAccounts: false, - }), - authentication.onDidChangeSessions(async (e) => { - if (e.provider.id === ApimlAuthenticationProvider.authId) { - // TODO handle session added/removed/changed - } }) ); } @@ -52,134 +45,136 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp return this.mInstance; } - public get onDidChangeSessions() { - return this._sessionChangeEmitter.event; + public async checkForUpdates(): Promise { + const oldSessions: AuthenticationSession[] = JSON.parse(JSON.stringify(this._sessionCache)); + const newSessions = await this.getSessions(); + const added: AuthenticationSession[] = []; + const removed: AuthenticationSession[] = []; + const changed: AuthenticationSession[] = []; + for (const sessionId of new Set(...oldSessions.map((session) => session.id), ...this._sessionCache.map((session) => session.id))) { + const oldSession = oldSessions.find((session) => session.id === sessionId); + const newSession = newSessions.find((session) => session.id === sessionId); + if (oldSession == null && newSession != null) { + added.push(newSession); + } else if (oldSession != null && newSession == null) { + removed.push(newSession); + } else if (oldSession.accessToken !== newSession.accessToken) { + changed.push(newSession); + } + } + this._sessionChangeEmitter.fire({ added, removed, changed }); } - public async getSessions(scopes?: string[]): Promise { - const allSessions: AuthenticationSession[] = []; - const profiles = Profiles.getInstance(); - for (const baseProfile of await profiles.fetchAllProfilesByType("base")) { - if (baseProfile.profile.tokenType === zowe.imperative.SessConstants.TOKEN_TYPE_APIML && baseProfile.profile.tokenValue != null) { - allSessions.push({ - id: `${baseProfile.name}_${baseProfile.type}`, - accessToken: baseProfile.profile.tokenValue, - account: { - label: baseProfile.name, - id: `${baseProfile.name}_${baseProfile.profile.tokenType}`, - }, - scopes: [baseProfile.name], - }); - } + public async login(profileName: string, loginSession: zowe.imperative.Session): Promise { + const session = await this.createSession([profileName], loginSession); + return { + tokenType: loginSession.ISession.tokenType, + tokenValue: session.accessToken, + }; + } + + public async logout(profileName: string, logoutSession: zowe.imperative.Session): Promise { + const apimlSession = this._sessionCache.find((session) => session.scopes[0] === profileName); + if (apimlSession != null) { + await this.removeSession(apimlSession.id, logoutSession); } - return allSessions; } - public async createSession(scopes: string[]): Promise { + public get onDidChangeSessions(): Event { + return this._sessionChangeEmitter.event; + } + + public async getSessions(_scopes?: string[]): Promise { + await this.updateSessionCache(); + return this._sessionCache; + } + + public async createSession(scopes: string[], loginSession?: zowe.imperative.Session): Promise { const profileName = scopes[0]; const profiles = Profiles.getInstance(); const baseProfile = await profiles.fetchBaseProfile(profileName); - const defaultApimlUrlStr = "https://" + (baseProfile.profile.host || "example.com") + ":" + (baseProfile.profile.port || 7554).toString(); - const apimlUrlStr = await Gui.showInputBox({ - prompt: "Enter the URL for your API ML instance:", - value: defaultApimlUrlStr, - }); - if (apimlUrlStr == null) { - return Promise.reject(); - } - const apimlUrl = new url.URL(apimlUrlStr); - baseProfile.profile.host = apimlUrl.hostname; - baseProfile.profile.port = parseInt(apimlUrl.port); - const apimlUser = await Gui.showInputBox({ - prompt: "Enter the username for your API ML instance:", - value: baseProfile.profile.user, - }); - if (apimlUser == null) { - return Promise.reject(); - } - const apimlPass = await Gui.showInputBox({ - prompt: "Enter the password for your API ML instance:", - value: baseProfile.profile.password, - password: true, - }); - if (apimlPass == null) { - return Promise.reject(); - } - const apimlSession = new zowe.imperative.Session({ - hostname: baseProfile.profile.host, - port: baseProfile.profile.port, - user: apimlUser, - password: apimlPass, - rejectUnauthorized: baseProfile.profile.rejectUnauthorized, - tokenType: zowe.imperative.SessConstants.TOKEN_TYPE_APIML, - type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, - }); - const tokenValue = await zowe.Login.apimlLogin(apimlSession); - baseProfile.profile.tokenType = apimlSession.ISession.tokenType; - baseProfile.profile.tokenValue = apimlSession.ISession.tokenValue; - try { - const profInfo = await profiles.getProfileInfo(); - for (const property of Object.keys(baseProfile.profile)) { - await profInfo.updateProperty({ - profileType: baseProfile.type, - profileName: baseProfile.name, - property, - value: baseProfile.profile[property], - }); + if (loginSession == null) { + const creds = await profiles.loginCredentialPrompt(); + if (!creds) { + return Promise.reject(); } - } catch (err) { - window.showErrorMessage(err.stack); - return; + loginSession = new zowe.imperative.Session({ + hostname: baseProfile.profile.host, + port: baseProfile.profile.port, + user: creds[0], + password: creds[1], + rejectUnauthorized: baseProfile.profile.rejectUnauthorized, + tokenType: zowe.imperative.SessConstants.TOKEN_TYPE_APIML, + type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, + }); } - const session: AuthenticationSession = { - id: `${baseProfile.name}_${baseProfile.type}`, - accessToken: tokenValue, - account: { - label: baseProfile.name, - id: `${baseProfile.name}_${apimlSession.ISession.tokenType}`, - }, - scopes, + const profileProps: zowe.imperative.IProfile = { + tokenType: loginSession.ISession.tokenType, + tokenValue: await zowe.Login.apimlLogin(loginSession), }; - this._sessionChangeEmitter.fire({ added: [session], removed: [], changed: [] }); + await profiles.updateBaseProfileFileLogin(baseProfile, profileProps); + const baseIndex = profiles.allProfiles.findIndex((profile) => profile.name === baseProfile.name); + profiles.allProfiles[baseIndex] = { ...baseProfile, profile: { ...baseProfile.profile, ...profileProps } }; + const session = this.buildSession(profiles.allProfiles[baseIndex]); + if (this._sessionCache.find((s) => s.id === session.id) == null) { + this._sessionChangeEmitter.fire({ added: [session], removed: [], changed: [] }); + } else { + this._sessionChangeEmitter.fire({ added: [], removed: [], changed: [session] }); + } return session; } - public async removeSession(sessionId: string): Promise { - const session = (await this.getSessions()).find((s) => s.id === sessionId); + public async removeSession(sessionId: string, logoutSession?: zowe.imperative.Session): Promise { + const session = this._sessionCache.find((s) => s.id === sessionId); const profileName = session.scopes[0]; const profiles = Profiles.getInstance(); const baseProfile = await profiles.fetchBaseProfile(profileName); - const apimlSession = new zowe.imperative.Session({ - hostname: baseProfile.profile.host, - port: baseProfile.profile.port, - rejectUnauthorized: baseProfile.profile.rejectUnauthorized, - tokenType: baseProfile.profile.tokenType, - tokenValue: baseProfile.profile.tokenValue, - type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, - }); - await zowe.Logout.apimlLogout(apimlSession); - try { - const profInfo = await profiles.getProfileInfo(); - await profInfo.updateProperty({ - profileType: baseProfile.type, - profileName: baseProfile.name, - property: "tokenValue", - value: undefined, + if (logoutSession == null) { + logoutSession = new zowe.imperative.Session({ + hostname: baseProfile.profile.host, + port: baseProfile.profile.port, + rejectUnauthorized: baseProfile.profile.rejectUnauthorized, + tokenType: baseProfile.profile.tokenType, + tokenValue: baseProfile.profile.tokenValue, + type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, }); + } + try { + await zowe.Logout.apimlLogout(logoutSession); } catch (err) { - window.showErrorMessage(err.stack); - return; + if ( + !(err instanceof zowe.imperative.ImperativeError) || + (err.errorCode as unknown as number) !== zowe.imperative.RestConstants.HTTP_STATUS_401 + ) { + throw err; + } } + await profiles.updateBaseProfileFileLogout(baseProfile); this._sessionChangeEmitter.fire({ added: [], removed: [session], changed: [] }); } - public dispose() { + public dispose(): void { this._disposable.dispose(); } - public async login(session: zowe.imperative.Session): Promise { - return ""; + private buildSession(profile: zowe.imperative.IProfileLoaded): AuthenticationSession { + return { + id: `${profile.name}_${profile.type}`, + accessToken: profile.profile.tokenValue, + account: { + label: profile.name, + id: `${profile.name}_${profile.profile.tokenType as string}`, + }, + scopes: [profile.name], + }; } - public async logout(session: zowe.imperative.Session): Promise {} + private async updateSessionCache(): Promise { + this._sessionCache = []; + for (const baseProfile of await Profiles.getInstance().fetchAllProfilesByType("base")) { + if (baseProfile.profile.tokenType === zowe.imperative.SessConstants.TOKEN_TYPE_APIML && baseProfile.profile.tokenValue != null) { + this._sessionCache.push(this.buildSession(baseProfile)); + } + } + } } diff --git a/packages/zowe-explorer/src/Profiles.ts b/packages/zowe-explorer/src/Profiles.ts index d32093a5e4..89dc58ee28 100644 --- a/packages/zowe-explorer/src/Profiles.ts +++ b/packages/zowe-explorer/src/Profiles.ts @@ -1141,7 +1141,6 @@ export class Profiles extends ProfilesCache { public async ssoLogin(node?: IZoweNodeType, label?: string): Promise { ZoweLogger.trace("Profiles.ssoLogin called."); - let loginToken: string; let loginTokenType: string; let creds: string[]; let serviceProfile: zowe.imperative.IProfileLoaded; @@ -1178,7 +1177,7 @@ export class Profiles extends ProfilesCache { session.ISession.user = creds[0]; session.ISession.password = creds[1]; try { - loginToken = await ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).login(session); + await ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).login(session); const profIndex = this.allProfiles.findIndex((profile) => profile.name === serviceProfile.name); this.allProfiles[profIndex] = { ...serviceProfile, profile: { ...serviceProfile, ...session } }; node.setProfileToChoice({ @@ -1192,43 +1191,34 @@ export class Profiles extends ProfilesCache { return; } } else { - const apimlProfileName = serviceProfile.profile.apimlProfile ?? "base"; - await vscode.authentication.getSession(ApimlAuthenticationProvider.authId, [apimlProfileName], { forceNewSession: true }); - // const baseProfile = await this.fetchBaseProfile(); - // if (baseProfile) { - // creds = await this.loginCredentialPrompt(); - // if (!creds) { - // return; - // } - // try { - // const updSession = new zowe.imperative.Session({ - // hostname: serviceProfile.profile.host, - // port: serviceProfile.profile.port, - // user: creds[0], - // password: creds[1], - // rejectUnauthorized: serviceProfile.profile.rejectUnauthorized, - // tokenType: loginTokenType, - // type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, - // }); - // loginToken = await ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).login(updSession); - // const updBaseProfile: zowe.imperative.IProfile = { - // tokenType: loginTokenType, - // tokenValue: loginToken, - // }; - // await this.updateBaseProfileFileLogin(baseProfile, updBaseProfile); - // const baseIndex = this.allProfiles.findIndex((profile) => profile.name === baseProfile.name); - // this.allProfiles[baseIndex] = { ...baseProfile, profile: { ...baseProfile.profile, ...updBaseProfile } }; - // node.setProfileToChoice({ - // ...node.getProfile(), - // profile: { ...node.getProfile().profile, ...updBaseProfile }, - // }); - // } catch (error) { - // const errMsg = localize("ssoLogin.unableToLogin", "Unable to log in with {0}. {1}", serviceProfile.name, error?.message); - // ZoweLogger.error(errMsg); - // Gui.errorMessage(errMsg); - // return; - // } - // } + const apimlProfileName = await this.getApimlProfileName(serviceProfile); + if (apimlProfileName != null) { + creds = await this.loginCredentialPrompt(); + if (!creds) { + return; + } + try { + const updSession = new zowe.imperative.Session({ + hostname: serviceProfile.profile.host, + port: serviceProfile.profile.port, + user: creds[0], + password: creds[1], + rejectUnauthorized: serviceProfile.profile.rejectUnauthorized, + tokenType: loginTokenType, + type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, + }); + const updBaseProfile = await ApimlAuthenticationProvider.instance.login(apimlProfileName, updSession); + node.setProfileToChoice({ + ...node.getProfile(), + profile: { ...node.getProfile().profile, ...updBaseProfile }, + }); + } catch (error) { + const errMsg = localize("ssoLogin.unableToLogin", "Unable to log in with {0}. {1}", serviceProfile.name, error?.message); + ZoweLogger.error(errMsg); + Gui.errorMessage(errMsg); + return; + } + } } Gui.showMessage(localize("ssoLogin.successful", "Login to authentication service was successful.")); } @@ -1248,25 +1238,18 @@ export class Profiles extends ProfilesCache { .getCommonApi(serviceProfile) .logout(await node.getSession()); } else { - const apimlProfileName = serviceProfile.profile.apimlProfile ?? "base"; - const apimlSession = await vscode.authentication.getSession(ApimlAuthenticationProvider.authId, [apimlProfileName]); - if (apimlSession != null) { - await ApimlAuthenticationProvider.instance.removeSession(apimlSession.id); - } - // // this will handle base profile apiml tokens - // const baseProfile = await this.fetchBaseProfile(); - // const loginTokenType = ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).getTokenTypeName(); - // const updSession = new zowe.imperative.Session({ - // hostname: serviceProfile.profile.host, - // port: serviceProfile.profile.port, - // rejectUnauthorized: serviceProfile.profile.rejectUnauthorized, - // tokenType: loginTokenType, - // tokenValue: serviceProfile.profile.tokenValue, - // type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, - // }); - // await ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).logout(updSession); - - // await this.updateBaseProfileFileLogout(baseProfile); + // this will handle base profile apiml tokens + const apimlProfileName = await this.getApimlProfileName(serviceProfile); + const loginTokenType = ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).getTokenTypeName(); + const updSession = new zowe.imperative.Session({ + hostname: serviceProfile.profile.host, + port: serviceProfile.profile.port, + rejectUnauthorized: serviceProfile.profile.rejectUnauthorized, + tokenType: loginTokenType, + tokenValue: serviceProfile.profile.tokenValue, + type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, + }); + await ApimlAuthenticationProvider.instance.logout(apimlProfileName, updSession); } Gui.showMessage(localize("ssoLogout.successful", "Logout from authentication service was successful for {0}.", serviceProfile.name)); } catch (error) { @@ -1283,6 +1266,25 @@ export class Profiles extends ProfilesCache { await Gui.showTextDocument(document); } + /** + * Look for a base profile where APIML token can be stored for SSO login. + * @param profile Imperative loaded profile object + * @returns Name of base profile to store APIML token + */ + private async getApimlProfileName(profile: zowe.imperative.IProfileLoaded): Promise { + // if (profile.profile?.apimlProfile != null) { + // return profile.profile.apimlProfile as string; + // } + if ((await this.getProfileInfo()).usingTeamConfig && profile.name.includes(".")) { + for (const baseProfile of await this.fetchAllProfilesByType("base")) { + if (profile.name.startsWith(baseProfile.name + ".")) { + return baseProfile.name; + } + } + } + return (await this.fetchBaseProfile())?.name; + } + private async getConfigLocationPrompt(action: string): Promise { ZoweLogger.trace("Profiles.getConfigLocationPrompt called."); let placeHolderText: string; @@ -1369,7 +1371,7 @@ export class Profiles extends ProfilesCache { return ret; } - private async updateBaseProfileFileLogin(profile: zowe.imperative.IProfileLoaded, updProfile: zowe.imperative.IProfile): Promise { + public async updateBaseProfileFileLogin(profile: zowe.imperative.IProfileLoaded, updProfile: zowe.imperative.IProfile): Promise { ZoweLogger.trace("Profiles.updateBaseProfileFileLogin called."); const upd = { profileName: profile.name, profileType: profile.type }; const mProfileInfo = await this.getProfileInfo(); @@ -1378,7 +1380,7 @@ export class Profiles extends ProfilesCache { await mProfileInfo.updateProperty({ ...upd, property: "tokenValue", value: updProfile.tokenValue, setSecure }); } - private async updateBaseProfileFileLogout(profile: zowe.imperative.IProfileLoaded): Promise { + public async updateBaseProfileFileLogout(profile: zowe.imperative.IProfileLoaded): Promise { ZoweLogger.trace("Profiles.updateBaseProfileFileLogout called."); const mProfileInfo = await this.getProfileInfo(); const setSecure = mProfileInfo.isSecured(); @@ -1388,7 +1390,7 @@ export class Profiles extends ProfilesCache { await mProfileInfo.updateKnownProperty({ mergedArgs, property: "tokenType", value: undefined }); } - private async loginCredentialPrompt(): Promise { + public async loginCredentialPrompt(): Promise { ZoweLogger.trace("Profiles.loginCredentialPrompt called."); let newPass: string; const newUser = await this.userInfo(); diff --git a/packages/zowe-explorer/src/extension.ts b/packages/zowe-explorer/src/extension.ts index b7454464de..ae87926932 100644 --- a/packages/zowe-explorer/src/extension.ts +++ b/packages/zowe-explorer/src/extension.ts @@ -26,7 +26,6 @@ import { IZoweProviders, registerCommonCommands, registerRefreshCommand, watchCo import { ZoweLogger } from "./utils/LoggerUtils"; import { ZoweSaveQueue } from "./abstract/ZoweSaveQueue"; import { PollDecorator } from "./utils/DecorationProviders"; -import { ApimlAuthenticationProvider } from "./ApimlAuthProvider"; /** * The function that runs when the extension is loaded @@ -60,7 +59,6 @@ export async function activate(context: vscode.ExtensionContext): Promise Date: Tue, 15 Aug 2023 12:13:45 -0400 Subject: [PATCH 6/6] Fix circular deps and bugs found in demo Signed-off-by: Timothy Johnson --- .../src/profiles/ProfilesCache.ts | 42 +++++++--- .../zowe-explorer/src/ApimlAuthProvider.ts | 80 +++++++++---------- packages/zowe-explorer/src/Profiles.ts | 62 +++++--------- packages/zowe-explorer/src/extension.ts | 3 +- packages/zowe-explorer/src/shared/init.ts | 7 +- 5 files changed, 98 insertions(+), 96 deletions(-) diff --git a/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts b/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts index c314107531..83c4e893ad 100644 --- a/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts +++ b/packages/zowe-explorer-api/src/profiles/ProfilesCache.ts @@ -196,7 +196,7 @@ export class ProfilesCache { this.allTypes.push(type); } // check for proper merging of apiml tokens - this.checkMergingConfigAllProfiles(); + await this.checkMergingConfigAllProfiles(); this.profilesForValidation = []; } catch (error) { this.log.error(error as string); @@ -284,7 +284,7 @@ export class ProfilesCache { for (const prof of profilesForType) { const profAttr = this.getMergedAttrs(mProfileInfo, prof); let profile = this.getProfileLoaded(prof.profName, prof.profType, profAttr); - profile = this.checkMergingConfigSingleProfile(profile); + profile = await this.checkMergingConfigSingleProfile(profile); profByType.push(profile); } } @@ -458,14 +458,14 @@ export class ProfilesCache { } // used by refresh to check correct merging of allProfiles - protected checkMergingConfigAllProfiles(): void { - const baseProfile = this.defaultProfileByType.get("base"); + protected async checkMergingConfigAllProfiles(): Promise { const allProfiles: zowe.imperative.IProfileLoaded[] = []; - this.allTypes.forEach((type) => { + for (const type of this.allTypes) { try { const allProfilesByType: zowe.imperative.IProfileLoaded[] = []; const profByType = this.profilesByType.get(type); - profByType.forEach((profile) => { + for (const profile of profByType) { + const baseProfile = await this.findApimlProfile(profile); if (this.shouldRemoveTokenFromProfile(profile, baseProfile)) { profile.profile.tokenType = undefined; profile.profile.tokenValue = undefined; @@ -476,20 +476,20 @@ export class ProfilesCache { } allProfiles.push(profile); allProfilesByType.push(profile); - }); + } this.profilesByType.set(type, allProfilesByType); } catch (error) { // do nothing, skip if profile type is not included in config file this.log.debug(error as string); } - }); + } this.allProfiles = []; this.allProfiles.push(...allProfiles); } // check correct merging of a single profile - protected checkMergingConfigSingleProfile(profile: zowe.imperative.IProfileLoaded): zowe.imperative.IProfileLoaded { - const baseProfile = this.defaultProfileByType.get("base"); + protected async checkMergingConfigSingleProfile(profile: zowe.imperative.IProfileLoaded): Promise { + const baseProfile = await this.findApimlProfile(profile); if (this.shouldRemoveTokenFromProfile(profile, baseProfile)) { profile.profile.tokenType = undefined; profile.profile.tokenValue = undefined; @@ -517,6 +517,25 @@ export class ProfilesCache { return profile; } + /** + * Look for a base profile where APIML token can be stored for SSO login. + * @param profile Imperative loaded profile object + * @returns Base profile to store APIML token + */ + public async findApimlProfile(profile: zowe.imperative.IProfileLoaded): Promise { + // if (profile.profile?.apimlProfile != null) { + // return profile.profile.apimlProfile as string; + // } + if ((await this.getProfileInfo()).usingTeamConfig && profile.name.includes(".")) { + for (const baseProfile of await this.fetchAllProfilesByType("base")) { + if (profile.name.startsWith(baseProfile.name + ".")) { + return baseProfile; + } + } + } + return this.fetchBaseProfile(); + } + // create an array that includes registered types from apiRegister.registeredApiTypes() // and allExternalTypes private getAllProfileTypes(registeredTypes: string[]): string[] { @@ -532,7 +551,8 @@ export class ProfilesCache { profile?.profile?.host && profile?.profile?.port && (baseProfile?.profile.host !== profile?.profile.host || baseProfile?.profile.port !== profile?.profile.port) && - profile?.profile.tokenType === zowe.imperative.SessConstants.TOKEN_TYPE_APIML + profile?.type !== zowe.ProfileConstants.BaseProfile.type && + (profile?.profile.tokenType as string)?.startsWith(zowe.imperative.SessConstants.TOKEN_TYPE_APIML) ); } } diff --git a/packages/zowe-explorer/src/ApimlAuthProvider.ts b/packages/zowe-explorer/src/ApimlAuthProvider.ts index 444228cb05..0c65955517 100644 --- a/packages/zowe-explorer/src/ApimlAuthProvider.ts +++ b/packages/zowe-explorer/src/ApimlAuthProvider.ts @@ -51,9 +51,9 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp const added: AuthenticationSession[] = []; const removed: AuthenticationSession[] = []; const changed: AuthenticationSession[] = []; - for (const sessionId of new Set(...oldSessions.map((session) => session.id), ...this._sessionCache.map((session) => session.id))) { - const oldSession = oldSessions.find((session) => session.id === sessionId); - const newSession = newSessions.find((session) => session.id === sessionId); + for (const sessionId of new Set([...oldSessions.map((s) => s.id), ...newSessions.map((s) => s.id)])) { + const oldSession = oldSessions.find((s) => s.id === sessionId); + const newSession = newSessions.find((s) => s.id === sessionId); if (oldSession == null && newSession != null) { added.push(newSession); } else if (oldSession != null && newSession == null) { @@ -62,21 +62,25 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp changed.push(newSession); } } - this._sessionChangeEmitter.fire({ added, removed, changed }); + if (added || removed || changed) { + this._sessionChangeEmitter.fire({ added, removed, changed }); + } } - public async login(profileName: string, loginSession: zowe.imperative.Session): Promise { - const session = await this.createSession([profileName], loginSession); - return { - tokenType: loginSession.ISession.tokenType, - tokenValue: session.accessToken, - }; + public async login(profile: zowe.imperative.IProfileLoaded): Promise<[string, string]> { + const apimlProfile = await Profiles.getInstance().findApimlProfile(profile); + if (apimlProfile != null) { + const session = await this.createSession([apimlProfile.name], profile.profile); + const loginTokenType = session.account.id.slice(session.account.id.indexOf(zowe.imperative.SessConstants.TOKEN_TYPE_APIML)); + return [loginTokenType, session.accessToken]; + } } - public async logout(profileName: string, logoutSession: zowe.imperative.Session): Promise { - const apimlSession = this._sessionCache.find((session) => session.scopes[0] === profileName); + public async logout(profile: zowe.imperative.IProfileLoaded): Promise { + const apimlProfile = await Profiles.getInstance().findApimlProfile(profile); + const apimlSession = this._sessionCache.find((session) => session.scopes[0] === apimlProfile.name); if (apimlSession != null) { - await this.removeSession(apimlSession.id, logoutSession); + await this.removeSession(apimlSession.id, profile.profile); } } @@ -89,25 +93,23 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp return this._sessionCache; } - public async createSession(scopes: string[], loginSession?: zowe.imperative.Session): Promise { + public async createSession(scopes: string[], loginProps?: zowe.imperative.IProfile): Promise { const profileName = scopes[0]; const profiles = Profiles.getInstance(); const baseProfile = await profiles.fetchBaseProfile(profileName); - if (loginSession == null) { - const creds = await profiles.loginCredentialPrompt(); - if (!creds) { - return Promise.reject(); - } - loginSession = new zowe.imperative.Session({ - hostname: baseProfile.profile.host, - port: baseProfile.profile.port, - user: creds[0], - password: creds[1], - rejectUnauthorized: baseProfile.profile.rejectUnauthorized, - tokenType: zowe.imperative.SessConstants.TOKEN_TYPE_APIML, - type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, - }); + const creds = await profiles.loginCredentialPrompt(); + if (!creds) { + return Promise.reject(); } + const loginSession = new zowe.imperative.Session({ + hostname: (loginProps ?? baseProfile.profile).host, + port: (loginProps ?? baseProfile.profile).port, + user: creds[0], + password: creds[1], + rejectUnauthorized: (loginProps ?? baseProfile.profile).rejectUnauthorized, + tokenType: zowe.imperative.SessConstants.TOKEN_TYPE_APIML, + type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, + }); const profileProps: zowe.imperative.IProfile = { tokenType: loginSession.ISession.tokenType, tokenValue: await zowe.Login.apimlLogin(loginSession), @@ -124,21 +126,19 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp return session; } - public async removeSession(sessionId: string, logoutSession?: zowe.imperative.Session): Promise { + public async removeSession(sessionId: string, logoutProps?: zowe.imperative.IProfile): Promise { const session = this._sessionCache.find((s) => s.id === sessionId); const profileName = session.scopes[0]; const profiles = Profiles.getInstance(); const baseProfile = await profiles.fetchBaseProfile(profileName); - if (logoutSession == null) { - logoutSession = new zowe.imperative.Session({ - hostname: baseProfile.profile.host, - port: baseProfile.profile.port, - rejectUnauthorized: baseProfile.profile.rejectUnauthorized, - tokenType: baseProfile.profile.tokenType, - tokenValue: baseProfile.profile.tokenValue, - type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, - }); - } + const logoutSession = new zowe.imperative.Session({ + hostname: (logoutProps ?? baseProfile.profile).host, + port: (logoutProps ?? baseProfile.profile).port, + rejectUnauthorized: (logoutProps ?? baseProfile.profile).rejectUnauthorized, + tokenType: (logoutProps ?? baseProfile.profile).tokenType, + tokenValue: (logoutProps ?? baseProfile.profile).tokenValue, + type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, + }); try { await zowe.Logout.apimlLogout(logoutSession); } catch (err) { @@ -172,7 +172,7 @@ export class ApimlAuthenticationProvider implements AuthenticationProvider, Disp private async updateSessionCache(): Promise { this._sessionCache = []; for (const baseProfile of await Profiles.getInstance().fetchAllProfilesByType("base")) { - if (baseProfile.profile.tokenType === zowe.imperative.SessConstants.TOKEN_TYPE_APIML && baseProfile.profile.tokenValue != null) { + if (baseProfile.profile.tokenType?.startsWith(zowe.imperative.SessConstants.TOKEN_TYPE_APIML) && baseProfile.profile.tokenValue != null) { this._sessionCache.push(this.buildSession(baseProfile)); } } diff --git a/packages/zowe-explorer/src/Profiles.ts b/packages/zowe-explorer/src/Profiles.ts index 89dc58ee28..ada3b9403c 100644 --- a/packages/zowe-explorer/src/Profiles.ts +++ b/packages/zowe-explorer/src/Profiles.ts @@ -37,7 +37,6 @@ import * as globals from "./globals"; import * as nls from "vscode-nls"; import { SettingsConfig } from "./utils/SettingsConfig"; import { ZoweLogger } from "./utils/LoggerUtils"; -import { ApimlAuthenticationProvider } from "./ApimlAuthProvider"; // Set up localization nls.config({ @@ -47,10 +46,15 @@ nls.config({ const localize: nls.LocalizeFunc = nls.loadMessageBundle(); let InputBoxOptions: vscode.InputBoxOptions; +interface IAuthProvider { + login: (profile: zowe.imperative.IProfileLoaded) => Promise<[string, string]>; + logout: (profile: zowe.imperative.IProfileLoaded) => Promise; +} + export class Profiles extends ProfilesCache { // Processing stops if there are no profiles detected - public static async createInstance(log: zowe.imperative.Logger): Promise { - Profiles.loader = new Profiles(log, vscode.workspace.workspaceFolders?.[0]?.uri.fsPath); + public static async createInstance(log: zowe.imperative.Logger, authProvider: IAuthProvider): Promise { + Profiles.loader = new Profiles(log, vscode.workspace.workspaceFolders?.[0]?.uri.fsPath, authProvider); await Profiles.loader.refresh(ZoweExplorerApiRegister.getInstance()); return Profiles.loader; } @@ -69,7 +73,7 @@ export class Profiles extends ProfilesCache { private jobsSchema: string = globals.SETTINGS_JOBS_HISTORY; private mProfileInfo: zowe.imperative.ProfileInfo; private profilesOpCancelled = localize("profiles.operation.cancelled", "Operation Cancelled"); - public constructor(log: zowe.imperative.Logger, cwd?: string) { + public constructor(log: zowe.imperative.Logger, cwd?: string, private apimlAuthProvider?: IAuthProvider) { super(log, cwd); } @@ -1163,7 +1167,7 @@ export class Profiles extends ProfilesCache { Gui.showMessage(localize("ssoAuth.noBase", "This profile does not support token authentication.")); return; } - if (loginTokenType && loginTokenType !== zowe.imperative.SessConstants.TOKEN_TYPE_APIML) { + if (loginTokenType && !loginTokenType.startsWith(zowe.imperative.SessConstants.TOKEN_TYPE_APIML)) { // this will handle extenders if (node) { session = node.getSession(); @@ -1191,33 +1195,19 @@ export class Profiles extends ProfilesCache { return; } } else { - const apimlProfileName = await this.getApimlProfileName(serviceProfile); - if (apimlProfileName != null) { - creds = await this.loginCredentialPrompt(); - if (!creds) { - return; - } - try { - const updSession = new zowe.imperative.Session({ - hostname: serviceProfile.profile.host, - port: serviceProfile.profile.port, - user: creds[0], - password: creds[1], - rejectUnauthorized: serviceProfile.profile.rejectUnauthorized, - tokenType: loginTokenType, - type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, - }); - const updBaseProfile = await ApimlAuthenticationProvider.instance.login(apimlProfileName, updSession); + try { + creds = await this.apimlAuthProvider.login(serviceProfile); + if (creds != null) { node.setProfileToChoice({ ...node.getProfile(), - profile: { ...node.getProfile().profile, ...updBaseProfile }, + profile: { ...node.getProfile().profile, tokenType: creds[0], tokenValue: creds[1] }, }); - } catch (error) { - const errMsg = localize("ssoLogin.unableToLogin", "Unable to log in with {0}. {1}", serviceProfile.name, error?.message); - ZoweLogger.error(errMsg); - Gui.errorMessage(errMsg); - return; } + } catch (error) { + const errMsg = localize("ssoLogin.unableToLogin", "Unable to log in with {0}. {1}", serviceProfile.name, error?.message); + ZoweLogger.error(errMsg); + Gui.errorMessage(errMsg); + return; } } Gui.showMessage(localize("ssoLogin.successful", "Login to authentication service was successful.")); @@ -1233,23 +1223,13 @@ export class Profiles extends ProfilesCache { } try { // this will handle extenders - if (serviceProfile.type !== "zosmf" && serviceProfile.profile?.tokenType !== zowe.imperative.SessConstants.TOKEN_TYPE_APIML) { + if (serviceProfile.type !== "zosmf" && !serviceProfile.profile?.tokenType.startsWith(zowe.imperative.SessConstants.TOKEN_TYPE_APIML)) { await ZoweExplorerApiRegister.getInstance() .getCommonApi(serviceProfile) .logout(await node.getSession()); } else { // this will handle base profile apiml tokens - const apimlProfileName = await this.getApimlProfileName(serviceProfile); - const loginTokenType = ZoweExplorerApiRegister.getInstance().getCommonApi(serviceProfile).getTokenTypeName(); - const updSession = new zowe.imperative.Session({ - hostname: serviceProfile.profile.host, - port: serviceProfile.profile.port, - rejectUnauthorized: serviceProfile.profile.rejectUnauthorized, - tokenType: loginTokenType, - tokenValue: serviceProfile.profile.tokenValue, - type: zowe.imperative.SessConstants.AUTH_TYPE_TOKEN, - }); - await ApimlAuthenticationProvider.instance.logout(apimlProfileName, updSession); + await this.apimlAuthProvider.logout(serviceProfile); } Gui.showMessage(localize("ssoLogout.successful", "Logout from authentication service was successful for {0}.", serviceProfile.name)); } catch (error) { @@ -1271,7 +1251,7 @@ export class Profiles extends ProfilesCache { * @param profile Imperative loaded profile object * @returns Name of base profile to store APIML token */ - private async getApimlProfileName(profile: zowe.imperative.IProfileLoaded): Promise { + public async getApimlProfileName(profile: zowe.imperative.IProfileLoaded): Promise { // if (profile.profile?.apimlProfile != null) { // return profile.profile.apimlProfile as string; // } diff --git a/packages/zowe-explorer/src/extension.ts b/packages/zowe-explorer/src/extension.ts index ae87926932..309e8173cc 100644 --- a/packages/zowe-explorer/src/extension.ts +++ b/packages/zowe-explorer/src/extension.ts @@ -26,6 +26,7 @@ import { IZoweProviders, registerCommonCommands, registerRefreshCommand, watchCo import { ZoweLogger } from "./utils/LoggerUtils"; import { ZoweSaveQueue } from "./abstract/ZoweSaveQueue"; import { PollDecorator } from "./utils/DecorationProviders"; +import { ApimlAuthenticationProvider } from "./ApimlAuthProvider"; /** * The function that runs when the extension is loaded @@ -46,7 +47,7 @@ export async function activate(context: vscode.ExtensionContext): Promise