Skip to content

Commit d82d6ea

Browse files
authored
VSCODE-74: Add SSL/TLS to Connect Form Webview (#55)
1 parent b5c6345 commit d82d6ea

33 files changed

+1645
-477
lines changed

images/leaf.svg

Lines changed: 13 additions & 0 deletions
Loading

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,13 +455,13 @@
455455
}
456456
},
457457
"dependencies": {
458-
"@mongosh/browser-runtime-electron": "0.0.1-alpha.10",
459-
"@mongosh/service-provider-server": "0.0.1-alpha.10",
460-
"analytics-node": "^3.4.0-beta.1",
461458
"@fortawesome/fontawesome-svg-core": "^1.2.28",
462459
"@fortawesome/free-solid-svg-icons": "^5.13.0",
463460
"@fortawesome/react-fontawesome": "^0.1.9",
464461
"@leafygreen-ui/toggle": "^3.0.0",
462+
"@mongosh/browser-runtime-electron": "0.0.1-alpha.10",
463+
"@mongosh/service-provider-server": "0.0.1-alpha.10",
464+
"analytics-node": "^3.4.0-beta.1",
465465
"bson": "^4.0.3",
466466
"classnames": "^2.2.6",
467467
"debug": "^4.1.1",

src/connectionController.ts

Lines changed: 92 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const { name, version } = require('../package.json');
88
import { ConnectionModelType } from './connectionModelType';
99
import { DataServiceType } from './dataServiceType';
1010
import { createLogger } from './logging';
11-
import { StatusView, ConnectFormView } from './views';
11+
import { StatusView } from './views';
1212
import { EventEmitter } from 'events';
1313
import { StorageController, StorageVariables } from './storage';
1414
import { StorageScope, SavedConnection } from './storage/storageController';
@@ -54,10 +54,16 @@ export default class ConnectionController {
5454
): void {
5555
let loadedSavedConnection: SavedConnection;
5656
try {
57+
if (!savedConnection.connectionModel) {
58+
// Ignore empty connections.
59+
return;
60+
}
61+
5762
loadedSavedConnection = {
5863
id: connectionId,
59-
name: savedConnection.name,
6064
driverUrl: savedConnection.driverUrl,
65+
name: savedConnection.name,
66+
connectionModel: savedConnection.connectionModel,
6167
storageLocation: savedConnection.storageLocation
6268
};
6369
} catch (error) {
@@ -101,18 +107,6 @@ export default class ConnectionController {
101107
}
102108
}
103109

104-
public addMongoDBConnection(
105-
context: vscode.ExtensionContext
106-
): Promise<boolean> {
107-
log.info('mdb.connect command called.');
108-
109-
const connectWebView = new ConnectFormView();
110-
return connectWebView.showConnectForm(
111-
context,
112-
this.addNewConnectionAndConnect
113-
);
114-
}
115-
116110
public async connectWithURI(): Promise<boolean> {
117111
log.info('connectWithURI command called');
118112

@@ -140,16 +134,19 @@ export default class ConnectionController {
140134
}
141135

142136
return new Promise((resolve) => {
143-
this.addNewConnectionAndConnect(connectionString).then(resolve, (err) => {
144-
vscode.window.showErrorMessage(err.message);
145-
resolve(false);
146-
});
137+
this.addNewConnectionStringAndConnect(connectionString).then(
138+
resolve,
139+
(err) => {
140+
vscode.window.showErrorMessage(err.message);
141+
resolve(false);
142+
}
143+
);
147144
});
148145
}
149146

150147
// Resolves true when the connection is successfully added.
151148
// The connection can fail to connect but be successfully added.
152-
public addNewConnectionAndConnect = (
149+
public addNewConnectionStringAndConnect = (
153150
connectionString: string
154151
): Promise<boolean> => {
155152
log.info('Trying to connect to a new connection configuration');
@@ -158,49 +155,71 @@ export default class ConnectionController {
158155
Connection.from(
159156
connectionString,
160157
(error: Error | undefined, newConnectionModel: ConnectionModelType) => {
161-
if (error && !newConnectionModel) {
162-
return reject(new Error(`Unable to load connection: ${error}`));
158+
if (error) {
159+
return reject(new Error(`Unable to create connection: ${error}`));
163160
}
164161

165-
const { driverUrl, instanceId } = newConnectionModel.getAttributes({
166-
derived: true
167-
});
162+
return this.saveNewConnectionAndConnect(newConnectionModel).then(
163+
resolve,
164+
reject
165+
);
166+
}
167+
);
168+
});
169+
};
170+
171+
public parseNewConnectionAndConnect = (
172+
newConnectionModel
173+
): Promise<boolean> => {
174+
// Here we re-parse the connection, as it can be loaded from storage or
175+
// passed by the connection model without the class methods.
176+
let connectionModel;
177+
178+
try {
179+
connectionModel = new Connection(newConnectionModel);
180+
} catch (error) {
181+
vscode.window.showErrorMessage(`Unable to load connection: ${error}`);
182+
return Promise.reject(new Error(`Unable to load connection: ${error}`));
183+
}
168184

169-
const newConnection: SavedConnection = {
170-
id: uuidv4(),
171-
name: instanceId,
172-
driverUrl,
173-
// To begin we just store it on the session, the storage controller
174-
// handles changing this based on user preference.
175-
storageLocation: StorageScope.NONE
176-
};
177-
this._savedConnections[newConnection.id] = newConnection;
185+
return this.saveNewConnectionAndConnect(connectionModel);
186+
};
178187

179-
this._storageController.storeNewConnection(newConnection);
188+
public saveNewConnectionAndConnect = (
189+
connectionModel: ConnectionModelType
190+
): Promise<boolean> => {
191+
const { driverUrl, instanceId } = connectionModel.getAttributes({
192+
derived: true
193+
});
180194

181-
if (error) {
182-
return reject(new Error(`Unable to connect: ${error}`));
183-
}
195+
const newConnection: SavedConnection = {
196+
id: uuidv4(),
197+
name: instanceId,
198+
connectionModel,
199+
driverUrl,
200+
// To begin we just store it on the session, the storage controller
201+
// handles changing this based on user preference.
202+
storageLocation: StorageScope.NONE
203+
};
204+
this._savedConnections[newConnection.id] = newConnection;
184205

185-
this.connect(newConnection.id, newConnectionModel).then(
186-
(connectSuccess) => {
187-
if (!connectSuccess) {
188-
return resolve(false);
189-
}
206+
this._storageController.storeNewConnection(newConnection);
190207

191-
resolve(true);
192-
},
193-
reject
194-
);
208+
return new Promise((resolve, reject) => {
209+
this.connect(newConnection.id, connectionModel).then((connectSuccess) => {
210+
if (!connectSuccess) {
211+
return resolve(false);
195212
}
196-
);
213+
214+
resolve(true);
215+
}, reject);
197216
});
198217
};
199218

200-
public async connect(
219+
public connect = async (
201220
connectionId: string,
202221
connectionModel: ConnectionModelType
203-
): Promise<boolean> {
222+
): Promise<boolean> => {
204223
log.info(
205224
'Connect called to connect to instance:',
206225
connectionModel.getAttributes({
@@ -258,35 +277,39 @@ export default class ConnectionController {
258277
return resolve(true);
259278
});
260279
});
261-
}
280+
};
262281

263-
public async connectWithConnectionId(connectionId: string): Promise<boolean> {
282+
public connectWithConnectionId = (connectionId: string): Promise<boolean> => {
264283
if (this._savedConnections[connectionId]) {
284+
let connectionModel;
285+
286+
try {
287+
const savedConnectionModel = this._savedConnections[connectionId]
288+
.connectionModel;
289+
// Here we rebuild the connection model to ensure it's up to date and
290+
// contains the connection model class methods (not just attributes).
291+
connectionModel = new Connection(
292+
savedConnectionModel.getAttributes
293+
? savedConnectionModel.getAttributes({ props: true })
294+
: savedConnectionModel
295+
);
296+
} catch (error) {
297+
vscode.window.showErrorMessage(`Unable to load connection: ${error}`);
298+
return Promise.resolve(false);
299+
}
265300
return new Promise((resolve) => {
266-
Connection.from(
267-
this._savedConnections[connectionId].driverUrl,
268-
(error: Error | undefined, connectionModel: ConnectionModelType) => {
269-
if (error && !connectionModel) {
270-
vscode.window.showErrorMessage(
271-
`Unable to load connection: ${error}`
272-
);
273-
return resolve(false);
274-
}
275-
276-
return this.connect(connectionId, connectionModel).then(
277-
resolve,
278-
(err: Error) => {
279-
vscode.window.showErrorMessage(err.message);
280-
return resolve(false);
281-
}
282-
);
301+
this.connect(connectionId, connectionModel).then(
302+
resolve,
303+
(err: Error) => {
304+
vscode.window.showErrorMessage(err.message);
305+
return resolve(false);
283306
}
284307
);
285308
});
286309
}
287310

288311
return Promise.reject(new Error('Connection not found.'));
289-
}
312+
};
290313

291314
public disconnect(): Promise<boolean> {
292315
log.info(

src/connectionModelType.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ type ConnectionAttributes = {
55

66
export type ConnectionModelType = {
77
appname: string;
8+
port: number;
89

910
getAttributes(options: object): ConnectionAttributes;
1011
disconnect(callback: (n: Error | undefined) => void): void;

src/explorer/schemaTreeItem.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export default class SchemaTreeItem extends vscode.TreeItem
141141
vscode.window.showErrorMessage(
142142
`Unable to list documents: ${findError}`
143143
);
144-
return reject(`Unable to list documents: ${findError}`);
144+
return reject(new Error(`Unable to list documents: ${findError}`));
145145
}
146146

147147
if (!documents || documents.length === 0) {

src/mdbExtensionController.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import DatabaseTreeItem from './explorer/databaseTreeItem';
1717
import ConnectionTreeItem from './explorer/connectionTreeItem';
1818
import SchemaTreeItem from './explorer/schemaTreeItem';
1919
import DocumentTreeItem from './explorer/documentTreeItem';
20+
import WebviewController from './views/webviewController';
2021

2122
const log = createLogger('commands');
2223

@@ -32,6 +33,7 @@ export default class MDBExtensionController implements vscode.Disposable {
3233
_storageController: StorageController;
3334
_telemetryController: TelemetryController;
3435
_languageServerController: LanguageServerController;
36+
_webviewController: WebviewController;
3537

3638
constructor(
3739
context: vscode.ExtensionContext,
@@ -68,6 +70,7 @@ export default class MDBExtensionController implements vscode.Disposable {
6870
this._languageServerController,
6971
this._telemetryController
7072
);
73+
this._webviewController = new WebviewController(this._connectionController);
7174
}
7275

7376
activate(): void {
@@ -81,7 +84,7 @@ export default class MDBExtensionController implements vscode.Disposable {
8184
// Register our extension's commands. These are the event handlers and
8285
// control the functionality of our extension.
8386
this.registerCommand('mdb.connect', () =>
84-
this._connectionController.addMongoDBConnection(this._context)
87+
this._webviewController.showConnectForm(this._context)
8588
);
8689
this.registerCommand('mdb.connectWithURI', () =>
8790
this._connectionController.connectWithURI()
@@ -138,7 +141,7 @@ export default class MDBExtensionController implements vscode.Disposable {
138141

139142
registerTreeViewCommands(): void {
140143
this.registerCommand('mdb.addConnection', () =>
141-
this._connectionController.addMongoDBConnection(this._context)
144+
this._webviewController.showConnectForm(this._context)
142145
);
143146
this.registerCommand('mdb.addConnectionWithURI', () =>
144147
this._connectionController.connectWithURI()

0 commit comments

Comments
 (0)