Skip to content

Commit

Permalink
Merge branch 'main' into fix/deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
JillieBeanSim authored Sep 25, 2024
2 parents 4d2fc80 + c1d216b commit 06c3caa
Show file tree
Hide file tree
Showing 48 changed files with 683 additions and 356 deletions.
8 changes: 4 additions & 4 deletions .github/release.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ module.exports = {
level: "minor"
},
{
name: "release/2.*",
name: "v2-lts",
channel: "zowe-v2-lts",
level: "patch"
},
{
name: "release/3.*",
channel: "latest",
name: "v1-lts",
channel: "zowe-v1-lts",
level: "patch"
},
{
name: "next",
name: "release/3.*",
prerelease: true,
}
],
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ packages/zowe-explorer/__tests__/__integration__/ci
!packages/zowe-explorer/__tests__/__integration__/ci/zowe.config.json
package.nls.*.json
bundle.l10n.*.json
bundle.l10n.json.template
zedc/target
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Join our [Slack channel](https://slack.openmainframeproject.org/) to connect wit
Client-side prerequisites for development:

- Install [Node.js](https://nodejs.org/en/download/) v16.0 or later.
- Install [PNPM](https://pnpm.io/installation).
- Install [PNPM 8](https://pnpm.io/installation).

Host-side prerequisites for connection:

Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@
"webpack-cli": "^5.1.4"
},
"pnpm": {
"overrides": {}
"overrides": {
"ws": "^8.17.1"
}
},
"scripts": {
"clean": "pnpm -r clean",
Expand Down
2 changes: 2 additions & 0 deletions packages/zowe-explorer-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t
- Deprecated the methods `ZoweVsCodeExtension.loginWithBaseProfile` and `ZoweVsCodeExtension.logoutWithBaseProfile`. Use `ZoweVsCodeExtension.ssoLogin` and `ZoweVsCodeExtension.ssoLogout` instead, which use the `BaseProfileAuthOptions` interface and allow you to choose whether the token value in the base profile should have precedence in case there are conflicts. [#3076](https://github.com/zowe/zowe-explorer-vscode/pull/3076)
- Fixed bug in `ProfilesCache` class where old profiles were still accessible after deleting a Team configuration file. [#3124](https://github.com/zowe/zowe-explorer-vscode/issues/3124)
- Added `extensionRemovedFromPath` private function to the `DsEntry` class to allow removing the extension from a data set before making API calls. [#3121](https://github.com/zowe/zowe-explorer-vscode/issues/3121)
- Deprecated the method `ProfilesCache.updateProfilesArrays`. Use `ProfilesCache.updateCachedProfile` instead, which handles updating credentials cached in memory when `autoStore` is false. [#3120](https://github.com/zowe/zowe-explorer-vscode/issues/3120)

### Bug fixes

- Updated the `TableViewProvider.setTableView` function to show the Zowe Resources panel if a table is provided. If `null` is passed, the Zowe Resources panel will be hidden. [#3113](https://github.com/zowe/zowe-explorer-vscode/issues/3113)
- Fixed behavior of logout action when token is defined in both base profile and parent profile. [#3076](https://github.com/zowe/zowe-explorer-vscode/issues/3076)
- Fixed profile cached by `FileSystemProvider` not refreshing on password change. [#3120](https://github.com/zowe/zowe-explorer-vscode/issues/3120)

## `3.0.0-next.202409132122`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,12 @@ function createProfInfoMock(profiles: Partial<imperative.IProfileLoaded>[]): imp
const teamConfigApi: Partial<imperative.Config> = {
api: {
profiles: {
get: jest.fn().mockReturnValue({}),
get: jest.fn(),
getProfilePathFromName: jest.fn().mockImplementation((x) => x),
},
secure: {
secureFields: jest.fn().mockReturnValue([]),
securePropsForProfile: jest.fn().mockReturnValue([]),
},
} as any,
exists: true,
Expand Down Expand Up @@ -223,6 +224,7 @@ describe("ProfilesCache", () => {
profCache.allProfiles = [lpar1Profile as imperative.IProfileLoaded];
(profCache as any).defaultProfileByType = new Map([["zosmf", { ...profCache.allProfiles[0] }]]);
expect(profCache.allProfiles[0].profile).toMatchObject(lpar1Profile.profile);
// eslint-disable-next-line deprecation/deprecation
profCache.updateProfilesArrays({
...lpar1Profile,
profile: lpar2Profile.profile,
Expand All @@ -231,6 +233,35 @@ describe("ProfilesCache", () => {
expect((profCache as any).defaultProfileByType.get("zosmf").profile).toMatchObject(lpar2Profile.profile);
});

it("updateCachedProfile should refresh all profiles when autoStore is true", async () => {
const profCache = new ProfilesCache(fakeLogger as unknown as imperative.Logger);
jest.spyOn(profCache, "getProfileInfo").mockResolvedValueOnce({
getTeamConfig: jest.fn().mockReturnValue({ properties: { autoStore: true } }),
} as unknown as imperative.ProfileInfo);
const refreshSpy = jest.spyOn(profCache, "refresh").mockImplementation();
await profCache.updateCachedProfile({
...lpar1Profile,
profile: lpar2Profile.profile,
} as imperative.IProfileLoaded);
expect(refreshSpy).toHaveBeenCalledTimes(1);
});

it("updateCachedProfile should update cached profile when autoStore is false", async () => {
const profCache = new ProfilesCache(fakeLogger as unknown as imperative.Logger);
profCache.allProfiles = [lpar1Profile as imperative.IProfileLoaded];
(profCache as any).defaultProfileByType = new Map([["zosmf", { ...profCache.allProfiles[0] }]]);
expect(profCache.allProfiles[0].profile).toMatchObject(lpar1Profile.profile);
jest.spyOn(profCache, "getProfileInfo").mockResolvedValueOnce({
getTeamConfig: jest.fn().mockReturnValue({ properties: { autoStore: false } }),
} as unknown as imperative.ProfileInfo);
await profCache.updateCachedProfile({
...lpar1Profile,
profile: lpar2Profile.profile,
} as imperative.IProfileLoaded);
expect(profCache.allProfiles[0].profile).toMatchObject(lpar2Profile.profile);
expect((profCache as any).defaultProfileByType.get("zosmf").profile).toMatchObject(lpar2Profile.profile);
});

it("getDefaultProfile should find default profile given type", () => {
const profCache = new ProfilesCache(fakeLogger as unknown as imperative.Logger);
(profCache as any).defaultProfileByType = new Map([["zosmf", lpar1Profile]]);
Expand Down Expand Up @@ -566,18 +597,18 @@ describe("ProfilesCache", () => {
expect(profile).toMatchObject({ name: "lpar1", type: "base" });
});

it("fetchBaseProfile should return typeless profile if base profile does not contain token type", async () => {
it("fetchBaseProfile should return typeless profile if base profile does not contain token value", async () => {
const profCache = new ProfilesCache(fakeLogger as unknown as imperative.Logger);
jest.spyOn(profCache, "getProfileInfo").mockResolvedValue(createProfInfoMock([baseProfile]));
const profile = await profCache.fetchBaseProfile("lpar1.zosmf");
expect(profile).toMatchObject({ name: "lpar1", type: "base" });
});

it("fetchBaseProfile should return base profile if it contains token type", async () => {
it("fetchBaseProfile should return base profile if it contains token value", async () => {
const profCache = new ProfilesCache(fakeLogger as unknown as imperative.Logger);
const profInfoMock = createProfInfoMock([baseProfile]);
jest.spyOn(profCache, "getProfileInfo").mockResolvedValue(profInfoMock);
mocked(profInfoMock.getTeamConfig().api.profiles.get).mockReturnValueOnce({ tokenType: imperative.SessConstants.TOKEN_TYPE_JWT });
mocked(profInfoMock.getTeamConfig().api.secure.securePropsForProfile).mockReturnValue(["tokenValue"]);
const profile = await profCache.fetchBaseProfile("lpar1.zosmf");
expect(profile).toMatchObject(baseProfile);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import * as vscode from "vscode";
import { ZoweTreeNode } from "../../../src/tree/ZoweTreeNode";
import { IZoweTreeNode } from "../../../src/tree/IZoweTreeNode";
import * as imperative from "@zowe/imperative";
import { BaseProvider } from "../../../src";

describe("ZoweTreeNode", () => {
const makeNode = (
Expand Down Expand Up @@ -79,4 +80,32 @@ describe("ZoweTreeNode", () => {
expect(node.getProfile()).toBeUndefined();
expect(node.getProfileName()).toBeUndefined();
});

it("setProfileToChoice should update properties on existing profile object", () => {
const node = makeNode("test", vscode.TreeItemCollapsibleState.None, undefined, undefined, {
name: "oldProfile",
profile: { host: "example.com" },
});
node.setProfileToChoice({ name: "newProfile", profile: { host: "example.com", port: 443 } } as unknown as imperative.IProfileLoaded);
// Profile name should not change but properties should
expect(node.getProfileName()).toBe("oldProfile");
expect(node.getProfile().profile?.port).toBeDefined();
});

it("setProfileToChoice should update profile for associated FSProvider entry", () => {
const node = makeNode("test", vscode.TreeItemCollapsibleState.None, undefined);
const fsEntry = {
metadata: {
profile: { name: "oldProfile" },
},
};
node.setProfileToChoice(
{ name: "newProfile" } as unknown as imperative.IProfileLoaded,
{
lookup: jest.fn().mockReturnValue(fsEntry),
} as unknown as BaseProvider
);
expect(node.getProfileName()).toBe("newProfile");
expect(fsEntry.metadata.profile.name).toBe("newProfile");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ describe("ZoweVsCodeExtension", () => {
mProfileSchemaCache: new Map(),
readProfilesFromDisk: jest.fn(),
});
testCache.allProfiles = [serviceProfile, baseProfile];
jest.spyOn(testCache, "getProfileInfo").mockResolvedValue(testProfInfo);

return {
Expand Down Expand Up @@ -338,6 +339,9 @@ describe("ZoweVsCodeExtension", () => {
};

const quickPickMock = jest.spyOn(Gui, "showQuickPick").mockImplementation((items) => items[0]);
await ZoweVsCodeExtension.profilesCache.refresh({
registeredApiTypes: jest.fn().mockReturnValue(["service"]),
} as unknown as Types.IApiRegisterClient);
await ZoweVsCodeExtension.ssoLogin({ serviceProfile: "lpar.service" });

const testSession = new imperative.Session(JSON.parse(JSON.stringify(blockMocks.expectedSession.ISession)));
Expand Down Expand Up @@ -541,9 +545,6 @@ describe("ZoweVsCodeExtension", () => {

jest.spyOn(ZoweVsCodeExtension as any, "promptUserPass").mockResolvedValue(["user", "pass"]);
const quickPickMock = jest.spyOn(Gui, "showQuickPick").mockImplementation((items) => items[0]);
await ZoweVsCodeExtension.profilesCache.refresh({
registeredApiTypes: jest.fn().mockReturnValue(["service"]),
} as unknown as Types.IApiRegisterClient);
const didLogin = await ZoweVsCodeExtension.ssoLogin({
serviceProfile: serviceProfileLoaded,
defaultTokenType: "apimlAuthenticationToken",
Expand Down Expand Up @@ -633,6 +634,9 @@ describe("ZoweVsCodeExtension", () => {

const testSpy = jest.spyOn(ZoweVsCodeExtension as any, "promptUserPass").mockResolvedValue(["abc", "def"]);
const quickPickMock = jest.spyOn(Gui, "showQuickPick").mockImplementation((items) => items[0]);
await ZoweVsCodeExtension.profilesCache.refresh({
registeredApiTypes: jest.fn().mockReturnValue(["service"]),
} as unknown as Types.IApiRegisterClient);
const didLogin = await ZoweVsCodeExtension.ssoLogin({
serviceProfile: serviceProfileLoaded,
defaultTokenType: "apimlAuthenticationToken",
Expand Down Expand Up @@ -686,6 +690,7 @@ describe("ZoweVsCodeExtension", () => {
updateProperty: mockUpdateProperty,
}),
refresh: jest.fn(),
updateCachedProfile: jest.fn(),
});
const showInputBoxSpy = jest.spyOn(Gui, "showInputBox").mockResolvedValueOnce("fakeUser").mockResolvedValueOnce("fakePassword");
const saveCredentialsSpy = jest.spyOn(ZoweVsCodeExtension as any, "saveCredentials");
Expand All @@ -711,6 +716,7 @@ describe("ZoweVsCodeExtension", () => {
updateProperty: mockUpdateProperty,
}),
refresh: jest.fn(),
updateCachedProfile: jest.fn(),
});
const showInputBoxSpy = jest.spyOn(Gui, "showInputBox").mockResolvedValueOnce("fakeUser").mockResolvedValueOnce("fakePassword");
const saveCredentialsSpy = jest.spyOn(ZoweVsCodeExtension as any, "saveCredentials");
Expand Down Expand Up @@ -739,6 +745,7 @@ describe("ZoweVsCodeExtension", () => {
updateProperty: mockUpdateProperty,
}),
refresh: jest.fn(),
updateCachedProfile: jest.fn(),
});
const showInputBoxSpy = jest.spyOn(Gui, "showInputBox").mockResolvedValueOnce("fakeUser").mockResolvedValueOnce("fakePassword");
jest.spyOn(Gui, "showMessage").mockResolvedValueOnce("yes");
Expand All @@ -765,6 +772,7 @@ describe("ZoweVsCodeExtension", () => {
updateProperty: mockUpdateProperty,
}),
refresh: jest.fn(),
updateCachedProfile: jest.fn(),
});
const showInputBoxSpy = jest.spyOn(Gui, "showInputBox").mockResolvedValueOnce("fakeUser").mockResolvedValueOnce("fakePassword");
jest.spyOn(Gui, "showMessage").mockResolvedValueOnce(undefined);
Expand Down
30 changes: 26 additions & 4 deletions packages/zowe-explorer-api/src/profiles/ProfilesCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Validation } from "./Validation";
import { ZosmfProfile } from "@zowe/zosmf-for-zowe-sdk";
import { ZosTsoProfile } from "@zowe/zos-tso-for-zowe-sdk";
import { ZosUssProfile } from "@zowe/zos-uss-for-zowe-sdk";
import { Types } from "../Types";

export class ProfilesCache {
public profilesForValidation: Validation.IValidationProfile[] = [];
Expand Down Expand Up @@ -79,9 +80,8 @@ export class ProfilesCache {

/**
* Updates profile in allProfiles array and if default updates defaultProfileByType
*
* @deprecated Use `updateCachedProfile` instead
* @param {string} profileLoaded
*
* @returns {void}
*/
public updateProfilesArrays(profileLoaded: imperative.IProfileLoaded): void {
Expand All @@ -97,6 +97,25 @@ export class ProfilesCache {
}
}

public async updateCachedProfile(
profileLoaded: imperative.IProfileLoaded,
profileNode?: Types.IZoweNodeType,
zeRegister?: Types.IApiRegisterClient
): Promise<void> {
if ((await this.getProfileInfo()).getTeamConfig().properties.autoStore) {
await this.refresh(zeRegister);
} else {
// Note: When autoStore is disabled, nested profiles within this service profile may not have their credentials updated.
const profIndex = this.allProfiles.findIndex((profile) => profile.type === profileLoaded.type && profile.name === profileLoaded.name);
this.allProfiles[profIndex].profile = profileLoaded.profile;
const defaultProf = this.defaultProfileByType.get(profileLoaded.type);
if (defaultProf != null && defaultProf.name === profileLoaded.name) {
this.defaultProfileByType.set(profileLoaded.type, profileLoaded);
}
}
profileNode?.setProfileToChoice(profileLoaded);
}

/**
* This returns default profile by type from defaultProfileByType
*
Expand Down Expand Up @@ -319,11 +338,14 @@ export class ProfilesCache {
const mProfileInfo = await this.getProfileInfo();
const baseProfileAttrs = mProfileInfo.getDefaultProfile("base");
const config = mProfileInfo.getTeamConfig();
if (profileName?.includes(".") && (baseProfileAttrs == null || config.api.profiles.get(baseProfileAttrs.profName).tokenType == null)) {
if (
profileName?.includes(".") &&
(baseProfileAttrs == null || !config.api.secure.securePropsForProfile(baseProfileAttrs.profName).includes("tokenValue"))
) {
// Retrieve parent typeless profile as base profile if:
// (1) The active profile name is nested (contains a period) AND
// (2) No default base profile was found OR
// Default base profile does not have tokenType defined
// Default base profile does not have tokenValue in secure array
const parentProfile = this.getParentProfileForToken(profileName, config);
return this.getProfileLoaded(parentProfile, "base", config.api.profiles.get(parentProfile));
} else if (baseProfileAttrs == null) {
Expand Down
14 changes: 12 additions & 2 deletions packages/zowe-explorer-api/src/tree/ZoweTreeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import * as vscode from "vscode";
import * as imperative from "@zowe/imperative";
import { IZoweTreeNode } from "./IZoweTreeNode";
import type { BaseProvider } from "../fs/BaseProvider";

/**
* Common implementation of functions and methods associated with the
Expand Down Expand Up @@ -99,8 +100,17 @@ export class ZoweTreeNode extends vscode.TreeItem {
*
* @param {imperative.IProfileLoaded} The profile you will set the node to use
*/
public setProfileToChoice(aProfile: imperative.IProfileLoaded): void {
this.profile = aProfile;
public setProfileToChoice(aProfile: imperative.IProfileLoaded, fsProvider?: BaseProvider): void {
if (this.profile == null) {
this.profile = aProfile;
} else {
// Don't reassign profile, we want to keep object reference shared across nodes
this.profile.profile = aProfile.profile;
}
const fsEntry = fsProvider?.lookup(this.resourceUri, true);
if (fsEntry != null) {
fsEntry.metadata.profile = aProfile;
}
}
/**
* Sets the session for this node to the one chosen in parameters.
Expand Down
1 change: 1 addition & 0 deletions packages/zowe-explorer-api/src/tree/sorting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export namespace Sorting {
export enum JobSortOpts {
Id,
DateSubmitted,
DateCompleted,
Name,
ReturnCode,
}
Expand Down
Loading

0 comments on commit 06c3caa

Please sign in to comment.