From cc16ff1b97e20a31e463d73a4c16c9e07b1a180c Mon Sep 17 00:00:00 2001 From: Trae Yelovich Date: Thu, 17 Oct 2024 11:33:31 -0400 Subject: [PATCH] feat: Detect JWT expiration in token values and prompt user if expired (#3174) * feat: Detect JWT token expiration during validation Signed-off-by: Trae Yelovich * refactor: Optimize logic in checkJwtTokenForProfile Signed-off-by: Trae Yelovich * wip: resolve failing test cases Signed-off-by: Trae Yelovich * tests: ZoweTreeProvider.checkJwtTokenForProfile test cases Signed-off-by: Trae Yelovich * refactor: Remove old ESLint max-len comment Signed-off-by: Trae Yelovich * fix(tests): failing test cases due to function change Signed-off-by: Trae Yelovich * chore: run prepublish Signed-off-by: Trae Yelovich * chore: update ZE changelog Signed-off-by: Trae Yelovich * refactor: rename promptUserForTokenLogin -> promptUserForSsoLogin Signed-off-by: Trae Yelovich * refactor: shorten logic in ZoweTreeProvider.checkJwtTokenForProfile Signed-off-by: Trae Yelovich * update SDKs and checkJwtTokenForProfile function Signed-off-by: Trae Yelovich * tests: Resolve failing tests after Imperative update Signed-off-by: Trae Yelovich * chore: update ZE changelog to address feedback Signed-off-by: Trae Yelovich * chore: update ZE API changelog Signed-off-by: Trae Yelovich * chore: update lockfile Signed-off-by: Trae Yelovich --------- Signed-off-by: Trae Yelovich Co-authored-by: Fernando Rijo Cedeno <37381190+zFernand0@users.noreply.github.com> Co-authored-by: Timothy Johnson --- packages/zowe-explorer-api/CHANGELOG.md | 1 + packages/zowe-explorer-api/package.json | 18 +-- .../zowe-explorer-ftp-extension/package.json | 4 +- packages/zowe-explorer/CHANGELOG.md | 1 + .../__mocks__/mockCreators/shared.ts | 1 + .../trees/ZoweTreeProvider.unit.test.ts | 52 +++++++ .../trees/dataset/DatasetTree.unit.test.ts | 2 + .../__unit__/trees/uss/USSTree.unit.test.ts | 5 +- packages/zowe-explorer/l10n/bundle.l10n.json | 58 ++++---- packages/zowe-explorer/l10n/poeditor.json | 18 +-- packages/zowe-explorer/package.json | 10 +- .../src/trees/ZoweTreeProvider.ts | 16 +++ packages/zowe-explorer/src/utils/AuthUtils.ts | 36 +++-- pnpm-lock.yaml | 135 +++++++++--------- 14 files changed, 221 insertions(+), 136 deletions(-) diff --git a/packages/zowe-explorer-api/CHANGELOG.md b/packages/zowe-explorer-api/CHANGELOG.md index 78a66f4070..8983d58066 100644 --- a/packages/zowe-explorer-api/CHANGELOG.md +++ b/packages/zowe-explorer-api/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t - Zowe Explorer now includes support for the [VS Code display languages](https://code.visualstudio.com/docs/getstarted/locales) French, German, Japanese, Portuguese, and Spanish. - Localization of strings within the webviews. [#2983](https://github.com/zowe/zowe-explorer-vscode/issues/2983) +- Update Zowe SDKs to `8.2.0` to get the latest enhancements from Imperative. ### Bug fixes diff --git a/packages/zowe-explorer-api/package.json b/packages/zowe-explorer-api/package.json index 7704ac56c9..f8a713dfc2 100644 --- a/packages/zowe-explorer-api/package.json +++ b/packages/zowe-explorer-api/package.json @@ -28,15 +28,15 @@ }, "dependencies": { "@types/vscode": "^1.53.2", - "@zowe/core-for-zowe-sdk": "^8.1.1", - "@zowe/imperative": "^8.1.0", - "@zowe/secrets-for-zowe-sdk": "^8.1.0", - "@zowe/zos-console-for-zowe-sdk": "^8.1.1", - "@zowe/zos-files-for-zowe-sdk": "^8.1.1", - "@zowe/zos-jobs-for-zowe-sdk": "^8.1.1", - "@zowe/zos-tso-for-zowe-sdk": "^8.1.1", - "@zowe/zos-uss-for-zowe-sdk": "^8.1.1", - "@zowe/zosmf-for-zowe-sdk": "^8.1.1", + "@zowe/core-for-zowe-sdk": "^8.2.0", + "@zowe/imperative": "^8.2.0", + "@zowe/secrets-for-zowe-sdk": "^8.1.2", + "@zowe/zos-console-for-zowe-sdk": "^8.2.0", + "@zowe/zos-files-for-zowe-sdk": "^8.2.0", + "@zowe/zos-jobs-for-zowe-sdk": "^8.2.0", + "@zowe/zos-tso-for-zowe-sdk": "^8.2.0", + "@zowe/zos-uss-for-zowe-sdk": "^8.2.0", + "@zowe/zosmf-for-zowe-sdk": "^8.2.0", "deep-object-diff": "^1.1.9", "mustache": "^4.2.0", "semver": "^7.6.0" diff --git a/packages/zowe-explorer-ftp-extension/package.json b/packages/zowe-explorer-ftp-extension/package.json index b6eaa89dcd..b57422009d 100644 --- a/packages/zowe-explorer-ftp-extension/package.json +++ b/packages/zowe-explorer-ftp-extension/package.json @@ -52,9 +52,9 @@ "vscode": "^1.79.0" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "^8.1.1", + "@zowe/zos-files-for-zowe-sdk": "^8.2.0", "@zowe/zos-ftp-for-zowe-cli": "^3.0.0", - "@zowe/zos-jobs-for-zowe-sdk": "^8.1.1", + "@zowe/zos-jobs-for-zowe-sdk": "^8.2.0", "@zowe/zowe-explorer-api": "3.1.0-SNAPSHOT", "tmp": "0.2.3" }, diff --git a/packages/zowe-explorer/CHANGELOG.md b/packages/zowe-explorer/CHANGELOG.md index 3432539ad2..5218a0458b 100644 --- a/packages/zowe-explorer/CHANGELOG.md +++ b/packages/zowe-explorer/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen - Zowe Explorer now includes support for the [VS Code display languages](https://code.visualstudio.com/docs/getstarted/locales) French, German, Japanese, Portuguese, and Spanish. Download the respective language pack and switch. - Localization of strings within the webviews. [#2983](https://github.com/zowe/zowe-explorer-vscode/issues/2983) +- Added expired JSON web token detection for profiles in each tree view (Data Sets, USS, Jobs). When a user performs a search on a profile, they are prompted to log in if their token expired. [#3175](https://github.com/zowe/zowe-explorer-vscode/issues/3175) ### Bug fixes diff --git a/packages/zowe-explorer/__tests__/__mocks__/mockCreators/shared.ts b/packages/zowe-explorer/__tests__/__mocks__/mockCreators/shared.ts index 1a5a240892..ea5e6e1ff5 100644 --- a/packages/zowe-explorer/__tests__/__mocks__/mockCreators/shared.ts +++ b/packages/zowe-explorer/__tests__/__mocks__/mockCreators/shared.ts @@ -407,6 +407,7 @@ export function createInstanceOfProfileInfo() { profLoc: { locType: 0, osLoc: ["location"], jsonLoc: "jsonLoc" }, }, ], + hasTokenExpiredForProfile: jest.fn(), updateProperty: jest.fn(), updateKnownProperty: jest.fn(), createSession: jest.fn(), diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/ZoweTreeProvider.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/ZoweTreeProvider.unit.test.ts index c7bbf3c1a1..472ed89871 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/ZoweTreeProvider.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/ZoweTreeProvider.unit.test.ts @@ -35,6 +35,7 @@ import { JobInit } from "../../../src/trees/job/JobInit"; import { createIJobObject, createJobSessionNode } from "../../__mocks__/mockCreators/jobs"; import { createDatasetSessionNode } from "../../__mocks__/mockCreators/datasets"; import { DatasetInit } from "../../../src/trees/dataset/DatasetInit"; +import { AuthUtils } from "../../../src/utils/AuthUtils"; async function createGlobalMocks() { Object.defineProperty(ZoweLocalStorage, "storage", { @@ -309,6 +310,7 @@ describe("ZoweJobNode unit tests - Function checkCurrentProfile", () => { testIJob: createIJobObject(), testJobsProvider: await JobInit.createJobsTree(imperative.Logger.getAppLogger()), jobNode: null, + checkJwtTokenForProfile: jest.spyOn(ZoweTreeProvider as any, "checkJwtTokenForProfile").mockImplementationOnce(() => {}), }; newMocks.jobNode = new ZoweJobNode({ @@ -627,3 +629,53 @@ describe("Tree Provider Unit Tests - function isGlobalProfileNode", () => { getOsLocInfoMock.mockRestore(); }); }); + +describe("Tree Provider Unit Tests - function checkJwtTokenForProfile", () => { + function getBlockMocks() { + const getAllProfiles = jest.fn().mockReturnValue([ + { + profName: "zosmf", + profType: "zosmf", + isDefaultProfile: false, + profLoc: { + locType: imperative.ProfLocType.TEAM_CONFIG, + osLoc: ["/a/b/c/zowe.config.json"], + jsonLoc: ["profiles.zosmf"], + }, + }, + ]); + const hasTokenExpiredForProfile = jest.fn(); + const mergeArgsForProfile = jest.fn(); + const profilesGetInstance = jest.spyOn(Profiles, "getInstance").mockReturnValue({ + getProfileInfo: jest.fn().mockResolvedValue({ + hasTokenExpiredForProfile, + getAllProfiles, + mergeArgsForProfile, + } as any), + } as any); + + return { + getAllProfiles, + hasTokenExpiredForProfile, + mergeArgsForProfile, + profilesGetInstance, + }; + } + + it("returns early if the profile's token has not expired", async () => { + const blockMocks = getBlockMocks(); + blockMocks.hasTokenExpiredForProfile.mockReturnValueOnce(false); + blockMocks.mergeArgsForProfile.mockReturnValue({ knownArgs: [{ argName: "tokenType", argValue: "LtpaToken2" }] }); + await (ZoweTreeProvider as any).checkJwtTokenForProfile("zosmf"); + expect(blockMocks.hasTokenExpiredForProfile).toHaveBeenCalledWith("zosmf"); + }); + + it("prompts the user to log in if a JWT token is present and has expired", async () => { + const blockMocks = getBlockMocks(); + blockMocks.hasTokenExpiredForProfile.mockReturnValueOnce(true); + const promptUserForSsoLogin = jest.spyOn(AuthUtils, "promptUserForSsoLogin").mockImplementation(); + await (ZoweTreeProvider as any).checkJwtTokenForProfile("zosmf"); + expect(blockMocks.hasTokenExpiredForProfile).toHaveBeenCalledWith("zosmf"); + expect(promptUserForSsoLogin).toHaveBeenCalled(); + }); +}); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts index 1cb7e8149f..e217c18606 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts @@ -53,6 +53,7 @@ import { ZoweScheme } from "../../../../../zowe-explorer-api/src/fs/types/abstra import { Sorting } from "../../../../../zowe-explorer-api/src/tree"; import { IconUtils } from "../../../../src/icons/IconUtils"; import { SharedContext } from "../../../../src/trees/shared/SharedContext"; +import { ZoweTreeProvider } from "../../../../src/trees/ZoweTreeProvider"; jest.mock("fs"); jest.mock("util"); @@ -1495,6 +1496,7 @@ describe("Dataset Tree Unit Tests - Function datasetFilterPrompt", () => { qpPlaceholder: 'Choose "Create new..." to define a new profile or select an existing profile to add to the Data Set Explorer', mockEnableValidationContext: jest.fn(), testTree: new DatasetTree(), + checkJwtTokenForProfile: jest.spyOn(ZoweTreeProvider as any, "checkJwtTokenForProfile").mockImplementationOnce(() => {}), }; newMocks.datasetSessionNode = createDatasetSessionNode(newMocks.session, newMocks.imperativeProfile); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts index 17cfac602d..1f03687097 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts @@ -43,6 +43,7 @@ import { IconUtils } from "../../../../src/icons/IconUtils"; import { FilterDescriptor } from "../../../../src/management/FilterManagement"; import { AuthUtils } from "../../../../src/utils/AuthUtils"; import { Icon } from "../../../../src/icons/Icon"; +import { ZoweTreeProvider } from "../../../../src/trees/ZoweTreeProvider"; function createGlobalMocks() { const globalMocks = { @@ -550,6 +551,7 @@ describe("USSTree Unit Tests - Function filterPrompt", () => { qpValue: "", qpItem: new FilterDescriptor("\uFF0B " + "Create a new filter"), resolveQuickPickHelper: jest.spyOn(Gui, "resolveQuickPick"), + checkJwtTokenForProfile: jest.spyOn(ZoweTreeProvider as any, "checkJwtTokenForProfile").mockImplementationOnce(() => {}), }; newMocks.resolveQuickPickHelper.mockImplementation(() => Promise.resolve(newMocks.qpItem)); globalMocks.createQuickPick.mockReturnValue({ @@ -655,7 +657,7 @@ describe("USSTree Unit Tests - Function filterPrompt", () => { it("Tests that filter() works correctly for favorited search nodes with credentials", async () => { const globalMocks = createGlobalMocks(); - await createBlockMocks(globalMocks); + const blockMocks = await createBlockMocks(globalMocks); const sessionWithCred = createISession(); globalMocks.createSessCfgFromArgs.mockReturnValue(sessionWithCred); @@ -669,6 +671,7 @@ describe("USSTree Unit Tests - Function filterPrompt", () => { node.fullPath = "/u/myFolder"; globalMocks.testTree.mFavorites.push(node); await expect(globalMocks.testTree.filterPrompt(node)).resolves.not.toThrow(); + expect(blockMocks.checkJwtTokenForProfile).toHaveBeenCalledWith("ussTestSess2"); }); it("Tests that filter() works correctly for favorited search nodes without credentials", async () => { diff --git a/packages/zowe-explorer/l10n/bundle.l10n.json b/packages/zowe-explorer/l10n/bundle.l10n.json index ef955fbf6b..4b2584e64f 100644 --- a/packages/zowe-explorer/l10n/bundle.l10n.json +++ b/packages/zowe-explorer/l10n/bundle.l10n.json @@ -166,13 +166,13 @@ "Label" ] }, - "Your connection is no longer active for profile '{0}'. Please log in to an authentication service to restore the connection./Label": { + "Update Credentials": "Update Credentials", + "Your connection is no longer active for profile '{0}'. Please log in to an authentication service to restore the connection./Profile name": { "message": "Your connection is no longer active for profile '{0}'. Please log in to an authentication service to restore the connection.", "comment": [ - "Label" + "Profile name" ] }, - "Update Credentials": "Update Credentials", "Profile Name {0} is inactive. Please check if your Zowe server is active or if the URL and port in your profile is correct./Profile name": { "message": "Profile Name {0} is inactive. Please check if your Zowe server is active or if the URL and port in your profile is correct.", "comment": [ @@ -209,32 +209,6 @@ "Profile auth error": "Profile auth error", "Profile is not authenticated, please log in to continue": "Profile is not authenticated, please log in to continue", "Retrieving response from USS list API": "Retrieving response from USS list API", - "The 'move' function is not implemented for this USS API.": "The 'move' function is not implemented for this USS API.", - "Could not list USS files: Empty path provided in URI": "Could not list USS files: Empty path provided in URI", - "Profile does not exist for this file.": "Profile does not exist for this file.", - "Saving USS file...": "Saving USS file...", - "Renaming {0} failed due to API error: {1}/File pathError message": { - "message": "Renaming {0} failed due to API error: {1}", - "comment": [ - "File path", - "Error message" - ] - }, - "Deleting {0} failed due to API error: {1}/File nameError message": { - "message": "Deleting {0} failed due to API error: {1}", - "comment": [ - "File name", - "Error message" - ] - }, - "No error details given": "No error details given", - "Error fetching destination {0} for paste action: {1}/USS pathError message": { - "message": "Error fetching destination {0} for paste action: {1}", - "comment": [ - "USS path", - "Error message" - ] - }, "Downloaded: {0}/Download time": { "message": "Downloaded: {0}", "comment": [ @@ -305,6 +279,32 @@ "initializeUSSFavorites.error.buttonRemove": "initializeUSSFavorites.error.buttonRemove", "File does not exist. It may have been deleted.": "File does not exist. It may have been deleted.", "Pulling from Mainframe...": "Pulling from Mainframe...", + "The 'move' function is not implemented for this USS API.": "The 'move' function is not implemented for this USS API.", + "Could not list USS files: Empty path provided in URI": "Could not list USS files: Empty path provided in URI", + "Profile does not exist for this file.": "Profile does not exist for this file.", + "Saving USS file...": "Saving USS file...", + "Renaming {0} failed due to API error: {1}/File pathError message": { + "message": "Renaming {0} failed due to API error: {1}", + "comment": [ + "File path", + "Error message" + ] + }, + "Deleting {0} failed due to API error: {1}/File nameError message": { + "message": "Deleting {0} failed due to API error: {1}", + "comment": [ + "File name", + "Error message" + ] + }, + "No error details given": "No error details given", + "Error fetching destination {0} for paste action: {1}/USS pathError message": { + "message": "Error fetching destination {0} for paste action: {1}", + "comment": [ + "USS path", + "Error message" + ] + }, "{0} location/Node type": { "message": "{0} location", "comment": [ diff --git a/packages/zowe-explorer/l10n/poeditor.json b/packages/zowe-explorer/l10n/poeditor.json index c5ed995fce..bf764c7232 100644 --- a/packages/zowe-explorer/l10n/poeditor.json +++ b/packages/zowe-explorer/l10n/poeditor.json @@ -511,8 +511,8 @@ "Select Certificate Key": "", "Required parameter 'host' must not be blank.": "", "Invalid Credentials for profile '{0}'. Please ensure the username and password are valid or this may lead to a lock-out.": "", - "Your connection is no longer active for profile '{0}'. Please log in to an authentication service to restore the connection.": "", "Update Credentials": "", + "Your connection is no longer active for profile '{0}'. Please log in to an authentication service to restore the connection.": "", "Profile Name {0} is inactive. Please check if your Zowe server is active or if the URL and port in your profile is correct.": "", "Use the search button to list USS files": "", "Invalid node": "", @@ -529,14 +529,6 @@ "Profile auth error": "", "Profile is not authenticated, please log in to continue": "", "Retrieving response from USS list API": "", - "The 'move' function is not implemented for this USS API.": "", - "Could not list USS files: Empty path provided in URI": "", - "Profile does not exist for this file.": "", - "Saving USS file...": "", - "Renaming {0} failed due to API error: {1}": "", - "Deleting {0} failed due to API error: {1}": "", - "No error details given": "", - "Error fetching destination {0} for paste action: {1}": "", "Downloaded: {0}": "", "Encoding: {0}": "", "Binary": "", @@ -565,6 +557,14 @@ "initializeUSSFavorites.error.buttonRemove": "", "File does not exist. It may have been deleted.": "", "Pulling from Mainframe...": "", + "The 'move' function is not implemented for this USS API.": "", + "Could not list USS files: Empty path provided in URI": "", + "Profile does not exist for this file.": "", + "Saving USS file...": "", + "Renaming {0} failed due to API error: {1}": "", + "Deleting {0} failed due to API error: {1}": "", + "No error details given": "", + "Error fetching destination {0} for paste action: {1}": "", "{0} location": "", "Choose a location to create the {0}": "", "Name of file or directory": "", diff --git a/packages/zowe-explorer/package.json b/packages/zowe-explorer/package.json index 42d748ef2f..fbc1303ab4 100644 --- a/packages/zowe-explorer/package.json +++ b/packages/zowe-explorer/package.json @@ -1830,11 +1830,11 @@ }, "dependencies": { "@vscode/codicons": "^0.0.35", - "@zowe/core-for-zowe-sdk": "^8.1.1", - "@zowe/secrets-for-zowe-sdk": "^8.1.0", - "@zowe/zos-files-for-zowe-sdk": "^8.1.1", - "@zowe/zos-jobs-for-zowe-sdk": "^8.1.1", - "@zowe/zosmf-for-zowe-sdk": "^8.1.1", + "@zowe/core-for-zowe-sdk": "^8.2.0", + "@zowe/secrets-for-zowe-sdk": "^8.1.2", + "@zowe/zos-files-for-zowe-sdk": "^8.2.0", + "@zowe/zos-jobs-for-zowe-sdk": "^8.2.0", + "@zowe/zosmf-for-zowe-sdk": "^8.2.0", "@zowe/zowe-explorer-api": "3.1.0-SNAPSHOT", "dayjs": "^1.11.10", "fs-extra": "8.0.1", diff --git a/packages/zowe-explorer/src/trees/ZoweTreeProvider.ts b/packages/zowe-explorer/src/trees/ZoweTreeProvider.ts index 5a2a99a44b..ea2ddbd1ed 100644 --- a/packages/zowe-explorer/src/trees/ZoweTreeProvider.ts +++ b/packages/zowe-explorer/src/trees/ZoweTreeProvider.ts @@ -266,6 +266,7 @@ export class ZoweTreeProvider { Profiles.getInstance().validProfile = Validation.ValidationType.UNVERIFIED; } } + await ZoweTreeProvider.checkJwtTokenForProfile(node.getProfileName()); this.refresh(); return profileStatus; } @@ -304,6 +305,21 @@ export class ZoweTreeProvider { await Profiles.getInstance().createZoweSession(zoweFileProvider); } + /** + * Checks if a JWT token is used for authenticating the given profile name. + * If so, it will grab and decode the token to determine its expire date. + * If the token has expired, it will prompt the user to log in again. + * + * @param profileName The name of the profile to check the JWT token for + */ + protected static async checkJwtTokenForProfile(profileName: string): Promise { + const profInfo = await Profiles.getInstance().getProfileInfo(); + + if (profInfo.hasTokenExpiredForProfile(profileName)) { + await AuthUtils.promptUserForSsoLogin(profileName); + } + } + private async loadProfileBySessionName( sessionName: string, treeProvider: IZoweTree, diff --git a/packages/zowe-explorer/src/utils/AuthUtils.ts b/packages/zowe-explorer/src/utils/AuthUtils.ts index 0f6fa561c4..93c7dcfbed 100644 --- a/packages/zowe-explorer/src/utils/AuthUtils.ts +++ b/packages/zowe-explorer/src/utils/AuthUtils.ts @@ -52,13 +52,6 @@ export class AuthUtils { args: [label], comment: ["Label"], }); - const errToken = vscode.l10n.t({ - message: - // eslint-disable-next-line max-len - "Your connection is no longer active for profile '{0}'. Please log in to an authentication service to restore the connection.", - args: [label], - comment: ["Label"], - }); if (label.includes("[")) { label = label.substring(0, label.indexOf(" [")).trim(); } @@ -68,13 +61,8 @@ export class AuthUtils { const isTokenAuth = await AuthUtils.isUsingTokenAuth(label); if (tokenError.includes("Token is not valid or expired.") || isTokenAuth) { - const message = vscode.l10n.t("Log in to Authentication Service"); - const success = Gui.showMessage(errToken, { items: [message] }).then(async (selection) => { - if (selection) { - return Constants.PROFILES_CACHE.ssoLogin(null, label); - } - }); - return success; + AuthUtils.promptUserForSsoLogin(label); + return; } } const checkCredsButton = vscode.l10n.t("Update Credentials"); @@ -104,6 +92,26 @@ export class AuthUtils { return false; } + /** + * Prompts user to log in to authentication service. + * @param profileName The name of the profile used to log in + */ + public static promptUserForSsoLogin(profileName: string): Thenable { + return Gui.showMessage( + vscode.l10n.t({ + message: + "Your connection is no longer active for profile '{0}'. Please log in to an authentication service to restore the connection.", + args: [profileName], + comment: ["Profile name"], + }), + { items: [vscode.l10n.t("Log in to Authentication Service")], vsCodeOpts: { modal: true } } + ).then(async (selection) => { + if (selection) { + await Constants.PROFILES_CACHE.ssoLogin(null, profileName); + } + }); + } + /** * Function to update session and profile information in provided node * @param profiles is data source to find profiles diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c2ff641447..0ab810f064 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -142,20 +142,20 @@ importers: specifier: ^0.0.35 version: 0.0.35 '@zowe/core-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/imperative@8.2.0) '@zowe/secrets-for-zowe-sdk': - specifier: ^8.1.0 - version: 8.1.0 + specifier: ^8.1.2 + version: 8.1.2 '@zowe/zos-files-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) '@zowe/zos-jobs-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) '@zowe/zosmf-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) '@zowe/zowe-explorer-api': specifier: 3.1.0-SNAPSHOT version: link:../zowe-explorer-api @@ -251,32 +251,32 @@ importers: specifier: ^1.53.2 version: 1.89.0 '@zowe/core-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/imperative@8.2.0) '@zowe/imperative': - specifier: ^8.1.0 - version: 8.1.0 + specifier: ^8.2.0 + version: 8.2.0 '@zowe/secrets-for-zowe-sdk': - specifier: ^8.1.0 - version: 8.1.0 + specifier: ^8.1.2 + version: 8.1.2 '@zowe/zos-console-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) '@zowe/zos-files-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) '@zowe/zos-jobs-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) '@zowe/zos-tso-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) '@zowe/zos-uss-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/imperative@8.2.0) '@zowe/zosmf-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) deep-object-diff: specifier: ^1.1.9 version: 1.1.9 @@ -300,14 +300,14 @@ importers: packages/zowe-explorer-ftp-extension: dependencies: '@zowe/zos-files-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) '@zowe/zos-ftp-for-zowe-cli': specifier: ^3.0.0 - version: 3.0.0(@zowe/imperative@8.1.0) + version: 3.0.0(@zowe/imperative@8.2.0) '@zowe/zos-jobs-for-zowe-sdk': - specifier: ^8.1.1 - version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + specifier: ^8.2.0 + version: 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) '@zowe/zowe-explorer-api': specifier: 3.1.0-SNAPSHOT version: link:../zowe-explorer-api @@ -3569,19 +3569,19 @@ packages: requiresBuild: true dev: true - /@zowe/core-for-zowe-sdk@8.1.1(@zowe/imperative@8.1.0): - resolution: {integrity: sha512-O3lbFiCWe8tsf7eAWdbmDqyEIhHniPD7AOr0IixRcnyPVu5aNLSX91Xt11PA7Ka+nbEN1mdo/BYZcpQiIcUiDQ==} + /@zowe/core-for-zowe-sdk@8.2.0(@zowe/imperative@8.2.0): + resolution: {integrity: sha512-pNSnJXmV8/OR8X2TXVF4nor8MdlyFCfU4WzPmtqlrpC+prwOvVMRbHpkS6CxibHh6O457L/dBEtBaQkEh46gBw==} engines: {node: '>=18.12.0'} peerDependencies: '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/imperative': 8.1.0 + '@zowe/imperative': 8.2.0 comment-json: 4.2.5 string-width: 4.2.3 dev: false - /@zowe/imperative@8.1.0: - resolution: {integrity: sha512-laKAPM5YWGD3s2Gc2y9BV/6QiENfg3hRbOBi+zEX8cDshAaZQ0Nd2Q1vN++6u211QvD50e/VVPwFusnJpqdczg==} + /@zowe/imperative@8.2.0: + resolution: {integrity: sha512-7noMZFgLe6gLeWGkt69Wyy5LOuo4mM9VClWpJibhCxkQp0L8KOz8TaW4wTu9Ze9gVm2bheE0rK3Nuv52Vaop4g==} engines: {node: '>=18.12.0'} dependencies: '@types/yargs': 17.0.33 @@ -3625,87 +3625,88 @@ packages: - supports-color dev: false - /@zowe/secrets-for-zowe-sdk@8.1.0: - resolution: {integrity: sha512-XhwuLo+e3sMIUETHLmVpKvU0ydnYouWHDOHTVvaWfexlwzcuZy23D0EOOjWw/LsQ65rABXaOHOfATuyT0FvFww==} + /@zowe/secrets-for-zowe-sdk@8.1.2: + resolution: {integrity: sha512-cE8rlBADL48wmiQr+fdQdxczW4wLsmv5BQa03QepKiydBBE7TLrG2Anx/F4uZ+sVIZQuN95SHvwkt8VZaTzuyw==} engines: {node: '>=14'} requiresBuild: true dev: false - /@zowe/zos-console-for-zowe-sdk@8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0): - resolution: {integrity: sha512-8rH3madm917KoBEMzyS2XLkzU7axQg5kvrQltjuF248pFEpPX4WkplHljaNOJ1RraZFdjp+6KdyEODWgeZpSmw==} + /@zowe/zos-console-for-zowe-sdk@8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0): + resolution: {integrity: sha512-9nW4UlrXRGLJkzDfWIhw6qu058eo1TaeuDkyd7XtRHbwm6fy4UCgWsalhoSqJsrTRsk9rEVtQklrxbTzbyHkMQ==} engines: {node: '>=18.12.0'} peerDependencies: '@zowe/core-for-zowe-sdk': ^8.0.0 '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/core-for-zowe-sdk': 8.1.1(@zowe/imperative@8.1.0) - '@zowe/imperative': 8.1.0 + '@zowe/core-for-zowe-sdk': 8.2.0(@zowe/imperative@8.2.0) + '@zowe/imperative': 8.2.0 dev: false - /@zowe/zos-files-for-zowe-sdk@8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0): - resolution: {integrity: sha512-zna2Dj8u1jL20YzkIq2FVHoiJFFFTKnurjfRfGHcy9WErLOKdM97AXVpCEVjMboWbIbBDomjXvsa0gYw3soqdg==} + /@zowe/zos-files-for-zowe-sdk@8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0): + resolution: {integrity: sha512-KRcSjbzOPZBo/Yvp1sOc7v1mirTJV8IuHAotSLEWCF1YTXv5e09w1O9T3IctmYDFUi32/bmlCLsK13HKNUwdQw==} engines: {node: '>=18.12.0'} peerDependencies: '@zowe/core-for-zowe-sdk': ^8.0.0 '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/core-for-zowe-sdk': 8.1.1(@zowe/imperative@8.1.0) - '@zowe/imperative': 8.1.0 + '@zowe/core-for-zowe-sdk': 8.2.0(@zowe/imperative@8.2.0) + '@zowe/imperative': 8.2.0 + lodash: 4.17.21 minimatch: 9.0.5 dev: false - /@zowe/zos-ftp-for-zowe-cli@3.0.0(@zowe/imperative@8.1.0): + /@zowe/zos-ftp-for-zowe-cli@3.0.0(@zowe/imperative@8.2.0): resolution: {integrity: sha512-lNt4t4VJMvnnjQXXusw5N5w5nVysbKZVSD+c7wvj/RJt6ceSV2aMH7QPeiyvTE0FEFErCkjCRl2AxeVtBkn82Q==} peerDependencies: '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/imperative': 8.1.0 + '@zowe/imperative': 8.2.0 zos-node-accessor: 2.0.11 dev: false - /@zowe/zos-jobs-for-zowe-sdk@8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0): - resolution: {integrity: sha512-ozdupvtmcuzq7P2CYueLGAfRUuxjL/vXAH9h11bLxiSO62LoqW87vDWJXwHQq0Fkey0TuU5Vi3Ayf8G0pNtuSQ==} + /@zowe/zos-jobs-for-zowe-sdk@8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0): + resolution: {integrity: sha512-Hjh1r9PaJhyeubxcIjigkqTkYQ04dWPrcO4a5mWwkwRhgBIgSJU17xEenWv2+QrYbSEtiz//e3p6Y2sCvgAEKQ==} engines: {node: '>=18.12.0'} peerDependencies: '@zowe/core-for-zowe-sdk': ^8.0.0 '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/core-for-zowe-sdk': 8.1.1(@zowe/imperative@8.1.0) - '@zowe/imperative': 8.1.0 - '@zowe/zos-files-for-zowe-sdk': 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + '@zowe/core-for-zowe-sdk': 8.2.0(@zowe/imperative@8.2.0) + '@zowe/imperative': 8.2.0 + '@zowe/zos-files-for-zowe-sdk': 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) dev: false - /@zowe/zos-tso-for-zowe-sdk@8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0): - resolution: {integrity: sha512-JVK/AkzdZfxaLsVpNm0x2CsTBJ6OaeFQEwJzMUtENM53t6IauDBKq2FfWe4ivxP2Hd/dyieRiSIS+Hw+KEN4Og==} + /@zowe/zos-tso-for-zowe-sdk@8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0): + resolution: {integrity: sha512-xY9VgGxsI1PGoBogIz/lw78s6+AvJmy1YfjZGpCWygy/0LgOj/A/Uk03Dusk0l+vVCn/XXLXgIl1NwU3AjcBuw==} engines: {node: '>=18.12.0'} peerDependencies: '@zowe/core-for-zowe-sdk': ^8.0.0 '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/core-for-zowe-sdk': 8.1.1(@zowe/imperative@8.1.0) - '@zowe/imperative': 8.1.0 - '@zowe/zosmf-for-zowe-sdk': 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) + '@zowe/core-for-zowe-sdk': 8.2.0(@zowe/imperative@8.2.0) + '@zowe/imperative': 8.2.0 + '@zowe/zosmf-for-zowe-sdk': 8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0) dev: false - /@zowe/zos-uss-for-zowe-sdk@8.1.1(@zowe/imperative@8.1.0): - resolution: {integrity: sha512-AvL7DNR/zdEI+K5kwWynnN20E7No+UzZMMvkpTEPjC6gWqlF7w9hq0kZ6EIeyml+QtwAEcsoWglhlQWQBMvr3g==} + /@zowe/zos-uss-for-zowe-sdk@8.2.0(@zowe/imperative@8.2.0): + resolution: {integrity: sha512-fHsWjHaE9zPnDfdBH1MEuiN/mbeWDtdRECn0hbvC4ZrYfOyux54gr4wdN6F4sGr6YmHqu5OjfpXgyIhPskg8Pw==} engines: {node: '>=18.12.0'} peerDependencies: '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/imperative': 8.1.0 + '@zowe/imperative': 8.2.0 ssh2: 1.15.0 dev: false - /@zowe/zosmf-for-zowe-sdk@8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0): - resolution: {integrity: sha512-bSY2RKo3aAjpm7Ec//gayjGv0pGiB4wfi/SztXa5gjB2sIgJcJDTxgResCWBhM8nDVqXw+rpvdaSMOptyAmlgQ==} + /@zowe/zosmf-for-zowe-sdk@8.2.0(@zowe/core-for-zowe-sdk@8.2.0)(@zowe/imperative@8.2.0): + resolution: {integrity: sha512-h5n5wS7UX5cai2xeTf+M2bwMPm6/1u9P/7X+CjefqhOjys9ujurJCFzgUPYY6Xuq7SrCewVXgaYWQ0DO0nrWmA==} engines: {node: '>=18.12.0'} peerDependencies: '@zowe/core-for-zowe-sdk': ^8.0.0 '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/core-for-zowe-sdk': 8.1.1(@zowe/imperative@8.1.0) - '@zowe/imperative': 8.1.0 + '@zowe/core-for-zowe-sdk': 8.2.0(@zowe/imperative@8.2.0) + '@zowe/imperative': 8.2.0 dev: false /abbrev@1.1.1: