Skip to content

Commit

Permalink
Add support for SSH tunnel
Browse files Browse the repository at this point in the history
  • Loading branch information
Paxa committed Aug 15, 2021
1 parent cae0242 commit efc0297
Show file tree
Hide file tree
Showing 18 changed files with 976 additions and 721 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ libudev.so.0
node_modules/
.ruby-version
dist/
.DS_Store
3 changes: 3 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ global.App = {
conn.connectToServer(options, (status, error) => {
this.stopLoading();
if (status) {
if (conn.options.tab_name) {
connectionName = conn.options.tab_name;
}
var tab = this.addDbScreen(conn, connectionName, options);
tab.activate();
if (callback && runCallback) callback(tab);
Expand Down
34 changes: 33 additions & 1 deletion app/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var colors = require('colors/safe');
colors.enabled = true;
var vsprintf = require("sprintf-js").vsprintf;
var ConnectionString = require('connection-string').ConnectionString;
var SshConnect = require('../lib/ssh_connect');


// Change postgres' type parser to use moment instance instead of js Date instance
Expand Down Expand Up @@ -88,6 +89,7 @@ class Connection {
startQuery: string
isCockroach: boolean
onDisconnect?: Function
sshConnection?: typeof SshConnect
static PG: any
public static instances: Connection[]
Expand Down Expand Up @@ -202,8 +204,34 @@ class Connection {

this.options = options;

this.connection = this._initConnection(this.connectString);
if (options.ssh_host && !this.sshConnection) {
this.sshConnection = new SshConnect();
this.sshConnection.connectTo(options).then(tunnel => {
console.log('ssh tunnel', tunnel);
this.options.tab_name = this.options.host;
this.options.host = tunnel.host;
this.options.port = tunnel.port;

var connStr = Connection.generateConnectionString(this.options);
this.connection = this._initConnection(connStr);
return this._startConnection(this.options, (success, error) => {
if (!success) {
this.sshConnection.disconnect();
}
callback(success, error)
});
}).catch(error => {
console.error(error);
callback && callback(false, error);
App.log("connect.error", this, JSON.parse(JSON.stringify(options)), error);
});
} else {
this.connection = this._initConnection(this.connectString);
return this._startConnection(options, callback);
}
}

_startConnection(options, callback) {
return this.connection.connect().then(() => {
this.connection.on('notification', (msg) => {
this.notificationCallbacks.forEach((fn) => {
Expand Down Expand Up @@ -593,6 +621,10 @@ class Connection {
if (this.connection) {
this.connection.end();
}
if (this.sshConnection) {
this.sshConnection.disconnect();
}

var index = global.Connection.instances.indexOf(this);
if (index != -1) {
global.Connection.instances.splice(index, 1);
Expand Down
3 changes: 3 additions & 0 deletions app/controllers/export_controller.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// @ts-ignore
var SqlExporter = require('../../lib/sql_exporter');

class ExportController {
/*::
dialog: Dialog.ExportFile
Expand Down
45 changes: 27 additions & 18 deletions app/login_screen.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class LoginScreen {

constructor (cliConnectString) {
this.type = "login_screen";
this.herokuClient = new HerokuClient();
this.activeForm = 'standard';

this.content = App.renderView('login_screen');
this.standardForm = new LoginStandardForm(this, this.content);
Expand All @@ -24,27 +26,26 @@ class LoginScreen {
$u.textareaAutoSize(el);
});

this.initEvents();

this.fillSavedConnections();
if (this.connections.find('li:first').length) {
this.connections.find('li:first').click();

if (Object.keys(this.savedConnections).length > 0) {
this.connectionName = Object.keys(this.savedConnections)[0];
this.connectionSelected(this.connectionName);
} else {
this.fillForm({user: process.env.USER || 'user'});
}

this.initEvents(this.content);

if (cliConnectString) {
this.makeConnection(cliConnectString, {});
} else {
this.checkAutoLogin();
}

this.herokuClient = new HerokuClient();
this.activeForm = 'standard';
}

initEvents(content) {
PaneBase.prototype.initEvents.call(this, content);
initEvents() {
PaneBase.prototype.initEvents.call(this, this.content);

this.content.find('a.go-to-help').bind('click', () => {
var help = HelpScreen.open();
Expand All @@ -55,7 +56,8 @@ class LoginScreen {
showPart (name) {
this.activeForm = name;
this.content.find('.middle-window-content').hide();
this.content.find('.middle-window-content.' + name).show();
this.content.find('.middle-window-content.' + name).show().css('display', 'block');
this.content.find('.middle-window').attr('active-part', name);
}

showStandardPane () {
Expand All @@ -80,6 +82,10 @@ class LoginScreen {
this.showPart('heroku-oauth');
}

showExtraLogingFields () {
this.content.find('.middle-window').toggleClass('extra-login-fields-open');
}

startHerokuOAuth () {
this.showHerokuOAuthPane();
var steps = this.content.find('.heroku-oauth ul.steps');
Expand Down Expand Up @@ -127,7 +133,6 @@ class LoginScreen {
fillSavedConnections () {
this.connections.empty();
this.savedConnections = Model.SavedConn.savedConnections();
var currentConnection = this.connectionName;

ObjectKit.forEach(this.savedConnections, (name, params) => {
var line = $dom(['li', {'data-auto-connect': params.auto_connect, 'data-name': name}, name]);
Expand All @@ -147,22 +152,26 @@ class LoginScreen {
}
});

if (name == currentConnection) {
$u(line).addClass('selected');
}
// if (name == currentConnection) {
// $u(line).addClass('selected');
// this.connectionSelected(name, params, line);
// }

$u(line).single_double_click_nowait((e) => {
this.connectionSelected(name, params, line);
this.connectionSelected(name);
}, (e) => {
this.connectionSelected(name, params, line);
this.connectionSelected(name);
this.submitCurrentForm();
});

this.connections.append(line)
});
}

connectionSelected (name, params, line) {
connectionSelected (name) {
var params = this.savedConnections[name];
var line = this.connections.find(`[data-name='${name}']`);

this.connections.find('.selected').removeClass('selected');
$u(line).addClass('selected');
this.connectionName = name;
Expand Down Expand Up @@ -276,7 +285,7 @@ class LoginScreen {
App.stopLoading();
}
});
this.connectionSelected(autoConnect, connection, this.connections.find(`[data-name='${autoConnect}']`));
this.connectionSelected(autoConnect);
this.submitCurrentForm();
}
}
Expand Down
35 changes: 34 additions & 1 deletion assets/styles/screens/_login.scss
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,37 @@ $mac-block-tabs-radius: 4px;
width: auto;
input[type=checkbox] {
margin-left: 0;
position: relative;
top: 2px;
}
}

// extra fields for ssh tunnel connection
.extra-login-fields {
p.extra-field {
display: none;
}
.close-extra-fields {
display: none;
}
}
}

&[active-part="standard"].extra-login-fields-open {
margin-top: calc(50vh - 275px);
.close-extra-fields {
display: inline;
}
.open-extra-fields {
display: none;
}
.extra-login-fields {
p.extra-field {
display: block;
}
}
}

} // .middle-window

.middle-window-content {
display: none;
Expand Down Expand Up @@ -193,6 +221,11 @@ $mac-block-tabs-radius: 4px;
font-size: 12px;
font-family: $code-font;
}
.ssh-tunnel-info {
text-align: center;
margin-bottom: -8px;
margin-top: 3px;
}
}

.sidebar {
Expand Down
9 changes: 8 additions & 1 deletion lib/pg_dump_runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ interface PgDumpRunner_Options {
args: string[]
debug: boolean
}
interface PgDumpRunner_Result {
code: number
stdout?: string
stderr?: string
}
*/

class PgDumpRunner {
Expand Down Expand Up @@ -56,7 +63,7 @@ class PgDumpRunner {
}
}

execute (extraArgs, callback) {
execute (extraArgs, callback /*:: ?: Function */) /*: Promise<PgDumpRunner_Result> */ {
if (typeof extraArgs == 'function' && callback === undefined) {
callback = extraArgs;
extraArgs = undefined;
Expand Down
27 changes: 22 additions & 5 deletions lib/sql_exporter.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
class SqlExporter {
/*::
interface SqlExporter_Options {
args: string[]
debug: boolean
}
interface SqlExporter_Env {
[column: string] : string[]
}
*/


class SqlExporter_ {

/*::
options: SqlExporter_Options
onMessageCallbacks: Function[]
*/

constructor(options = {}) {
this.onMessageCallbacks = [];
Expand All @@ -19,7 +36,9 @@ class SqlExporter {
//runner.addArguments("--single-transaction");

runner.addArguments("--host=" + connection.options.host);
runner.addArguments("--username=" + connection.options.user);
if (connection.options.user) {
runner.addArguments("--username=" + connection.options.user);
}
if (connection.options.password && connection.options.password != "") {
runner.env.PGPASSWORD = connection.options.password;
}
Expand Down Expand Up @@ -79,7 +98,5 @@ class SqlExporter {
}
}

global.SqlExporter = SqlExporter;
window.SqlExporter = global.SqlExporter;
module.exports = SqlExporter_;

module.exports = SqlExporter;
4 changes: 3 additions & 1 deletion lib/sql_importer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ class SqlImporter {
//runner.addArguments("--single-transaction");

runner.addArguments("--host=" + connection.options.host);
runner.addArguments("--username=" + connection.options.user);
if (connection.options.user) {
runner.addArguments("--username=" + connection.options.user);
}
if (connection.options.password && connection.options.password != "") {
//runner.addArguments("--password=" + connection.options.password);
runner.env.PGPASSWORD = connection.options.password;
Expand Down
Loading

0 comments on commit efc0297

Please sign in to comment.