mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Added reset password dialog upon SQL Server expired password error (#21295)
* Added initial password connection dialog box * made small changes * more preliminary work * more WIP changes * more cleanup done * added dialog instantiation * added placeholder dialog window * added changePasswordController * made some changes to changePasswordController * some changes made * added more changes * more changes made to dialogue * added password confirm box * added WIP change password function * small changes made to API * small changes for test * added uri * added valid password * added TODO comments * added small change to connectionManagementService * added connectionManagementService password change * added comment on what to do next * made some simplification of change password * added response callback * added fixes to protocol * added throw error for passwordChangeResult * WIP added call to self after password change * WIP changes to implementing new password change dialog * added changes to passwordChangeDialog * added launchChangePasswordDialog * remove erroneous css * added working dialog * removed old password change dialog * fixed space * added checkbox option to passwordChangeDialog * added test signatures * added error handling * added some changes * added changes to HTML for passwordChangeDialog * added CSS to passwordChangeDialog * added display none for matching passwords * added documentation changes * small cleanup * added working error catch and retry * added await * added recovery instructions * Added ok button hide for button click. * added loading spinner * fixed for semicolon * added updated message * Added message change * added minor fixes * added small fixes * made more changes * renamed messages to errorDetails * added styling to passwordChangeDialog * simplified error message * changed comment * modified azdata to be consistent * small changes * change to azdata for consistency * added clarification for provider * removed additional instructions * Added new dialog title * addressed feedback * added comments * added changes
This commit is contained in:
19
src/sql/azdata.proposed.d.ts
vendored
19
src/sql/azdata.proposed.d.ts
vendored
@@ -403,6 +403,25 @@ declare module 'azdata' {
|
|||||||
title: string;
|
title: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ConnectionProvider extends DataProvider {
|
||||||
|
/**
|
||||||
|
* Changes a user's password for the scenario of password expiration during SQL Authentication. (for Azure Data Studio use only)
|
||||||
|
*/
|
||||||
|
changePassword?(connectionUri: string, connectionInfo: ConnectionInfo, newPassword: string): Thenable<PasswordChangeResult>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Password Change Request ----------------------------------------------------------------------
|
||||||
|
export interface PasswordChangeResult {
|
||||||
|
/**
|
||||||
|
* Whether the password change was successful
|
||||||
|
*/
|
||||||
|
result: boolean;
|
||||||
|
/**
|
||||||
|
* Error message if the password change was unsuccessful
|
||||||
|
*/
|
||||||
|
errorMessage?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IConnectionProfile extends ConnectionInfo {
|
export interface IConnectionProfile extends ConnectionInfo {
|
||||||
/**
|
/**
|
||||||
* The type of authentication to use when connecting
|
* The type of authentication to use when connecting
|
||||||
|
|||||||
@@ -119,6 +119,11 @@ export interface IConnectionManagementService {
|
|||||||
*/
|
*/
|
||||||
connectAndSaveProfile(connection: IConnectionProfile, uri: string, options?: IConnectionCompletionOptions, callbacks?: IConnectionCallbacks): Promise<IConnectionResult>;
|
connectAndSaveProfile(connection: IConnectionProfile, uri: string, options?: IConnectionCompletionOptions, callbacks?: IConnectionCallbacks): Promise<IConnectionResult>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes password of the connection profile's user.
|
||||||
|
*/
|
||||||
|
changePassword(connection: IConnectionProfile, uri: string, newPassword: string): Promise<azdata.PasswordChangeResult>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces a connectioninfo's associated uri with a new uri.
|
* Replaces a connectioninfo's associated uri with a new uri.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -65,3 +65,6 @@ export const UNSAVED_GROUP_ID = 'unsaved';
|
|||||||
/* Server Type Constants */
|
/* Server Type Constants */
|
||||||
export const sqlDataWarehouse = 'Azure SQL Data Warehouse';
|
export const sqlDataWarehouse = 'Azure SQL Data Warehouse';
|
||||||
export const gen3Version = 12;
|
export const gen3Version = 12;
|
||||||
|
|
||||||
|
/* SQL Server Password Reset Error Code */
|
||||||
|
export const sqlPasswordErrorCode = 18488;
|
||||||
|
|||||||
@@ -180,6 +180,10 @@ export class TestConnectionManagementService implements IConnectionManagementSer
|
|||||||
return new Promise<IConnectionResult>(() => true);
|
return new Promise<IConnectionResult>(() => true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changePassword(connection: IConnectionProfile, uri: string, newPassword: string): Promise<azdata.PasswordChangeResult> {
|
||||||
|
return Promise.resolve(undefined!);
|
||||||
|
}
|
||||||
|
|
||||||
disconnectEditor(owner: IConnectableInput): Promise<boolean> {
|
disconnectEditor(owner: IConnectableInput): Promise<boolean> {
|
||||||
return new Promise<boolean>(() => true);
|
return new Promise<boolean>(() => true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ export class TestConnectionProvider implements azdata.ConnectionProvider {
|
|||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changePassword(connectionUri: string, connectionInfo: azdata.ConnectionInfo, newPassword: string): Thenable<azdata.PasswordChangeResult> {
|
||||||
|
return Promise.resolve({ result: false });
|
||||||
|
}
|
||||||
|
|
||||||
cancelConnect(connectionUri: string): Thenable<boolean> {
|
cancelConnect(connectionUri: string): Thenable<boolean> {
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ export class MainThreadDataProtocol extends Disposable implements MainThreadData
|
|||||||
disconnect(connectionUri: string): Thenable<boolean> {
|
disconnect(connectionUri: string): Thenable<boolean> {
|
||||||
return self._proxy.$disconnect(handle, connectionUri);
|
return self._proxy.$disconnect(handle, connectionUri);
|
||||||
},
|
},
|
||||||
|
changePassword(connectionUri, connectionInfo, newPassword): Thenable<azdata.PasswordChangeResult> {
|
||||||
|
return self._proxy.$changePassword(handle, connectionUri, connectionInfo, newPassword);
|
||||||
|
},
|
||||||
changeDatabase(connectionUri: string, newDatabase: string): Thenable<boolean> {
|
changeDatabase(connectionUri: string, newDatabase: string): Thenable<boolean> {
|
||||||
return self._proxy.$changeDatabase(handle, connectionUri, newDatabase);
|
return self._proxy.$changeDatabase(handle, connectionUri, newDatabase);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -225,6 +225,13 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
|
|||||||
return this._resolveProvider<azdata.ConnectionProvider>(handle).disconnect(connectionUri);
|
return this._resolveProvider<azdata.ConnectionProvider>(handle).disconnect(connectionUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override $changePassword(handle: number, connectionUri: string, connection: azdata.ConnectionInfo, newPassword: string): Thenable<azdata.PasswordChangeResult> {
|
||||||
|
if (this.uriTransformer) {
|
||||||
|
connectionUri = this._getTransformedUri(connectionUri, this.uriTransformer.transformIncoming);
|
||||||
|
}
|
||||||
|
return this._resolveProvider<azdata.ConnectionProvider>(handle).changePassword(connectionUri, connection, newPassword);
|
||||||
|
}
|
||||||
|
|
||||||
override $cancelConnect(handle: number, connectionUri: string): Thenable<boolean> {
|
override $cancelConnect(handle: number, connectionUri: string): Thenable<boolean> {
|
||||||
return this._resolveProvider<azdata.ConnectionProvider>(handle).cancelConnect(connectionUri);
|
return this._resolveProvider<azdata.ConnectionProvider>(handle).cancelConnect(connectionUri);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ export abstract class ExtHostDataProtocolShape {
|
|||||||
*/
|
*/
|
||||||
$disconnect(handle: number, connectionUri: string): Thenable<boolean> { throw ni(); }
|
$disconnect(handle: number, connectionUri: string): Thenable<boolean> { throw ni(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes password of the connection profile's user.
|
||||||
|
*/
|
||||||
|
$changePassword(handle: number, connectionUri: string, connection: azdata.ConnectionInfo, newPassword: string): Thenable<azdata.PasswordChangeResult> { throw ni(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel a connection to a data source using the provided connectionUri string.
|
* Cancel a connection to a data source using the provided connectionUri string.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
|||||||
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
||||||
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
|
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
|
||||||
import { CmsConnectionController } from 'sql/workbench/services/connection/browser/cmsConnectionController';
|
import { CmsConnectionController } from 'sql/workbench/services/connection/browser/cmsConnectionController';
|
||||||
|
import { PasswordChangeDialog } from 'sql/workbench/services/connection/browser/passwordChangeDialog';
|
||||||
import { entries } from 'sql/base/common/collections';
|
import { entries } from 'sql/base/common/collections';
|
||||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||||
import { ILogService } from 'vs/platform/log/common/log';
|
import { ILogService } from 'vs/platform/log/common/log';
|
||||||
@@ -241,6 +242,14 @@ export class ConnectionDialogService implements IConnectionDialogService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the default connect function (used by password reset dialog)
|
||||||
|
*/
|
||||||
|
public async callDefaultOnConnect(connection: IConnectionProfile, params: INewConnectionParams): Promise<void> {
|
||||||
|
// Needed for password reset dialog to connect after changing password.
|
||||||
|
return this.handleDefaultOnConnect(params, connection);
|
||||||
|
}
|
||||||
|
|
||||||
private async handleDefaultOnConnect(params: INewConnectionParams, connection: IConnectionProfile): Promise<void> {
|
private async handleDefaultOnConnect(params: INewConnectionParams, connection: IConnectionProfile): Promise<void> {
|
||||||
if (this.ignoreNextConnect) {
|
if (this.ignoreNextConnect) {
|
||||||
this._connectionDialog.resetConnection();
|
this._connectionDialog.resetConnection();
|
||||||
@@ -275,6 +284,9 @@ export class ConnectionDialogService implements IConnectionDialogService {
|
|||||||
} else if (connectionResult && connectionResult.errorHandled) {
|
} else if (connectionResult && connectionResult.errorHandled) {
|
||||||
this._connectionDialog.resetConnection();
|
this._connectionDialog.resetConnection();
|
||||||
this._logService.debug(`ConnectionDialogService: Error handled and connection reset - Error: ${connectionResult.errorMessage}`);
|
this._logService.debug(`ConnectionDialogService: Error handled and connection reset - Error: ${connectionResult.errorMessage}`);
|
||||||
|
} else if (connection.providerName === Constants.mssqlProviderName && connectionResult.errorCode === Constants.sqlPasswordErrorCode) {
|
||||||
|
this._connectionDialog.resetConnection();
|
||||||
|
this.launchChangePasswordDialog(connection, params);
|
||||||
} else {
|
} else {
|
||||||
this._connectionDialog.resetConnection();
|
this._connectionDialog.resetConnection();
|
||||||
this.showErrorDialog(Severity.Error, this._connectionErrorTitle, connectionResult.errorMessage, connectionResult.callStack, connectionResult.errorCode);
|
this.showErrorDialog(Severity.Error, this._connectionErrorTitle, connectionResult.errorMessage, connectionResult.callStack, connectionResult.errorCode);
|
||||||
@@ -495,6 +507,12 @@ export class ConnectionDialogService implements IConnectionDialogService {
|
|||||||
recentConnections.forEach(conn => conn.dispose());
|
recentConnections.forEach(conn => conn.dispose());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public launchChangePasswordDialog(profile: IConnectionProfile, params: INewConnectionParams): void {
|
||||||
|
let dialog = this._instantiationService.createInstance(PasswordChangeDialog);
|
||||||
|
dialog.open(profile, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private showErrorDialog(severity: Severity, headerTitle: string, message: string, messageDetails?: string, errorCode?: number): void {
|
private showErrorDialog(severity: Severity, headerTitle: string, message: string, messageDetails?: string, errorCode?: number): void {
|
||||||
// Kerberos errors are currently very hard to understand, so adding handling of these to solve the common scenario
|
// Kerberos errors are currently very hard to understand, so adding handling of these to solve the common scenario
|
||||||
// note that ideally we would have an extensible service to handle errors by error code and provider, but for now
|
// note that ideally we would have an extensible service to handle errors by error code and provider, but for now
|
||||||
|
|||||||
@@ -425,6 +425,14 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes password of the connection profile's user.
|
||||||
|
*/
|
||||||
|
public changePassword(connection: interfaces.IConnectionProfile, uri: string, newPassword: string):
|
||||||
|
Promise<azdata.PasswordChangeResult> {
|
||||||
|
return this.sendChangePasswordRequest(connection, uri, newPassword);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a new connection and saves the profile in the settings.
|
* Opens a new connection and saves the profile in the settings.
|
||||||
* This method doesn't load the password because it only gets called from the
|
* This method doesn't load the password because it only gets called from the
|
||||||
@@ -1037,6 +1045,18 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async sendChangePasswordRequest(connection: interfaces.IConnectionProfile, uri: string, newPassword: string): Promise<azdata.PasswordChangeResult> {
|
||||||
|
let connectionInfo = Object.assign({}, {
|
||||||
|
options: connection.options
|
||||||
|
});
|
||||||
|
|
||||||
|
return this._providers.get(connection.providerName).onReady.then((provider) => {
|
||||||
|
return provider.changePassword(uri, connectionInfo, newPassword).then(result => {
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private sendCancelRequest(uri: string): Promise<boolean> {
|
private sendCancelRequest(uri: string): Promise<boolean> {
|
||||||
let providerId: string = this.getProviderIdFromUri(uri);
|
let providerId: string = this.getProviderIdFromUri(uri);
|
||||||
if (!providerId) {
|
if (!providerId) {
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
.change-password-dialog {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-password-dialog .properties-content {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-password-dialog .component-label {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-password-dialog .components-grid {
|
||||||
|
display: grid;
|
||||||
|
/* grid-template-columns: column 1 is for label, column 2 is for component.*/
|
||||||
|
grid-template-columns: max-content 1fr;
|
||||||
|
grid-template-rows: max-content;
|
||||||
|
grid-gap: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
align-content: start;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import 'vs/css!./media/passwordDialog';
|
||||||
|
import { Button } from 'sql/base/browser/ui/button/button';
|
||||||
|
import { Modal } from 'sql/workbench/browser/modal/modal';
|
||||||
|
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
||||||
|
import { attachInputBoxStyler } from 'sql/platform/theme/common/styler';
|
||||||
|
import { INewConnectionParams } from 'sql/platform/connection/common/connectionManagement';
|
||||||
|
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
|
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||||
|
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||||
|
import { localize } from 'vs/nls';
|
||||||
|
import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
|
||||||
|
import { attachButtonStyler } from 'vs/platform/theme/common/styler';
|
||||||
|
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||||
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
|
import { ILogService } from 'vs/platform/log/common/log';
|
||||||
|
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
||||||
|
import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService';
|
||||||
|
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
||||||
|
import Severity from 'vs/base/common/severity';
|
||||||
|
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
|
||||||
|
import { attachModalDialogStyler } from 'sql/workbench/common/styler';
|
||||||
|
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||||
|
import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfiguration';
|
||||||
|
|
||||||
|
const dialogWidth: string = '300px'; // Width is set manually here as there is no default width for normal dialogs.
|
||||||
|
const okText: string = localize('passwordChangeDialog.ok', "OK");
|
||||||
|
const cancelText: string = localize('passwordChangeDialog.cancel', "Cancel");
|
||||||
|
const dialogTitle: string = localize('passwordChangeDialog.title', "Change Password");
|
||||||
|
const newPasswordText: string = localize('passwordChangeDialog.newPassword', 'New password:');
|
||||||
|
const confirmPasswordText: string = localize('passwordChangeDialog.confirmPassword', 'Confirm password:');
|
||||||
|
const passwordChangeLoadText: string = localize('passwordChangeDialog.connecting', "Connecting");
|
||||||
|
const errorHeader: string = localize('passwordChangeDialog.errorHeader', "Failure when attempting to change password");
|
||||||
|
const errorPasswordMismatchMessage = localize('passwordChangeDialog.errorPasswordMismatchMessage', "Passwords entered do not match\n\nPress OK and enter the exact same password in both boxes.");
|
||||||
|
|
||||||
|
export class PasswordChangeDialog extends Modal {
|
||||||
|
|
||||||
|
private _okButton?: Button;
|
||||||
|
private _cancelButton?: Button;
|
||||||
|
private _profile: IConnectionProfile;
|
||||||
|
private _params: INewConnectionParams;
|
||||||
|
private _uri: string;
|
||||||
|
private _passwordValueText: InputBox;
|
||||||
|
private _confirmValueText: InputBox;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@IThemeService themeService: IThemeService,
|
||||||
|
@IClipboardService clipboardService: IClipboardService,
|
||||||
|
@IConnectionManagementService private readonly connectionManagementService: IConnectionManagementService,
|
||||||
|
@IErrorMessageService private readonly errorMessageService: IErrorMessageService,
|
||||||
|
@IConnectionDialogService private readonly connectionDialogService: IConnectionDialogService,
|
||||||
|
@ILayoutService layoutService: ILayoutService,
|
||||||
|
@IAdsTelemetryService telemetryService: IAdsTelemetryService,
|
||||||
|
@IContextKeyService contextKeyService: IContextKeyService,
|
||||||
|
@ILogService logService: ILogService,
|
||||||
|
@IContextViewService private readonly contextViewService: IContextViewService,
|
||||||
|
@ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService,
|
||||||
|
) {
|
||||||
|
super('', '', telemetryService, layoutService, clipboardService, themeService, logService, textResourcePropertiesService, contextKeyService, { hasSpinner: true, spinnerTitle: passwordChangeLoadText, dialogStyle: 'normal', width: dialogWidth, dialogPosition: 'left' });
|
||||||
|
}
|
||||||
|
|
||||||
|
public open(profile: IConnectionProfile, params: INewConnectionParams) {
|
||||||
|
this._profile = profile;
|
||||||
|
this._params = params;
|
||||||
|
this._uri = this.connectionManagementService.getConnectionUri(profile);
|
||||||
|
this.render();
|
||||||
|
this.show();
|
||||||
|
this._okButton!.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override dispose(): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override render() {
|
||||||
|
super.render();
|
||||||
|
this.title = dialogTitle;
|
||||||
|
this._register(attachModalDialogStyler(this, this._themeService));
|
||||||
|
this._okButton = this.addFooterButton(okText, () => this.handleOkButtonClick());
|
||||||
|
this._cancelButton = this.addFooterButton(cancelText, () => this.hide('cancel'), 'right', true);
|
||||||
|
this._register(attachButtonStyler(this._okButton, this._themeService));
|
||||||
|
this._register(attachButtonStyler(this._cancelButton, this._themeService));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected renderBody(container: HTMLElement) {
|
||||||
|
const body = container.appendChild(DOM.$('.change-password-dialog'));
|
||||||
|
const contentElement = body.appendChild(DOM.$('.properties-content.components-grid'));
|
||||||
|
contentElement.appendChild(DOM.$('')).appendChild(DOM.$('span.component-label')).innerText = newPasswordText;
|
||||||
|
const passwordInputContainer = contentElement.appendChild(DOM.$(''));
|
||||||
|
this._passwordValueText = new InputBox(passwordInputContainer, this.contextViewService, { type: 'password' });
|
||||||
|
this._register(attachInputBoxStyler(this._passwordValueText, this._themeService));
|
||||||
|
|
||||||
|
contentElement.appendChild(DOM.$('')).appendChild(DOM.$('span.component-label')).innerText = confirmPasswordText;
|
||||||
|
const confirmInputContainer = contentElement.appendChild(DOM.$(''));
|
||||||
|
this._confirmValueText = new InputBox(confirmInputContainer, this.contextViewService, { type: 'password' });
|
||||||
|
this._register(attachInputBoxStyler(this._confirmValueText, this._themeService));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected layout(height?: number): void {
|
||||||
|
// Nothing to re-layout
|
||||||
|
}
|
||||||
|
|
||||||
|
/* espace key */
|
||||||
|
protected override onClose() {
|
||||||
|
this.hide('close');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enter key */
|
||||||
|
protected override onAccept() {
|
||||||
|
this.handleOkButtonClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleOkButtonClick(): void {
|
||||||
|
this._okButton.enabled = false;
|
||||||
|
this._cancelButton.enabled = false;
|
||||||
|
this.spinner = true;
|
||||||
|
this.changePasswordFunction(this._profile, this._params, this._uri, this._passwordValueText.value, this._confirmValueText.value).then(
|
||||||
|
() => {
|
||||||
|
this.hide('ok'); /* password changed successfully */
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this._okButton.enabled = true; /* ignore, user must try again */
|
||||||
|
this._cancelButton.enabled = true;
|
||||||
|
this.spinner = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async changePasswordFunction(connection: IConnectionProfile, params: INewConnectionParams, uri: string, oldPassword: string, newPassword: string): Promise<void> {
|
||||||
|
// Verify passwords match before changing the password.
|
||||||
|
if (oldPassword !== newPassword) {
|
||||||
|
this.errorMessageService.showDialog(Severity.Error, errorHeader, errorPasswordMismatchMessage);
|
||||||
|
return Promise.reject(new Error(errorPasswordMismatchMessage));
|
||||||
|
}
|
||||||
|
let passwordChangeResult = await this.connectionManagementService.changePassword(connection, uri, newPassword);
|
||||||
|
if (!passwordChangeResult.result) {
|
||||||
|
this.errorMessageService.showDialog(Severity.Error, errorHeader, passwordChangeResult.errorMessage);
|
||||||
|
return Promise.reject(new Error(passwordChangeResult.errorMessage));
|
||||||
|
}
|
||||||
|
connection.options['password'] = newPassword;
|
||||||
|
await this.connectionDialogService.callDefaultOnConnect(connection, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,4 +20,9 @@ export interface IConnectionDialogService {
|
|||||||
* or dialog is closed
|
* or dialog is closed
|
||||||
*/
|
*/
|
||||||
openDialogAndWait(connectionManagementService: IConnectionManagementService, params?: INewConnectionParams, model?: IConnectionProfile, connectionResult?: IConnectionResult, doConnect?: boolean): Promise<IConnectionProfile>;
|
openDialogAndWait(connectionManagementService: IConnectionManagementService, params?: INewConnectionParams, model?: IConnectionProfile, connectionResult?: IConnectionResult, doConnect?: boolean): Promise<IConnectionProfile>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the default connect function (used by password reset dialog)
|
||||||
|
*/
|
||||||
|
callDefaultOnConnect(connection: IConnectionProfile, params: INewConnectionParams): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,4 +25,8 @@ export class TestConnectionDialogService implements IConnectionDialogService {
|
|||||||
params?: INewConnectionParams, model?: IConnectionProfile, connectionResult?: IConnectionResult): Promise<IConnectionProfile> {
|
params?: INewConnectionParams, model?: IConnectionProfile, connectionResult?: IConnectionResult): Promise<IConnectionProfile> {
|
||||||
return Promise.resolve(undefined);
|
return Promise.resolve(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public callDefaultOnConnect(connection: IConnectionProfile, params: INewConnectionParams): Promise<void> {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user