Azure core | Include alternate library accounts if found (#21565)

This commit is contained in:
Cheena Malhotra
2023-01-11 16:05:20 -08:00
committed by GitHub
parent 16740ba61f
commit 9708b470c7
3 changed files with 77 additions and 41 deletions

View File

@@ -51,10 +51,10 @@ import { IAccountManagementService } from 'sql/platform/accounts/common/interfac
export const VIEWLET_ID = 'workbench.view.accountpanel';
export type AuthLibrary = 'ADAL' | 'MSAL';
export const MSAL_AUTH_LIBRARY: AuthLibrary = 'MSAL'; // default
export const ADAL_AUTH_LIBRARY: AuthLibrary = 'ADAL';
export class AccountPaneContainer extends ViewPaneContainer {
}
export class AccountPaneContainer extends ViewPaneContainer { }
export const ACCOUNT_VIEW_CONTAINER = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({
id: VIEWLET_ID,
@@ -499,19 +499,10 @@ export class AccountDialog extends Modal {
export function filterAccounts(accounts: azdata.Account[], authLibrary: AuthLibrary): azdata.Account[] {
let filteredAccounts = accounts.filter(account => {
if (account.key.authLibrary) {
if (account.key.authLibrary === authLibrary) {
return true;
} else {
return false;
}
return account.key.authLibrary === authLibrary;
} else {
if (authLibrary === 'ADAL') {
return true;
} else {
return false;
}
return authLibrary === ADAL_AUTH_LIBRARY;
}
});
return filteredAccounts;
}

View File

@@ -26,7 +26,7 @@ import { INotificationService, Severity, INotification } from 'vs/platform/notif
import { Action } from 'vs/base/common/actions';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { AuthLibrary, filterAccounts } from 'sql/workbench/services/accountManagement/browser/accountDialog';
import { ADAL_AUTH_LIBRARY, AuthLibrary, filterAccounts, MSAL_AUTH_LIBRARY } from 'sql/workbench/services/accountManagement/browser/accountDialog';
export class AccountManagementService implements IAccountManagementService {
// CONSTANTS ///////////////////////////////////////////////////////////
@@ -168,6 +168,28 @@ export class AccountManagementService implements IAccountManagementService {
});
}
/**
* Adds an account to the account store without prompting the user
* @param account account to add
*/
public addAccountWithoutPrompt(account: azdata.Account): Promise<void> {
return this.doWithProvider(account.key.providerId, async (provider) => {
let result = await this._accountStore.addOrUpdate(account);
if (!result) {
this._logService.error('adding account failed');
}
if (result.accountAdded) {
// Add the account to the list
provider.accounts.push(result.changedAccount);
}
if (result.accountModified) {
this.spliceModifiedAccount(provider, result.changedAccount);
}
this.fireAccountListUpdate(provider, result.accountAdded);
});
}
private isCanceledResult(result: azdata.Account | azdata.PromptFailedResult): result is azdata.PromptFailedResult {
return (<azdata.PromptFailedResult>result).canceled;
}
@@ -504,35 +526,58 @@ export class AccountManagementService implements IAccountManagementService {
private registerListeners(): void {
this.disposables.add(this.configurationService.onDidChangeConfiguration(async e => {
if (e.affectsConfiguration('azure.authenticationLibrary')) {
const authLibrary: AuthLibrary = this.configurationService.getValue('azure.authenticationLibrary');
if (authLibrary) {
let accounts = await this._accountStore.getAllAccounts();
if (accounts) {
let updatedAccounts = filterAccounts(accounts, authLibrary);
let eventArg: UpdateAccountListEventParams;
if (updatedAccounts.length > 0) {
updatedAccounts.forEach(account => {
if (account.key.authLibrary === 'MSAL') {
account.isStale = false;
}
});
eventArg = {
providerId: updatedAccounts[0].key.providerId,
accountList: updatedAccounts
};
} else { // default to public cloud if no accounts
eventArg = {
providerId: 'azure_publicCloud',
accountList: updatedAccounts
};
}
this._updateAccountListEmitter.fire(eventArg);
const authLibrary: AuthLibrary = this.configurationService.getValue('azure.authenticationLibrary') ?? MSAL_AUTH_LIBRARY;
let accounts = await this._accountStore.getAllAccounts();
if (accounts) {
let updatedAccounts = await this.filterAndMergeAccounts(accounts, authLibrary);
let eventArg: UpdateAccountListEventParams;
if (updatedAccounts.length > 0) {
updatedAccounts.forEach(account => {
if (account.key.authLibrary === MSAL_AUTH_LIBRARY) {
account.isStale = false;
}
});
eventArg = {
providerId: updatedAccounts[0].key.providerId,
accountList: updatedAccounts
};
} else { // default to public cloud if no accounts
eventArg = {
providerId: 'azure_publicCloud',
accountList: updatedAccounts
};
}
this._updateAccountListEmitter.fire(eventArg);
}
}
}));
}
// Filters and merges accounts from both authentication libraries
private async filterAndMergeAccounts(accounts: azdata.Account[], currentAuthLibrary: AuthLibrary): Promise<azdata.Account[]> {
// Fetch accounts for alternate authenticationLibrary
const altLibrary = currentAuthLibrary === MSAL_AUTH_LIBRARY ? ADAL_AUTH_LIBRARY : MSAL_AUTH_LIBRARY;
const altLibraryAccounts = filterAccounts(accounts, altLibrary);
// Fetch accounts for current authenticationLibrary
const currentLibraryAccounts = filterAccounts(accounts, currentAuthLibrary);
// In the list of alternate accounts, check if the accounts are present in the current library cache,
// if not, add the account and mark it stale. The original account is marked as taken so its not picked again.
for (let account of altLibraryAccounts) {
await this.removeAccount(account.key);
if (currentLibraryAccounts.find(a => account.displayInfo.email === a.displayInfo.email)) {
continue;
} else {
// TODO: Refresh access token for the account if feasible.
account.isStale = true;
account.key.authLibrary = currentAuthLibrary;
currentLibraryAccounts.push(account);
await this.addAccountWithoutPrompt(account);
}
}
return currentLibraryAccounts;
}
}
/**