CMS fit and finish (#5542)

* cms connections dont save

* added value to enum

* remove refresh and update provider name for cms

* removed ownerUri from saved connection and contributed to array

* removed owneruri

* ownerUri not needed any more

* removed AAD from cms

* initial review

* changed comments

* add back saveProfile option for connectionProfile

* review fixes and other UI improvements

* fixed auth

* added cms integration tests

* added constants

* removed utils from apiwrapper

* changed connection type name

* review comments

* clearer code and addressed reviews
This commit is contained in:
Aditya Bist
2019-05-31 11:14:37 -07:00
committed by GitHub
parent fa52478ffa
commit 1773dede25
27 changed files with 546 additions and 278 deletions

View File

@@ -7,7 +7,7 @@ import { SqlExtHostContext, SqlMainContext, ExtHostConnectionManagementShape, Ma
import * as azdata from 'azdata';
import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { IConnectionManagementService, ConnectionType } from 'sql/platform/connection/common/connectionManagement';
import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/common/objectExplorerService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
@@ -60,15 +60,23 @@ export class MainThreadConnectionManagement implements MainThreadConnectionManag
}
public async $openConnectionDialog(providers: string[], initialConnectionProfile?: IConnectionProfile, connectionCompletionOptions?: azdata.IConnectionCompletionOptions): Promise<azdata.connection.Connection> {
// Here we default to ConnectionType.editor which saves the connecton in the connection store by default
let connectionType = ConnectionType.editor;
// If the API call explicitly set saveConnection to false, set it to ConnectionType.extension
// which doesn't save the connection by default
if (connectionCompletionOptions && !connectionCompletionOptions.saveConnection) {
connectionType = ConnectionType.temporary;
}
let connectionProfile = await this._connectionDialogService.openDialogAndWait(this._connectionManagementService,
{ connectionType: 1, providers: providers }, initialConnectionProfile, undefined);
{ connectionType: connectionType, providers: providers }, initialConnectionProfile, undefined);
const connection = connectionProfile ? {
connectionId: connectionProfile.id,
options: connectionProfile.options,
providerName: connectionProfile.providerName
} : undefined;
if (connectionCompletionOptions) {
if (connectionCompletionOptions && connectionCompletionOptions.saveConnection) {
// Somehow, connectionProfile.saveProfile is false even if initialConnectionProfile.saveProfile is true, reset the flag here.
connectionProfile.saveProfile = initialConnectionProfile.saveProfile;
await this._connectionManagementService.connectAndSaveProfile(connectionProfile, undefined, {
@@ -79,7 +87,6 @@ export class MainThreadConnectionManagement implements MainThreadConnectionManag
showFirewallRuleOnError: isUndefinedOrNull(connectionCompletionOptions.showFirewallRuleOnError) ? true : connectionCompletionOptions.showFirewallRuleOnError
});
}
return connection;
}

View File

@@ -121,8 +121,8 @@ export function createApiFactory(
getUriForConnection(connectionId: string): Thenable<string> {
return extHostConnectionManagement.$getUriForConnection(connectionId);
},
connect(connectionProfile: azdata.IConnectionProfile): Thenable<azdata.ConnectionResult> {
return extHostConnectionManagement.$connect(connectionProfile);
connect(connectionProfile: azdata.IConnectionProfile, saveConnection: boolean, showDashboard: boolean): Thenable<azdata.ConnectionResult> {
return extHostConnectionManagement.$connect(connectionProfile, saveConnection, showDashboard);
}
};

View File

@@ -55,5 +55,6 @@ MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, {
command: {
id: REFRESH_COMMAND_ID,
title: localize('refresh', 'Refresh')
}
},
when: NodeContextKey.IsConnected
});

View File

@@ -97,10 +97,18 @@ export class CmsConnectionWidget extends ConnectionWidget {
let newAuthTypes = authTypeOption.categoryValues;
// True when opening a CMS dialog to add a registered server
if (authTypeChanged) {
// Need to filter out SQL Login because registered servers don't support it
newAuthTypes = authTypeOption.categoryValues.filter((option) => option.name !== AuthenticationType.SqlLogin);
// Registered Servers only support Integrated Auth
newAuthTypes = authTypeOption.categoryValues.filter((option) => option.name === AuthenticationType.Integrated);
this._authTypeSelectBox.setOptions(newAuthTypes.map(c => c.displayName), 0);
authTypeOption.defaultValue = AuthenticationType.Integrated;
this._authTypeSelectBox.setOptions(newAuthTypes.map(c => c.displayName));
} else {
// CMS supports all auth types
if (OS === OperatingSystem.Windows) {
authTypeOption.defaultValue = this.getAuthTypeDisplayName(AuthenticationType.Integrated);
} else {
authTypeOption.defaultValue = this.getAuthTypeDisplayName(AuthenticationType.SqlLogin);
}
this._authTypeSelectBox.setOptions(authTypeOption.categoryValues.map(c => c.displayName), 1);
}
}

View File

@@ -61,14 +61,14 @@ export class ConnectionDialogService implements IConnectionDialogService {
_serviceBrand: any;
private _connectionDialog: ConnectionDialogWidget;
private _connectionControllerMap: { [providerDisplayName: string]: IConnectionComponentController } = {};
private _connectionControllerMap: { [providerName: string]: IConnectionComponentController } = {};
private _model: ConnectionProfile;
private _params: INewConnectionParams;
private _options: IConnectionCompletionOptions;
private _inputModel: IConnectionProfile;
private _providerNameToDisplayNameMap: { [providerDisplayName: string]: string } = {};
private _providerTypes: string[] = [];
private _currentProviderType: string = 'Microsoft SQL Server';
private _currentProviderType: string = Constants.mssqlProviderName;
private _previousProviderType: string = undefined;
private _connecting: boolean = false;
private _connectionErrorTitle = localize('connectionError', 'Connection error');
@@ -171,8 +171,8 @@ export class ConnectionDialogService implements IConnectionDialogService {
profile.serverName = trim(profile.serverName);
// append the port to the server name for SQL Server connections
if (this.getCurrentProviderName() === Constants.mssqlProviderName ||
this.getCurrentProviderName() === Constants.cmsProviderName) {
if (this._currentProviderType === Constants.mssqlProviderName ||
this._currentProviderType === Constants.cmsProviderName) {
let portPropertyName: string = 'port';
let portOption: string = profile.options[portPropertyName];
if (portOption && portOption.indexOf(',') === -1) {
@@ -235,14 +235,15 @@ export class ConnectionDialogService implements IConnectionDialogService {
return Promise.resolve();
}
let fromEditor = params && params.connectionType === ConnectionType.editor;
let isTemporaryConnection = params && params.connectionType === ConnectionType.temporary;
let uri: string = undefined;
if (fromEditor && params && params.input) {
uri = params.input.uri;
}
let options: IConnectionCompletionOptions = this._options || {
params: params,
saveTheConnection: true,
showDashboard: params && params.showDashboard !== undefined ? params.showDashboard : !fromEditor,
saveTheConnection: !isTemporaryConnection,
showDashboard: params && params.showDashboard !== undefined ? params.showDashboard : !fromEditor && !isTemporaryConnection,
showConnectionDialogOnError: false,
showFirewallRuleOnError: true
};
@@ -269,7 +270,7 @@ export class ConnectionDialogService implements IConnectionDialogService {
private get uiController(): IConnectionComponentController {
// Find the provider name from the selected provider type, or throw an error if it does not correspond to a known provider
let providerName = this.getCurrentProviderName();
let providerName = this._currentProviderType;
if (!providerName) {
throw Error('Invalid provider type');
}
@@ -302,9 +303,23 @@ export class ConnectionDialogService implements IConnectionDialogService {
private handleShowUiComponent(input: OnShowUIResponse) {
if (input.selectedProviderType) {
this._currentProviderType = input.selectedProviderType;
// If the call is for specific providers
let isParamProvider: boolean = false;
if (this._params && this._params.providers) {
this._params.providers.forEach((provider) => {
if (input.selectedProviderType === this._providerNameToDisplayNameMap[provider]) {
isParamProvider = true;
this._currentProviderType = provider;
}
});
}
if (!isParamProvider) {
this._currentProviderType = Object.keys(this._providerNameToDisplayNameMap).find((key) =>
this._providerNameToDisplayNameMap[key] === input.selectedProviderType
);
}
}
this._model.providerName = this.getCurrentProviderName();
this._model.providerName = this._currentProviderType;
this._model = new ConnectionProfile(this._capabilitiesService, this._model);
if (this._inputModel && this._inputModel.options) {
@@ -339,9 +354,9 @@ export class ConnectionDialogService implements IConnectionDialogService {
private updateModelServerCapabilities(model: IConnectionProfile) {
this._model = this.createModel(model);
if (this._model.providerName) {
this._currentProviderType = this._providerNameToDisplayNameMap[this._model.providerName];
this._currentProviderType = this._model.providerName;
if (this._connectionDialog) {
this._connectionDialog.updateProvider(this._currentProviderType);
this._connectionDialog.updateProvider(this._providerNameToDisplayNameMap[this._currentProviderType]);
}
}
}
@@ -404,7 +419,8 @@ export class ConnectionDialogService implements IConnectionDialogService {
return new Promise<void>((resolve, reject) => {
this.updateModelServerCapabilities(model);
// If connecting from a query editor set "save connection" to false
if (params && params.input && params.connectionType === ConnectionType.editor) {
if (params && (params.input && params.connectionType === ConnectionType.editor ||
params.connectionType === ConnectionType.temporary)) {
this._model.saveProfile = false;
}
@@ -416,7 +432,6 @@ export class ConnectionDialogService implements IConnectionDialogService {
});
}
private doShowDialog(params: INewConnectionParams): Promise<void> {
if (!this._connectionDialog) {
this._connectionDialog = this._instantiationService.createInstance(ConnectionDialogWidget, this._providerTypes, this._providerNameToDisplayNameMap[this._model.providerName], this._providerNameToDisplayNameMap);
@@ -438,7 +453,7 @@ export class ConnectionDialogService implements IConnectionDialogService {
// if provider changed
if ((this._previousProviderType !== this._currentProviderType) ||
// or if currentProvider not set correctly yet
!(this._currentProviderType === Constants.cmsProviderDisplayName && params.providers && params.providers.length > 1)) {
!(this._currentProviderType === Constants.cmsProviderName && params.providers && params.providers.length > 1)) {
this._previousProviderType = undefined;
this._connectionDialog.updateProvider(this._providerNameToDisplayNameMap[this.getDefaultProviderName()]);
} else {
@@ -450,12 +465,6 @@ export class ConnectionDialogService implements IConnectionDialogService {
});
}
private getCurrentProviderName(): string {
return Object.keys(this._providerNameToDisplayNameMap).find(providerName => {
return this._currentProviderType === this._providerNameToDisplayNameMap[providerName];
});
}
private showErrorDialog(severity: Severity, headerTitle: string, message: string, messageDetails?: string): void {
// 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

View File

@@ -119,12 +119,17 @@ export class ConnectionDialogWidget extends Modal {
if (this._newConnectionParams && this._newConnectionParams.providers) {
const validProviderNames = Object.keys(this.providerNameToDisplayNameMap).filter(x => this.includeProvider(x, this._newConnectionParams));
if (validProviderNames && validProviderNames.length > 0) {
filteredProviderTypes = filteredProviderTypes.filter(x => validProviderNames.find(v => this.providerNameToDisplayNameMap[v] === x) !== undefined);
filteredProviderTypes = filteredProviderTypes.filter(x => validProviderNames.find(
v => this.providerNameToDisplayNameMap[v] === x) !== undefined
);
}
} else {
filteredProviderTypes = filteredProviderTypes.filter(x => x !== Constants.cmsProviderDisplayName);
filteredProviderTypes = filteredProviderTypes.filter(x => x !== Constants.cmsProviderName);
}
this._providerTypeSelectBox.setOptions(filteredProviderTypes);
this._providerTypeSelectBox.setOptions(filteredProviderTypes.filter((providerType, index) =>
// Remove duplicate listings
filteredProviderTypes.indexOf(providerType) === index)
);
}
private includeProvider(providerName: string, params?: INewConnectionParams): Boolean {