diff --git a/src/sql/platform/accounts/common/accountStore.ts b/src/sql/platform/accounts/common/accountStore.ts index 837b9a888d..b4d96d7340 100644 --- a/src/sql/platform/accounts/common/accountStore.ts +++ b/src/sql/platform/accounts/common/accountStore.ts @@ -8,15 +8,20 @@ import { AccountAdditionResult } from 'sql/platform/accounts/common/eventTypes'; import { IAccountStore } from 'sql/platform/accounts/common/interfaces'; import { deepClone } from 'vs/base/common/objects'; import { firstIndex } from 'vs/base/common/arrays'; +import { ILogService } from 'vs/platform/log/common/log'; export default class AccountStore implements IAccountStore { + private readonly deprecatedProviders = ['azurePublicCloud']; // CONSTANTS /////////////////////////////////////////////////////////// public static MEMENTO_KEY: string = 'Microsoft.SqlTools.Accounts'; // MEMBER VARIABLES //////////////////////////////////////////////////// private _activeOperation?: Thenable; - constructor(private _memento: { [key: string]: any }) { } + constructor( + private _memento: { [key: string]: any }, + @ILogService readonly logService: ILogService + ) { } // PUBLIC METHODS ////////////////////////////////////////////////////// public addOrUpdate(newAccount: azdata.Account): Thenable { @@ -43,10 +48,37 @@ export default class AccountStore implements IAccountStore { public getAllAccounts(): Thenable { return this.doOperation(() => { - return this.readFromMemento(); + return this.cleanupDeprecatedAccounts().then(() => { + return this.readFromMemento(); + }); }); } + public cleanupDeprecatedAccounts(): Thenable { + return this.readFromMemento() + .then(accounts => { + // No need to waste cycles + if (!accounts || accounts.length === 0) { + return Promise.resolve(); + } + // Remove old accounts that are now deprecated + try { + accounts = accounts.filter(account => { + const providerKey = account?.key?.providerId; + // Account has no provider, remove it. + if (providerKey === undefined) { + return false; + } + // Returns true if the account isn't from a deprecated provider + return !this.deprecatedProviders.includes(providerKey); + }); + } catch (ex) { + this.logService.error(ex); + return Promise.resolve(); + } + return this.writeToMemento(accounts); + }); + } public remove(key: azdata.AccountKey): Thenable { return this.doOperation(() => { diff --git a/src/sql/platform/accounts/test/common/accountStore.test.ts b/src/sql/platform/accounts/test/common/accountStore.test.ts index 1cd6ee9e22..7aa787d3e3 100644 --- a/src/sql/platform/accounts/test/common/accountStore.test.ts +++ b/src/sql/platform/accounts/test/common/accountStore.test.ts @@ -7,12 +7,14 @@ import * as assert from 'assert'; import * as azdata from 'azdata'; import AccountStore from 'sql/platform/accounts/common/accountStore'; import { EventVerifierSingle } from 'sql/base/test/common/event'; +import { ConsoleLogService } from 'vs/platform/log/common/log'; +const consoleLogService = new ConsoleLogService; suite('Account Store Tests', () => { test('AddOrUpdate - Uninitialized memento', () => { // Setup: Create account store w/o initialized memento let memento: { [key: string]: azdata.Account[] } = {}; - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I add an account to the store return as.addOrUpdate(account1) @@ -34,7 +36,7 @@ suite('Account Store Tests', () => { // Setup: Create account store with initialized memento with accounts let memento: { [key: string]: azdata.Account[] } = {}; memento[AccountStore.MEMENTO_KEY] = []; - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I add an account to the store return as.addOrUpdate(account1) @@ -55,7 +57,7 @@ suite('Account Store Tests', () => { test('AddOrUpdate - Updates account', () => { // Setup: Create account store with initialized memento with accounts let memento = getTestMemento(); - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I add an account to the store that already exists let param = { @@ -82,7 +84,7 @@ suite('Account Store Tests', () => { test('GetAccountsByProvider - Uninitialized memento', () => { // Setup: Create account store w/o initialized memento let memento = {}; - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I get accounts by provider return as.getAccountsByProvider('azure') @@ -101,7 +103,7 @@ suite('Account Store Tests', () => { // Setup: Create account store with initialized memento with accounts let memento: { [key: string]: azdata.Account[] } = {}; memento[AccountStore.MEMENTO_KEY] = []; - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I get accounts when there aren't any accounts return as.getAccountsByProvider('azure') @@ -115,7 +117,7 @@ suite('Account Store Tests', () => { test('GetAccountsByProvider - Accounts, but no accounts for provider', () => { // Setup: Create account store with initialized memento with accounts let memento = getTestMemento(); - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I get accounts by provider that doesn't have accounts return as.getAccountsByProvider('cloudycloud') @@ -129,7 +131,7 @@ suite('Account Store Tests', () => { test('GetAccountsByProvider - Accounts for provider', () => { // Setup: Create account store with initialized memento with accounts let memento = getTestMemento(); - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I get accounts by provider that has accounts return as.getAccountsByProvider('azure') @@ -145,7 +147,7 @@ suite('Account Store Tests', () => { test('GetAllAccounts - Uninitialized memento', () => { // Setup: Create account store w/o initialized memento let memento = {}; - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I get accounts return as.getAllAccounts() @@ -164,7 +166,7 @@ suite('Account Store Tests', () => { // Setup: Create account store with initialized memento with accounts let memento: { [key: string]: azdata.Account[] } = {}; memento[AccountStore.MEMENTO_KEY] = []; - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I get accounts when there aren't any accounts return as.getAllAccounts() @@ -178,7 +180,7 @@ suite('Account Store Tests', () => { test('GetAllAccounts - Accounts', () => { // Setup: Create account store with initialized memento with accounts let memento = getTestMemento(); - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I get accounts return as.getAllAccounts() @@ -194,7 +196,7 @@ suite('Account Store Tests', () => { test('Remove - Uninitialized menento', () => { // Setup: Create account store w/o initialized memento let memento: { [key: string]: azdata.Account[] } = {}; - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I remove an account when there's an uninitialized memento return as.remove(account1.key) @@ -213,7 +215,7 @@ suite('Account Store Tests', () => { // Setup: Create account store with initialized memento with accounts let memento: { [key: string]: azdata.Account[] } = {}; memento[AccountStore.MEMENTO_KEY] = []; - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I remove an account that doesn't exist return as.remove({ providerId: 'cloudyCloud', accountId: 'testyTest' }) @@ -231,7 +233,7 @@ suite('Account Store Tests', () => { test('Remove - Account exists', () => { // Setup: Create account store with initialized memento with accounts let memento = getTestMemento(); - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // If: I remove an account that does exist return as.remove(account1.key) @@ -251,7 +253,7 @@ suite('Account Store Tests', () => { // Setup: // ... Create account store w/o initialized memento let memento: { [key: string]: azdata.Account[] } = {}; - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // ... Create a callback that we can verify was called let updateCallback = new EventVerifierSingle(); @@ -276,7 +278,7 @@ suite('Account Store Tests', () => { // Setup: Create account store with initialized memento with accounts let memento: { [key: string]: azdata.Account[] } = {}; memento[AccountStore.MEMENTO_KEY] = []; - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // ... Create a callback that we can verify was called let updateCallback = new EventVerifierSingle(); @@ -300,7 +302,7 @@ suite('Account Store Tests', () => { test('Update - Account exists', () => { // Setup: Create account store with initialized memento with accounts let memento = getTestMemento(); - let as = new AccountStore(memento); + let as = new AccountStore(memento, consoleLogService); // ... Create a callback to update the account let newDisplayName = 'Display Name Changed!'; @@ -327,6 +329,19 @@ suite('Account Store Tests', () => { }); }); + test('Remove - Deprecated Account', () => { + let memento = getTestMemento(); + memento[AccountStore.MEMENTO_KEY].push(deprecatedAccount1, deprecatedAccount2); + let as = new AccountStore(memento, consoleLogService); + // We know that we have 4 accounts now + assert.equal(memento[AccountStore.MEMENTO_KEY].length, 4); + + return as.getAllAccounts().then(accounts => { + // After pruning we will have 2 accounts + assert.equal(accounts.length, 2); + }); + }); + // TODO: Test to make sure operations occur sequentially }); @@ -357,6 +372,32 @@ const account2 = { isStale: false }; +const deprecatedAccount1 = { + key: { + providerId: 'azurePublicCloud', + accountId: 'testDeprecatedAccount1' + }, + displayInfo: { + displayName: 'Test Deprecated Account', + accountType: 'test', + contextualDisplayName: 'Azure Account' + }, + isStale: false +}; + +const deprecatedAccount2 = { + key: { + providerId: 'azurePublicCloud', + accountId: 'testDeprecatedAccount2' + }, + displayInfo: { + displayName: 'Test Deprecated Account 2', + accountType: 'test', + contextualDisplayName: 'Azure Account' + }, + isStale: false +}; + function getTestMemento() { let memento: { [key: string]: azdata.Account[] } = {}; memento[AccountStore.MEMENTO_KEY] = [account1, account2];