Fix #4089 Linked account cancel (#5347)

VSCode serialization changed rejection handling to only serialize errors, which caused things to break
- Changed to return either account info or a cancel message in the resolve
- Rewrote to use promises. Tracking how to return canceled through 4+ thenables was way trickier than just using a promise
- Updated unit tests to handle new scenario
- Tested integration tests, realized they a) didn't run and b) didn't passed. 
  - Added vscode dev dependency to fix run issue
  - Fixed tests to account for behavior changes in tree state.
This commit is contained in:
Kevin Cunnane
2019-05-06 09:13:03 -07:00
committed by GitHub
parent b9d985b663
commit 022761aa4b
11 changed files with 1130 additions and 145 deletions

View File

@@ -21,6 +21,7 @@ import { AccountListStatusbarItem } from 'sql/platform/accounts/browser/accountL
import { AccountProviderAddedEventParams, UpdateAccountListEventParams } from 'sql/platform/accounts/common/eventTypes';
import { IAccountManagementService } from 'sql/platform/accounts/common/interfaces';
import { Deferred } from 'sql/base/common/promise';
import { localize } from 'vs/nls';
export class AccountManagementService implements IAccountManagementService {
// CONSTANTS ///////////////////////////////////////////////////////////
@@ -127,30 +128,29 @@ export class AccountManagementService implements IAccountManagementService {
public addAccount(providerId: string): Thenable<void> {
let self = this;
return this.doWithProvider(providerId, (provider) => {
return provider.provider.prompt()
.then(account => self._accountStore.addOrUpdate(account))
.then(result => {
if (result.accountAdded) {
// Add the account to the list
provider.accounts.push(result.changedAccount);
}
if (result.accountModified) {
self.spliceModifiedAccount(provider, result.changedAccount);
}
return this.doWithProvider(providerId, async (provider) => {
let account = await provider.provider.prompt();
if (self.isCanceledResult(account)) {
return;
}
self.fireAccountListUpdate(provider, result.accountAdded);
})
.then(null, err => {
// On error, check to see if the error is because the user cancelled. If so, just ignore
if (err && 'userCancelledSignIn' in err) {
return Promise.resolve();
}
return Promise.reject(err);
});
let result = await self._accountStore.addOrUpdate(account);
if (result.accountAdded) {
// Add the account to the list
provider.accounts.push(result.changedAccount);
}
if (result.accountModified) {
self.spliceModifiedAccount(provider, result.changedAccount);
}
self.fireAccountListUpdate(provider, result.accountAdded);
});
}
private isCanceledResult(result: azdata.Account | azdata.PromptFailedResult): result is azdata.PromptFailedResult {
return (<azdata.PromptFailedResult>result).canceled;
}
/**
* Asks the requested provider to refresh an account
* @param account account to refresh
@@ -159,27 +159,32 @@ export class AccountManagementService implements IAccountManagementService {
public refreshAccount(account: azdata.Account): Thenable<azdata.Account> {
let self = this;
return this.doWithProvider(account.key.providerId, (provider) => {
return provider.provider.refresh(account)
.then(account => self._accountStore.addOrUpdate(account))
.then(result => {
if (result.accountAdded) {
// Add the account to the list
provider.accounts.push(result.changedAccount);
}
if (result.accountModified) {
// Find the updated account and splice the updated on in
let indexToRemove: number = provider.accounts.findIndex(account => {
return account.key.accountId === result.changedAccount.key.accountId;
});
if (indexToRemove >= 0) {
provider.accounts.splice(indexToRemove, 1, result.changedAccount);
}
}
return this.doWithProvider(account.key.providerId, async (provider) => {
let refreshedAccount = await provider.provider.refresh(account);
if (self.isCanceledResult(refreshedAccount)) {
// Pattern here is to throw if this fails. Handled upstream.
throw new Error(localize('refreshFailed', 'Refresh account was canceled by the user'));
} else {
account = refreshedAccount;
}
self.fireAccountListUpdate(provider, result.accountAdded);
return result.changedAccount;
let result = await self._accountStore.addOrUpdate(account);
if (result.accountAdded) {
// Add the account to the list
provider.accounts.push(result.changedAccount);
}
if (result.accountModified) {
// Find the updated account and splice the updated on in
let indexToRemove: number = provider.accounts.findIndex(account => {
return account.key.accountId === result.changedAccount.key.accountId;
});
if (indexToRemove >= 0) {
provider.accounts.splice(indexToRemove, 1, result.changedAccount);
}
}
self.fireAccountListUpdate(provider, result.accountAdded);
return result.changedAccount;
});
}