Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ignore expired orgs #5729

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export class WorkspaceContextUtil {
this._orgId = '';
if (error instanceof Error) {
console.log(
'There was an problem getting the orgId of the default org: ',
'There was a problem getting the orgId of the default org: ',
error
);
TelemetryService.getInstance().sendException(
Expand Down
38 changes: 16 additions & 22 deletions packages/salesforcedx-vscode-core/src/orgPicker/orgList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { AuthFields, AuthInfo, OrgAuthorization } from '@salesforce/core-bundle';
import {
AuthFields,
AuthInfo,
OrgAuthorization
} from '@salesforce/core-bundle';
import {
CancelResponse,
ConfigUtil,
ContinueResponse,
OrgUserInfo
} from '@salesforce/salesforcedx-utils-vscode';
Expand Down Expand Up @@ -61,7 +64,6 @@ export class OrgList implements vscode.Disposable {
const targetDevHub = await OrgAuthInfo.getDevHubUsername();

const authList = [];
const today = new Date();
for (const orgAuth of orgAuthorizations) {
// When this is called right after logging out of an org, there can
// still be a cached Org Auth in the list with a "No auth information found"
Expand All @@ -88,34 +90,26 @@ export class OrgList implements vscode.Disposable {
// scratch orgs parented by other (non-default) devHub orgs
continue;
}
const isExpired =
authFields && authFields.expirationDate
? today >= new Date(authFields.expirationDate)
: false;

const aliases = await ConfigUtil.getAllAliasesFor(orgAuth.username);
let authListItem =
aliases && aliases.length > 0
? `${aliases.join(',')} - ${orgAuth.username}`
: orgAuth.username;

if (isExpired) {
authListItem += ` - ${nls.localize(
'org_expired'
)} ${String.fromCodePoint(0x274c)}`; // cross-mark
if (orgAuth.isExpired === true) {
// If the scratch org is expired we don't want to see it in the org picker
continue;
}
const aliases = orgAuth.aliases || [];
const authListItem =
aliases.length > 0
? `${aliases.join(',')} - ${orgAuth.username}`
: orgAuth.username;

authList.push(authListItem);
}
return authList;
}

public async updateOrgList(): Promise<string[]> {
const orgAuthorizations = await this.getOrgAuthorizations();
if (orgAuthorizations && orgAuthorizations.length === 0) {
return [];
}
const authUsernameList = await this.filterAuthInfo(orgAuthorizations);
const authUsernameList = await this.filterAuthInfo(
mingxuanzhangsfdx marked this conversation as resolved.
Show resolved Hide resolved
await this.getOrgAuthorizations()
);
return authUsernameList;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { AuthFields, OrgAuthorization } from '@salesforce/core-bundle';
import * as vscode from 'vscode';
import { OrgList } from '../../../src/orgPicker';
import { OrgAuthInfo } from '../../../src/util';

describe('OrgList - filterAuthInfo', () => {
let orgList: OrgList;
let createFileSystemWatcherMock: jest.SpyInstance;
let getDevHubUsernameMock: jest.SpyInstance;
let getAuthFieldsForMock: jest.SpyInstance;
let mockWatcher: any;

const dummyDevHubUsername = '[email protected]';

const createOrgAuthorization = (
overrides: Partial<OrgAuthorization> = {}
): OrgAuthorization => ({
orgId: '000',
username: '[email protected]',
oauthMethod: 'unknown',
aliases: [],
configs: [],
isScratchOrg: undefined,
isDevHub: undefined,
isSandbox: undefined,
instanceUrl: undefined,
accessToken: undefined,
error: undefined,
isExpired: false,
...overrides
});

beforeEach(() => {
mockWatcher = {
onDidChange: jest.fn(),
onDidCreate: jest.fn(),
onDidDelete: jest.fn()
};
createFileSystemWatcherMock = (
vscode.workspace.createFileSystemWatcher as any
).mockReturnValue(mockWatcher);
(vscode.window.createStatusBarItem as jest.Mock).mockReturnValue({
command: '',
text: '',
tooltip: '',
show: jest.fn(),
dispose: jest.fn()
});
orgList = new OrgList();
getAuthFieldsForMock = jest.spyOn(OrgList.prototype, 'getAuthFieldsFor');
getDevHubUsernameMock = jest.spyOn(OrgAuthInfo, 'getDevHubUsername');
});

afterEach(() => {
jest.clearAllMocks();
});

it('should filter out orgs with the scratchAdminUsername field', async () => {
const orgAuth = createOrgAuthorization();
const orgAuths = [orgAuth];
getAuthFieldsForMock.mockResolvedValueOnce({
scratchAdminUsername: '[email protected]'
} as AuthFields);
getDevHubUsernameMock.mockResolvedValueOnce(null);

const result = await orgList.filterAuthInfo(orgAuths);

expect(result).toEqual([]);
});

it('should filter out scratch orgs parented by non-default Dev Hubs', async () => {
const orgAuth = createOrgAuthorization({ isScratchOrg: true });
const orgAuths = [orgAuth];
getAuthFieldsForMock.mockResolvedValueOnce({
devHubUsername: '[email protected]'
} as AuthFields);
getDevHubUsernameMock.mockResolvedValueOnce(dummyDevHubUsername);

const result = await orgList.filterAuthInfo(orgAuths);

expect(result).toEqual([]);
});

it('should filter out expired orgs', async () => {
const expiredOrgAuth = createOrgAuthorization({
username: '[email protected]',
isExpired: true
});
const orgAuths = [expiredOrgAuth];
getAuthFieldsForMock.mockResolvedValueOnce({} as AuthFields);
getDevHubUsernameMock.mockResolvedValueOnce(dummyDevHubUsername);

const result = await orgList.filterAuthInfo(orgAuths);

expect(result).toEqual([]);
});

it('should include aliases in the result if available', async () => {
const orgAuth = createOrgAuthorization({
username: '[email protected]',
aliases: ['alias1']
});
const orgAuths = [orgAuth];
getAuthFieldsForMock.mockResolvedValueOnce({} as AuthFields);
getDevHubUsernameMock.mockResolvedValueOnce(null);

const result = await orgList.filterAuthInfo(orgAuths);

expect(result).toEqual(['alias1 - [email protected]']);
});

it('should filter out org authorizations with errors', async () => {
const orgAuthWithError = createOrgAuthorization({
username: '[email protected]',
error: 'Some error'
});
const orgAuths = [orgAuthWithError];
getAuthFieldsForMock.mockResolvedValueOnce({} as AuthFields);
getDevHubUsernameMock.mockResolvedValueOnce(null);

const result = await orgList.filterAuthInfo(orgAuths);

expect(result).toEqual([]);
});

it('should return a list of valid org authorizations', async () => {
const validOrgAuth = createOrgAuthorization({
username: '[email protected]'
});
const orgAuths = [validOrgAuth];
getAuthFieldsForMock.mockResolvedValueOnce({} as AuthFields);
getDevHubUsernameMock.mockResolvedValueOnce(dummyDevHubUsername);

const result = await orgList.filterAuthInfo(orgAuths);

expect(result).toEqual(['[email protected]']);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { AuthInfo, OrgAuthorization, StateAggregator } from '@salesforce/core-bundle';
import { ConfigUtil } from '@salesforce/salesforcedx-utils-vscode';
import {
AuthInfo,
OrgAuthorization,
StateAggregator
} from '@salesforce/core-bundle';
import { expect } from 'chai';
import { createSandbox, SinonStub } from 'sinon';
import * as vscode from 'vscode';
Expand All @@ -14,7 +17,6 @@ import { OrgList } from '../../../src/orgPicker';
import * as util from '../../../src/util';
import { OrgAuthInfo } from '../../../src/util';

const AN_ALIAS = 'anAlias';
const sandbox = createSandbox();

describe('orgList Tests', () => {
Expand All @@ -35,8 +37,8 @@ describe('orgList Tests', () => {
it('should return a list of FileInfo objects when given an array of file names', async () => {
// Arrange
const authFilesArray = [
{ username: '[email protected]' },
{ username: '[email protected]' }
{ username: '[email protected]', aliases: ['alias1'] },
{ username: '[email protected]', aliases: ['alias2'] }
];
getAuthInfoListAllAuthorizationsStub.resolves(authFilesArray);
const orgList = new OrgList();
Expand Down Expand Up @@ -67,7 +69,6 @@ describe('orgList Tests', () => {
let getUsernameStub: SinonStub;
let stateAggregatorCreateStub: SinonStub;
let getAllStub: SinonStub;
let getAllAliasesForStub: SinonStub;
let getAuthFieldsForStub: SinonStub;
const orgList = new OrgList();

Expand All @@ -87,7 +88,6 @@ describe('orgList Tests', () => {
.stub(StateAggregator, 'create')
.resolves(fakeStateAggregator);

getAllAliasesForStub = sandbox.stub(ConfigUtil, 'getAllAliasesFor');
getAuthFieldsForStub = sandbox.stub(
OrgList.prototype,
'getAuthFieldsFor'
Expand Down Expand Up @@ -116,7 +116,8 @@ describe('orgList Tests', () => {

const dummyOrgAuth1 = getFakeOrgAuthorization({
orgId: '000',
username: '[email protected]'
username: '[email protected]',
aliases: ['alias1']
});
const dummyOrgAuth2 = getFakeOrgAuthorization({
orgId: '111',
Expand All @@ -129,13 +130,15 @@ describe('orgList Tests', () => {
});
const dummyScratchOrgAuth2 = getFakeOrgAuthorization({
orgId: '111',
username: '[email protected]'
username: '[email protected]',
aliases: ['anAlias']
});
const dummyScratchOrgAuthWithError = getFakeOrgAuthorization({
orgId: '222',
username: '[email protected]',
error:
'No authorization information found for [email protected].'
'No authorization information found for [email protected].',
aliases: ['anAlias']
});

const dummyDevHubUsername1 = '[email protected]';
Expand Down Expand Up @@ -209,17 +212,13 @@ describe('orgList Tests', () => {
.returns({
devHubUsername: dummyDevHubUsername1
});
getAllAliasesForStub
.withArgs(authInfoObjectsWithOneError[0].username)
.returns([AN_ALIAS]);
getDevHubUsernameStub.resolves(dummyDevHubUsername1);

const authList = await orgList.filterAuthInfo(
authInfoObjectsWithOneError
);
expect(getDevHubUsernameStub.calledOnce).to.equal(true);
expect(authList.length).to.equal(1);
expect(authList[0].includes(AN_ALIAS)).to.equal(true);
expect(authList[0].includes(dummyScratchOrgAuth1.username)).to.equal(
true
);
Expand All @@ -233,9 +232,6 @@ describe('orgList Tests', () => {
dummyOrgAuth2
];
getAllStub.withArgs(dummyOrgAuth1.username).returns(['alias1']);
getAllAliasesForStub
.withArgs(dummyOrgAuth1.username)
.returns(['alias1']);
getAuthFieldsForStub.withArgs(authInfoObjects[0].username).returns({});

// Act
Expand All @@ -245,7 +241,7 @@ describe('orgList Tests', () => {
expect(authList[0]).to.equal('alias1 - [email protected]');
});

it('should flag the org as expired if expiration date has passed', async () => {
it('should filter the list to ignore expired orgs', async () => {
CristiCanizales marked this conversation as resolved.
Show resolved Hide resolved
const oneDayMillis = 60 * 60 * 24 * 1000;
const today = new Date();
const yesterday = new Date(today.getTime() - oneDayMillis);
Expand All @@ -254,15 +250,18 @@ describe('orgList Tests', () => {
const authInfoObjects: OrgAuthorization[] = [
getFakeOrgAuthorization({
orgId: '000',
username: '[email protected]'
username: '[email protected]',
isExpired: true
}),
getFakeOrgAuthorization({
orgId: '111',
username: '[email protected]'
username: '[email protected]',
isExpired: true
}),
getFakeOrgAuthorization({
orgId: '222',
username: '[email protected]'
username: '[email protected]',
isExpired: false
})
];

Expand Down Expand Up @@ -290,19 +289,11 @@ describe('orgList Tests', () => {

const authList = await orgList.filterAuthInfo(authInfoObjects);

expect(authList[0]).to.equal(
'[email protected] - ' +
nls.localize('org_expired') +
' ' +
String.fromCodePoint(0x274c)
);
expect(authList[1]).to.equal(
'[email protected] - ' +
nls.localize('org_expired') +
' ' +
String.fromCodePoint(0x274c)
expect(authList).to.not.contain('[email protected]');
expect(authList).to.not.contain(
'[email protected]'
);
expect(authList[2]).to.equal('[email protected]');
expect(authList[0]).to.equal('[email protected]');
});
});
describe('Set Default Org', () => {
Expand Down
Loading