Skip to content

Commit 127fa7f

Browse files
authored
Fixing some connection string bugs (#18030)
* Fixing bug where connection string with integrated auth crashes connection dialog * added displayName for MRU list to avoid setting profileName unexpectedly * PR feedback
1 parent 381f1d6 commit 127fa7f

File tree

3 files changed

+30
-17
lines changed

3 files changed

+30
-17
lines changed

src/connectionconfig/connectionDialogWebviewController.ts

+27-14
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export class ConnectionDialogWebviewController extends ReactWebviewPanelControll
8181

8282
private async loadRecentConnections() {
8383
const recentConnections = this._mainController.connectionManager.connectionStore.loadAllConnections(true).map(c => c.connectionCreds);
84-
const dialogConnections = [];
84+
const dialogConnections: IConnectionDialogProfile[] = [];
8585
for (let i = 0; i < recentConnections.length; i++) {
8686
dialogConnections.push(await this.initializeConnectionForDialog(recentConnections[i]));
8787
}
@@ -105,28 +105,41 @@ export class ConnectionDialogWebviewController extends ReactWebviewPanelControll
105105
this.state.connectionProfile = emptyConnection;
106106
}
107107

108-
private async initializeConnectionForDialog(connection: IConnectionInfo) {
108+
private async initializeConnectionForDialog(connection: IConnectionInfo): Promise<IConnectionDialogProfile> {
109109
// Load the password if it's saved
110110
const isConnectionStringConnection = connection.connectionString !== undefined && connection.connectionString !== '';
111-
const password = await this._mainController.connectionManager.connectionStore.lookupPassword(connection, isConnectionStringConnection);
112111
if (!isConnectionStringConnection) {
112+
const password = await this._mainController.connectionManager.connectionStore.lookupPassword(connection, isConnectionStringConnection);
113113
connection.password = password;
114114
} else {
115-
connection.connectionString = '';
116-
// extract password from connection string it starts after 'Password=' and ends before ';'
117-
const passwordIndex = password.indexOf('Password=') === -1 ? password.indexOf('password=') : password.indexOf('Password=');
118-
if (passwordIndex !== -1) {
119-
const passwordStart = passwordIndex + 'Password='.length;
120-
const passwordEnd = password.indexOf(';', passwordStart);
121-
if (passwordEnd !== -1) {
122-
connection.password = password.substring(passwordStart, passwordEnd);
115+
// If the connection is a connection string connection with SQL Auth:
116+
// * the full connection string is stored as the "password" in the credential store
117+
// * we need to extract the password from the connection string
118+
// If the connection is a connection string connection with a different auth type, then there's nothing in the credential store.
119+
120+
const connectionString = await this._mainController.connectionManager.connectionStore.lookupPassword(connection, isConnectionStringConnection);
121+
122+
if (connectionString) {
123+
const passwordIndex = connectionString.toLowerCase().indexOf('password=');
124+
125+
if (passwordIndex !== -1) {
126+
// extract password from connection string; found between 'Password=' and the next ';'
127+
const passwordStart = passwordIndex + 'password='.length;
128+
const passwordEnd = connectionString.indexOf(';', passwordStart);
129+
if (passwordEnd !== -1) {
130+
connection.password = connectionString.substring(passwordStart, passwordEnd);
131+
}
132+
133+
// clear the connection string from the IConnectionDialogProfile so that the ugly connection string key
134+
// that's used to look up the actual connection string (with password) isn't displayed
135+
connection.connectionString = '';
123136
}
124137
}
125-
126138
}
139+
127140
const dialogConnection = connection as IConnectionDialogProfile;
128-
// Set the profile name
129-
dialogConnection.profileName = dialogConnection.profileName ?? getConnectionDisplayName(connection);
141+
// Set the display name
142+
dialogConnection.displayName = dialogConnection.profileName ? dialogConnection.profileName : getConnectionDisplayName(connection);
130143
return dialogConnection;
131144
}
132145

src/reactviews/pages/ConnectionDialog/mruConnectionsContainer.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export const MruConnectionsContainer = () => {
5454
connectionDialogContext.loadConnection(connection);
5555
}}>
5656
<TreeItemLayout iconBefore={<ServerRegular />}>
57-
{connection.profileName}
57+
{connection.displayName}
5858
</TreeItemLayout>
5959
</TreeItem>;
6060
})

src/sharedInterfaces/connectionDialog.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ export interface IConnectionDialogProfile extends vscodeMssql.IConnectionInfo {
6666
savePassword?: boolean;
6767
emptyPasswordInput?: boolean;
6868
azureAuthType?: vscodeMssql.AzureAuthType;
69+
/** display name for the MRU pane; should be set to the profileName if available, otherwise generated from connection details */
70+
displayName?: string;
6971
}
7072

71-
72-
7373
export interface ConnectionDialogContextProps extends FormContextProps<ConnectionDialogWebviewState, IConnectionDialogProfile> {
7474
theme: Theme;
7575
loadConnection: (connection: IConnectionDialogProfile) => void;

0 commit comments

Comments
 (0)