Fix race condition in account management (#14218)

This commit is contained in:
Charles Gagnon
2021-02-09 22:40:46 -08:00
committed by GitHub
parent a226c75d8c
commit d78d89e326

View File

@@ -15,11 +15,12 @@ import { IMainContext } from 'vs/workbench/api/common/extHost.protocol';
import { Event, Emitter } from 'vs/base/common/event';
import { values } from 'vs/base/common/collections';
type ProviderAndAccount = { provider: azdata.AccountProvider, account: azdata.Account };
export class ExtHostAccountManagement extends ExtHostAccountManagementShape {
private _handlePool: number = 0;
private _proxy: MainThreadAccountManagementShape;
private _providers: { [handle: number]: AccountProviderWithMetadata } = {};
private _accounts: { [handle: number]: azdata.Account[] } = {};
private readonly _onDidChangeAccounts = new Emitter<azdata.DidChangeAccountsParams>();
constructor(mainContext: IMainContext) {
@@ -62,14 +63,19 @@ export class ExtHostAccountManagement extends ExtHostAccountManagementShape {
this._proxy.$accountUpdated(updatedAccount);
}
public $getAllAccounts(): Thenable<azdata.Account[]> {
return this.getAllProvidersAndAccounts().then(providersAndAccounts => {
return providersAndAccounts.map(providerAndAccount => providerAndAccount.account);
});
}
private async getAllProvidersAndAccounts(): Promise<ProviderAndAccount[]> {
if (Object.keys(this._providers).length === 0) {
throw new Error('No account providers registered.');
}
this._accounts = {};
const resultAccounts: azdata.Account[] = [];
const resultProviderAndAccounts: ProviderAndAccount[] = [];
const promises: Thenable<void>[] = [];
@@ -79,37 +85,31 @@ export class ExtHostAccountManagement extends ExtHostAccountManagementShape {
const provider = this._providers[providerHandle];
promises.push(this._proxy.$getAccountsForProvider(provider.metadata.id).then(
(accounts) => {
this._accounts[providerHandle] = accounts;
resultAccounts.push(...accounts);
resultProviderAndAccounts.push(...accounts.map(account => { return { provider: provider.provider, account }; }));
}
));
}
return Promise.all(promises).then(() => resultAccounts);
await Promise.all(promises);
return resultProviderAndAccounts;
}
public $getSecurityToken(account: azdata.Account, resource: azdata.AzureResource = AzureResource.ResourceManagement): Thenable<{}> {
return this.$getAllAccounts().then(() => {
for (const handle in this._accounts) {
const providerHandle = parseInt(handle);
if (this._accounts[handle].findIndex((acct) => acct.key.accountId === account.key.accountId) !== -1) {
return this._withProvider(providerHandle, (provider: azdata.AccountProvider) => provider.getSecurityToken(account, resource));
}
return this.getAllProvidersAndAccounts().then(providerAndAccounts => {
const providerAndAccount = providerAndAccounts.find(providerAndAccount => providerAndAccount.account.key.accountId === account.key.accountId);
if (providerAndAccount) {
return providerAndAccount.provider.getSecurityToken(account, resource);
}
throw new Error(`Account ${account.key.accountId} not found.`);
});
}
public $getAccountSecurityToken(account: azdata.Account, tenant: string, resource: azdata.AzureResource = AzureResource.ResourceManagement): Thenable<{ token: string }> {
return this.$getAllAccounts().then(() => {
for (const handle in this._accounts) {
const providerHandle = parseInt(handle);
if (this._accounts[handle].findIndex((acct) => acct.key.accountId === account.key.accountId) !== -1) {
return this._withProvider(providerHandle, (provider: azdata.AccountProvider) => provider.getAccountSecurityToken(account, tenant, resource));
}
return this.getAllProvidersAndAccounts().then(providerAndAccounts => {
const providerAndAccount = providerAndAccounts.find(providerAndAccount => providerAndAccount.account.key.accountId === account.key.accountId);
if (providerAndAccount) {
return providerAndAccount.provider.getAccountSecurityToken(account, tenant, resource);
}
throw new Error(`Account ${account.key.accountId} not found.`);
});
}