Skip to content

Commit

Permalink
Fix: To resolve error message upon switching the authentication metho…
Browse files Browse the repository at this point in the history
…ds (#3275)

* To handle missing args in basicAuthClearSecureArray

Signed-off-by: Santhoshi Boyina <[email protected]>

* To handle missing args in tokenAuthClearSecureArray

Signed-off-by: Santhoshi Boyina <[email protected]>

* To add unit test case for missing arg's in basicAuthClearSecureArray

Signed-off-by: Santhoshi Boyina <[email protected]>

* To add unit test case for missing arg's in tokenAuthClearSecureArray

Signed-off-by: Santhoshi Boyina <[email protected]>

* To run pre-publish command

Signed-off-by: Santhoshi Boyina <[email protected]>

* To update changelog

Signed-off-by: Santhoshi Boyina <[email protected]>

* To modify tokenAuthClearSecureArray() function

Signed-off-by: Santhoshi Boyina <[email protected]>

* To add additional test cases for tokenAuthClearSecureArray()

Signed-off-by: Santhoshi Boyina <[email protected]>

---------

Signed-off-by: Santhoshi Boyina <[email protected]>
  • Loading branch information
SanthoshiBoyina1 authored Oct 24, 2024
1 parent a888e85 commit 5e1b8e3
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 10 deletions.
1 change: 1 addition & 0 deletions packages/zowe-explorer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen

- `DatasetFSProvider.stat()` will now throw a `FileNotFound` error for extenders trying to fetch an MVS resource that does not exist. [#3252](https://github.com/zowe/zowe-explorer-vscode/issues/3252)
- Fixed an issue where renaming or deleting a USS file or data set did not update the opened editor. [#3260](https://github.com/zowe/zowe-explorer-vscode/issues/3260)
- Fixed issue where switching the authentication methods would cause `Cannot read properties of undefined` error. [#3142](https://github.com/zowe/zowe-explorer-vscode/issues/3142)

## `3.0.2`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2281,4 +2281,171 @@ describe("Profiles Unit Tests - function basicAuthClearSecureArray", () => {
getProfileInfoMock.mockRestore();
getProfileFromConfigMock.mockRestore();
});

it("does not call Config.delete when user and password arg's are missing in mergeArgsForProfile", async () => {
const teamCfgMock = {
delete: jest.fn(),
save: jest.fn(),
set: jest.fn(),
};
const profAttrsMock = {
isDefaultProfile: false,
profName: "example_profile",
profType: "zosmf",
profLoc: {
jsonLoc: undefined,
},
};
const mergeArgsMock = {
knownArgs: [],
};
const getProfileInfoMock = jest.spyOn(Profiles.getInstance(), "getProfileInfo").mockResolvedValue({
getTeamConfig: jest.fn().mockReturnValue(teamCfgMock),
mergeArgsForProfile: jest.fn().mockReturnValue(mergeArgsMock),
} as any);
const getProfileFromConfigMock = jest.spyOn(Profiles.getInstance(), "getProfileFromConfig").mockResolvedValue(profAttrsMock);

await Profiles.getInstance().basicAuthClearSecureArray("example_profile");
expect(teamCfgMock.delete).not.toHaveBeenCalled();
expect(teamCfgMock.set).not.toHaveBeenCalled();
expect(teamCfgMock.save).toHaveBeenCalled();
getProfileInfoMock.mockRestore();
getProfileFromConfigMock.mockRestore();
});
});

describe("Profiles Unit Tests - function tokenAuthClearSecureArray", () => {
it("calls Config APIs when profLoc.jsonLoc is valid, no loginTokenType provided", async () => {
const teamCfgMock = {
delete: jest.fn(),
save: jest.fn(),
set: jest.fn(),
};
const profAttrsMock = {
isDefaultProfile: false,
profName: "example_profile",
profType: "zosmf",
profLoc: {
jsonLoc: "/user/path/to/zowe.config.json",
locType: imperative.ProfLocType.TEAM_CONFIG,
},
};
const mergeArgsMock = {
knownArgs: [
{
argName: "tokenType",
argLoc: {
jsonLoc: "profiles.example_profile.properties.tokenType",
},
},
{
argName: "tokenValue",
argLoc: {
jsonLoc: "profiles.example_profile.properties.tokenValue",
},
},
{
argName: "tokenExpiration",
argLoc: {
jsonLoc: "profiles.example_profile.properties.tokenExpiration",
},
},
],
};
const getProfileInfoMock = jest.spyOn(Profiles.getInstance(), "getProfileInfo").mockResolvedValue({
getTeamConfig: jest.fn().mockReturnValue(teamCfgMock),
mergeArgsForProfile: jest.fn().mockReturnValue(mergeArgsMock),
} as any);
const getProfileFromConfigMock = jest.spyOn(Profiles.getInstance(), "getProfileFromConfig").mockResolvedValue(profAttrsMock);

await Profiles.getInstance().tokenAuthClearSecureArray("example_profile");
expect(teamCfgMock.delete).toHaveBeenCalledWith(mergeArgsMock.knownArgs[0].argLoc.jsonLoc);
expect(teamCfgMock.delete).toHaveBeenCalledWith(mergeArgsMock.knownArgs[1].argLoc.jsonLoc);
expect(teamCfgMock.delete).toHaveBeenCalledWith(mergeArgsMock.knownArgs[2].argLoc.jsonLoc);
expect(teamCfgMock.set).toHaveBeenCalledWith(`${profAttrsMock.profLoc.jsonLoc}.secure`, ["user", "password"]);
expect(teamCfgMock.save).toHaveBeenCalled();
getProfileInfoMock.mockRestore();
getProfileFromConfigMock.mockRestore();
});
it("calls Config APIs when profLoc.jsonLoc is valid, loginTokenType provided", async () => {
const teamCfgMock = {
delete: jest.fn(),
save: jest.fn(),
set: jest.fn(),
};
const profAttrsMock = {
isDefaultProfile: false,
profName: "example_profile",
profType: "zosmf",
profLoc: {
jsonLoc: "/user/path/to/zowe.config.json",
locType: imperative.ProfLocType.TEAM_CONFIG,
},
};
const mergeArgsMock = {
knownArgs: [
{
argName: "tokenType",
argLoc: {
jsonLoc: "profiles.example_profile.properties.tokenType",
},
},
{
argName: "tokenValue",
argLoc: {
jsonLoc: "profiles.example_profile.properties.tokenValue",
},
},
{
argName: "tokenExpiration",
argLoc: {
jsonLoc: "profiles.example_profile.properties.tokenExpiration",
},
},
],
};
const getProfileInfoMock = jest.spyOn(Profiles.getInstance(), "getProfileInfo").mockResolvedValue({
getTeamConfig: jest.fn().mockReturnValue(teamCfgMock),
mergeArgsForProfile: jest.fn().mockReturnValue(mergeArgsMock),
} as any);
const getProfileFromConfigMock = jest.spyOn(Profiles.getInstance(), "getProfileFromConfig").mockResolvedValue(profAttrsMock);

await Profiles.getInstance().tokenAuthClearSecureArray("example_profile", "apimlAuthenticationToken");
expect(teamCfgMock.delete).toHaveBeenCalledWith(mergeArgsMock.knownArgs[0].argLoc.jsonLoc);
expect(teamCfgMock.delete).toHaveBeenCalledWith(mergeArgsMock.knownArgs[1].argLoc.jsonLoc);
expect(teamCfgMock.delete).toHaveBeenCalledWith(mergeArgsMock.knownArgs[2].argLoc.jsonLoc);
expect(teamCfgMock.set).toHaveBeenCalledWith(`${profAttrsMock.profLoc.jsonLoc}.secure`, []);
expect(teamCfgMock.save).toHaveBeenCalled();
getProfileInfoMock.mockRestore();
getProfileFromConfigMock.mockRestore();
});
it("does not call Config.delete when tokenType, tokenValue, tokenExpiration arg's are missing in mergeArgsForProfile", async () => {
const teamCfgMock = {
delete: jest.fn(),
save: jest.fn(),
set: jest.fn(),
};
const profAttrsMock = {
isDefaultProfile: false,
profName: "example_profile",
profType: "zosmf",
profLoc: {
jsonLoc: undefined,
},
};
const mergeArgsMock = {
knownArgs: [],
};
const getProfileInfoMock = jest.spyOn(Profiles.getInstance(), "getProfileInfo").mockResolvedValue({
getTeamConfig: jest.fn().mockReturnValue(teamCfgMock),
mergeArgsForProfile: jest.fn().mockReturnValue(mergeArgsMock),
} as any);
const getProfileFromConfigMock = jest.spyOn(Profiles.getInstance(), "getProfileFromConfig").mockResolvedValue(profAttrsMock);
await Profiles.getInstance().tokenAuthClearSecureArray("example_profile");
expect(teamCfgMock.delete).not.toHaveBeenCalled();
expect(teamCfgMock.set).not.toHaveBeenCalled();
expect(teamCfgMock.save).toHaveBeenCalled();
getProfileInfoMock.mockRestore();
getProfileFromConfigMock.mockRestore();
});
});
3 changes: 1 addition & 2 deletions packages/zowe-explorer/l10n/bundle.l10n.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
"Page Size:": "Page Size:",
"Page": "Page",
"No": "No",
"items": "items",
"item": "item",
"s": "s",
"selected": "selected",
"Data Sets": "Data Sets",
"Unix System Services (USS)": "Unix System Services (USS)",
"Jobs": "Jobs",
"DataPanelContext has to be used within <DataPanelContext.Provider>": "DataPanelContext has to be used within <DataPanelContext.Provider>",
"Refresh": "Refresh",
"Search History": "Search History",
"Favorites": "Favorites",
Expand Down
3 changes: 1 addition & 2 deletions packages/zowe-explorer/l10n/poeditor.json
Original file line number Diff line number Diff line change
Expand Up @@ -414,13 +414,12 @@
"Page Size:": "",
"Page": "",
"No": "",
"items": "",
"item": "",
"s": "",
"selected": "",
"Data Sets": "",
"Unix System Services (USS)": "",
"Jobs": "",
"DataPanelContext has to be used within <DataPanelContext.Provider>": "",
"Refresh": "",
"Search History": "",
"Favorites": "",
Expand Down
29 changes: 23 additions & 6 deletions packages/zowe-explorer/src/configuration/Profiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -834,8 +834,14 @@ export class Profiles extends ProfilesCache {
if (profAttrs.profLoc.jsonLoc) {
configApi.set(`${profAttrs.profLoc.jsonLoc}.secure`, loginTokenType?.startsWith("apimlAuthenticationToken") ? [] : ["tokenValue"]);
}
configApi.delete(profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "user")?.argLoc.jsonLoc);
configApi.delete(profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "password")?.argLoc.jsonLoc);
const userArgJsonLoc = profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "user")?.argLoc.jsonLoc;
if (userArgJsonLoc) {
configApi.delete(userArgJsonLoc);
}
const passwordArgJsonLoc = profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "password")?.argLoc.jsonLoc;
if (passwordArgJsonLoc) {
configApi.delete(passwordArgJsonLoc);
}
await configApi.save();
}

Expand All @@ -848,11 +854,22 @@ export class Profiles extends ProfilesCache {
// Otherwise, we want to keep `tokenValue` in the secure array of the parent profile to avoid disconnecting child profiles
if (profAttrs?.profLoc.jsonLoc) {
configApi.set(`${profAttrs.profLoc.jsonLoc}.secure`, usingApimlToken ? [] : ["user", "password"]);
configApi.delete(profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "tokenType")?.argLoc.jsonLoc);
configApi.delete(profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "tokenValue")?.argLoc.jsonLoc);
configApi.delete(profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "tokenExpiration")?.argLoc.jsonLoc);
await configApi.save();
const tokenTypeArgJsonLoc = profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "tokenType")?.argLoc.jsonLoc;
if (tokenTypeArgJsonLoc) {
configApi.delete(tokenTypeArgJsonLoc);
}
const tokenValueArgJsonLoc = profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "tokenValue")
?.argLoc.jsonLoc;
if (tokenValueArgJsonLoc) {
configApi.delete(tokenValueArgJsonLoc);
}
const tokenExpirationArgJsonLoc = profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "tokenExpiration")
?.argLoc.jsonLoc;
if (tokenExpirationArgJsonLoc) {
configApi.delete(tokenExpirationArgJsonLoc);
}
}
await configApi.save();
}

public async handleSwitchAuthentication(node: Types.IZoweNodeType): Promise<void> {
Expand Down

0 comments on commit 5e1b8e3

Please sign in to comment.