mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
feat: SSH Tunnel functionality (#81)
* added ssh-tunnel-functionality for mysql-connections * remove autoformat-stuff * added identity for using ssh-key * added identity to mysqlclient to use sshkey * removed debug console.log * added ssh-tunnel-functionality for postgresqlclient * changed naming to sshKey for sshKey-input * refactoring code * fix lint * set dbConfig.ssl to null initially
This commit is contained in:
@ -102,6 +102,7 @@
|
|||||||
"source-map-support": "^0.5.16",
|
"source-map-support": "^0.5.16",
|
||||||
"spectre.css": "^0.5.9",
|
"spectre.css": "^0.5.9",
|
||||||
"sql-formatter": "^4.0.2",
|
"sql-formatter": "^4.0.2",
|
||||||
|
"ssh2-promise": "^0.1.7",
|
||||||
"v-mask": "^2.2.4",
|
"v-mask": "^2.2.4",
|
||||||
"vue-i18n": "^8.24.4",
|
"vue-i18n": "^8.24.4",
|
||||||
"vuedraggable": "^2.24.3",
|
"vuedraggable": "^2.24.3",
|
||||||
|
@ -24,13 +24,23 @@ export default connections => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const connection = ClientsFactory.getConnection({
|
if (conn.ssh) {
|
||||||
client: conn.client,
|
params.ssh = {
|
||||||
params
|
host: conn.sshHost,
|
||||||
});
|
username: conn.sshUser,
|
||||||
|
password: conn.sshPass,
|
||||||
|
port: conn.sshPort ? conn.sshPort : 22,
|
||||||
|
identity: conn.sshKey
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const connection = await ClientsFactory.getConnection({
|
||||||
|
client: conn.client,
|
||||||
|
params
|
||||||
|
});
|
||||||
await connection.connect();
|
await connection.connect();
|
||||||
|
|
||||||
await connection.select('1+1').run();
|
await connection.select('1+1').run();
|
||||||
connection.destroy();
|
connection.destroy();
|
||||||
|
|
||||||
@ -66,6 +76,16 @@ export default connections => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conn.ssh) {
|
||||||
|
params.ssh = {
|
||||||
|
host: conn.sshHost,
|
||||||
|
username: conn.sshUser,
|
||||||
|
password: conn.sshPass,
|
||||||
|
port: conn.sshPort ? conn.sshPort : 22,
|
||||||
|
identity: conn.sshKey
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const connection = ClientsFactory.getConnection({
|
const connection = ClientsFactory.getConnection({
|
||||||
client: conn.client,
|
client: conn.client,
|
||||||
|
@ -12,6 +12,10 @@ export class ClientsFactory {
|
|||||||
* @param {String} args.params.host
|
* @param {String} args.params.host
|
||||||
* @param {Number} args.params.port
|
* @param {Number} args.params.port
|
||||||
* @param {String} args.params.password
|
* @param {String} args.params.password
|
||||||
|
* @param {String} args.params.ssh.host
|
||||||
|
* @param {String} args.params.ssh.username
|
||||||
|
* @param {String} args.params.ssh.password
|
||||||
|
* @param {Number} args.params.ssh.port
|
||||||
* @param {Number=} args.poolSize
|
* @param {Number=} args.poolSize
|
||||||
* @returns Database Connection
|
* @returns Database Connection
|
||||||
* @memberof ClientsFactory
|
* @memberof ClientsFactory
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import mysql from 'mysql2/promise';
|
import mysql from 'mysql2/promise';
|
||||||
import { AntaresCore } from '../AntaresCore';
|
import { AntaresCore } from '../AntaresCore';
|
||||||
import dataTypes from 'common/data-types/mysql';
|
import dataTypes from 'common/data-types/mysql';
|
||||||
|
import * as SSH2Promise from 'ssh2-promise';
|
||||||
|
|
||||||
export class MySQLClient extends AntaresCore {
|
export class MySQLClient extends AntaresCore {
|
||||||
constructor (args) {
|
constructor (args) {
|
||||||
@ -104,11 +105,32 @@ export class MySQLClient extends AntaresCore {
|
|||||||
async connect () {
|
async connect () {
|
||||||
delete this._params.application_name;
|
delete this._params.application_name;
|
||||||
|
|
||||||
if (!this._poolSize)
|
const dbConfig = {
|
||||||
this._connection = await mysql.createConnection(this._params);
|
host: this._params.host,
|
||||||
|
port: this._params.port,
|
||||||
|
user: this._params.user,
|
||||||
|
password: this._params.password,
|
||||||
|
ssl: null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this._params.database?.length) dbConfig.database = this._params.database;
|
||||||
|
|
||||||
|
if (this._params.ssl) dbConfig.ssl = { ...this._params.ssl };
|
||||||
|
|
||||||
|
if (this._params.ssh) {
|
||||||
|
this._ssh = new SSH2Promise({ ...this._params.ssh });
|
||||||
|
|
||||||
|
this._tunnel = await this._ssh.addTunnel({
|
||||||
|
remoteAddr: this._params.host,
|
||||||
|
remotePort: this._params.port
|
||||||
|
});
|
||||||
|
dbConfig.port = this._tunnel.localPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._poolSize) this._connection = await mysql.createConnection(dbConfig);
|
||||||
else {
|
else {
|
||||||
this._connection = mysql.createPool({
|
this._connection = mysql.createPool({
|
||||||
...this._params,
|
...dbConfig,
|
||||||
connectionLimit: this._poolSize,
|
connectionLimit: this._poolSize,
|
||||||
typeCast: (field, next) => {
|
typeCast: (field, next) => {
|
||||||
if (field.type === 'DATETIME')
|
if (field.type === 'DATETIME')
|
||||||
@ -125,6 +147,7 @@ export class MySQLClient extends AntaresCore {
|
|||||||
*/
|
*/
|
||||||
destroy () {
|
destroy () {
|
||||||
this._connection.end();
|
this._connection.end();
|
||||||
|
if (this._ssh) this._ssh.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,6 +3,7 @@ import { Pool, Client, types } from 'pg';
|
|||||||
import { parse } from 'pgsql-ast-parser';
|
import { parse } from 'pgsql-ast-parser';
|
||||||
import { AntaresCore } from '../AntaresCore';
|
import { AntaresCore } from '../AntaresCore';
|
||||||
import dataTypes from 'common/data-types/postgresql';
|
import dataTypes from 'common/data-types/postgresql';
|
||||||
|
import * as SSH2Promise from 'ssh2-promise';
|
||||||
|
|
||||||
function pgToString (value) {
|
function pgToString (value) {
|
||||||
return value.toString();
|
return value.toString();
|
||||||
@ -51,13 +52,35 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
* @memberof PostgreSQLClient
|
* @memberof PostgreSQLClient
|
||||||
*/
|
*/
|
||||||
async connect () {
|
async connect () {
|
||||||
|
const dbConfig = {
|
||||||
|
host: this._params.host,
|
||||||
|
port: this._params.port,
|
||||||
|
user: this._params.user,
|
||||||
|
password: this._params.password,
|
||||||
|
ssl: null
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this._params.database?.length) dbConfig.database = this._params.database;
|
||||||
|
|
||||||
|
if (this._params.ssl) dbConfig.ssl = { ...this._params.ssl };
|
||||||
|
|
||||||
|
if (this._params.ssh) {
|
||||||
|
this._ssh = new SSH2Promise({ ...this._params.ssh });
|
||||||
|
|
||||||
|
this._tunnel = await this._ssh.addTunnel({
|
||||||
|
remoteAddr: this._params.host,
|
||||||
|
remotePort: this._params.port
|
||||||
|
});
|
||||||
|
dbConfig.port = this._tunnel.localPort;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this._poolSize) {
|
if (!this._poolSize) {
|
||||||
const client = new Client(this._params);
|
const client = new Client(dbConfig);
|
||||||
await client.connect();
|
await client.connect();
|
||||||
this._connection = client;
|
this._connection = client;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const pool = new Pool({ ...this._params, max: this._poolSize });
|
const pool = new Pool({ ...dbConfig, max: this._poolSize });
|
||||||
this._connection = pool;
|
this._connection = pool;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,6 +90,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
*/
|
*/
|
||||||
destroy () {
|
destroy () {
|
||||||
this._connection.end();
|
this._connection.end();
|
||||||
|
if (this._ssh) this._ssh.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,6 +28,13 @@
|
|||||||
>
|
>
|
||||||
<a class="tab-link">{{ $t('word.ssl') }}</a>
|
<a class="tab-link">{{ $t('word.ssl') }}</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li
|
||||||
|
class="tab-item"
|
||||||
|
:class="{'active': selectedTab === 'ssh'}"
|
||||||
|
@click="selectTab('ssh')"
|
||||||
|
>
|
||||||
|
<a class="c-hand">{{ $t('word.sshTunnel') }}</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="selectedTab === 'general'" class="panel-body py-0">
|
<div v-if="selectedTab === 'general'" class="panel-body py-0">
|
||||||
@ -208,7 +215,6 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-4 col-sm-12">
|
<div class="col-4 col-sm-12">
|
||||||
<label class="form-label">{{ $t('word.ciphers') }}</label>
|
<label class="form-label">{{ $t('word.ciphers') }}</label>
|
||||||
@ -231,6 +237,95 @@
|
|||||||
:status="toast.status"
|
:status="toast.status"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="selectedTab === 'ssh'" class="panel-body py-0">
|
||||||
|
<div class="container">
|
||||||
|
<form class="form-horizontal">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">
|
||||||
|
{{ $t('message.enableSsh') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<label class="form-switch d-inline-block" @click.prevent="toggleSsh">
|
||||||
|
<input type="checkbox" :checked="localConnection.ssh">
|
||||||
|
<i class="form-icon" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<fieldset class="m-0" :disabled="isTesting || !localConnection.ssh">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<input
|
||||||
|
v-model="localConnection.sshHost"
|
||||||
|
class="form-input"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.user') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<input
|
||||||
|
v-model="localConnection.sshUser"
|
||||||
|
class="form-input"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.password') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<input
|
||||||
|
v-model="localConnection.sshPass"
|
||||||
|
class="form-input"
|
||||||
|
type="password"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.port') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<input
|
||||||
|
v-model="localConnection.sshPort"
|
||||||
|
class="form-input"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
max="65535"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.privateKey') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<BaseUploadInput
|
||||||
|
:value="localConnection.sshKey"
|
||||||
|
:message="$t('word.browse')"
|
||||||
|
@clear="pathClear('sshKey')"
|
||||||
|
@change="pathSelection($event, 'sshKey')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<BaseToast
|
||||||
|
class="mb-2"
|
||||||
|
:message="toast.message"
|
||||||
|
:status="toast.status"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div class="modal-footer text-light">
|
<div class="modal-footer text-light">
|
||||||
<button
|
<button
|
||||||
class="btn btn-gray mr-2"
|
class="btn btn-gray mr-2"
|
||||||
@ -369,6 +464,9 @@ export default {
|
|||||||
toggleSsl () {
|
toggleSsl () {
|
||||||
this.localConnection.ssl = !this.localConnection.ssl;
|
this.localConnection.ssl = !this.localConnection.ssl;
|
||||||
},
|
},
|
||||||
|
toggleSsh () {
|
||||||
|
this.localConnection.ssh = !this.localConnection.ssh;
|
||||||
|
},
|
||||||
pathSelection (event, name) {
|
pathSelection (event, name) {
|
||||||
const { files } = event.target;
|
const { files } = event.target;
|
||||||
if (!files.length) return;
|
if (!files.length) return;
|
||||||
|
@ -29,6 +29,13 @@
|
|||||||
>
|
>
|
||||||
<a class="tab-link">{{ $t('word.ssl') }}</a>
|
<a class="tab-link">{{ $t('word.ssl') }}</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li
|
||||||
|
class="tab-item"
|
||||||
|
:class="{'active': selectedTab === 'ssh'}"
|
||||||
|
@click="selectTab('ssh')"
|
||||||
|
>
|
||||||
|
<a class="c-hand">{{ $t('word.sshTunnel') }}</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="selectedTab === 'general'" class="panel-body py-0">
|
<div v-if="selectedTab === 'general'" class="panel-body py-0">
|
||||||
@ -213,7 +220,6 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-4 col-sm-12">
|
<div class="col-4 col-sm-12">
|
||||||
<label class="form-label">{{ $t('word.ciphers') }}</label>
|
<label class="form-label">{{ $t('word.ciphers') }}</label>
|
||||||
@ -236,6 +242,95 @@
|
|||||||
:status="toast.status"
|
:status="toast.status"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="selectedTab === 'ssh'" class="panel-body py-0">
|
||||||
|
<div class="container">
|
||||||
|
<form class="form-horizontal">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">
|
||||||
|
{{ $t('message.enableSsh') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<label class="form-switch d-inline-block" @click.prevent="toggleSsh">
|
||||||
|
<input type="checkbox" :checked="connection.ssh">
|
||||||
|
<i class="form-icon" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<fieldset class="m-0" :disabled="isTesting || !connection.ssh">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.hostName') }}/IP</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<input
|
||||||
|
v-model="connection.sshHost"
|
||||||
|
class="form-input"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.user') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<input
|
||||||
|
v-model="connection.sshUser"
|
||||||
|
class="form-input"
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.password') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<input
|
||||||
|
v-model="connection.sshPass"
|
||||||
|
class="form-input"
|
||||||
|
type="password"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.port') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<input
|
||||||
|
v-model="connection.sshPort"
|
||||||
|
class="form-input"
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
max="65535"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-4 col-sm-12">
|
||||||
|
<label class="form-label">{{ $t('word.privateKey') }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-sm-12">
|
||||||
|
<BaseUploadInput
|
||||||
|
:value="connection.sshKey"
|
||||||
|
:message="$t('word.browse')"
|
||||||
|
@clear="pathClear('sshKey')"
|
||||||
|
@change="pathSelection($event, 'sshKey')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<BaseToast
|
||||||
|
class="mb-2"
|
||||||
|
:message="toast.message"
|
||||||
|
:status="toast.status"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer text-light">
|
<div class="modal-footer text-light">
|
||||||
@ -294,8 +389,13 @@ export default {
|
|||||||
cert: '',
|
cert: '',
|
||||||
key: '',
|
key: '',
|
||||||
ca: '',
|
ca: '',
|
||||||
ciphers: ''
|
ciphers: '',
|
||||||
|
ssh: false,
|
||||||
|
sshHost: '',
|
||||||
|
sshUser: '',
|
||||||
|
sshPass: '',
|
||||||
|
sshKey: '',
|
||||||
|
sshPort: 22
|
||||||
},
|
},
|
||||||
toast: {
|
toast: {
|
||||||
status: '',
|
status: '',
|
||||||
@ -393,6 +493,9 @@ export default {
|
|||||||
toggleSsl () {
|
toggleSsl () {
|
||||||
this.connection.ssl = !this.connection.ssl;
|
this.connection.ssl = !this.connection.ssl;
|
||||||
},
|
},
|
||||||
|
toggleSsh () {
|
||||||
|
this.connection.ssh = !this.connection.ssh;
|
||||||
|
},
|
||||||
pathSelection (event, name) {
|
pathSelection (event, name) {
|
||||||
const { files } = event.target;
|
const { files } = event.target;
|
||||||
if (!files.length) return;
|
if (!files.length) return;
|
||||||
|
@ -104,7 +104,8 @@ module.exports = {
|
|||||||
database: 'Datenbank',
|
database: 'Datenbank',
|
||||||
scratchpad: 'Scratchpad',
|
scratchpad: 'Scratchpad',
|
||||||
array: 'Array',
|
array: 'Array',
|
||||||
format: 'Formatierung'
|
format: 'Formatierung',
|
||||||
|
sshTunnel: 'SSH Tunnel'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Willkommen im Antares SQL Client!',
|
appWelcome: 'Willkommen im Antares SQL Client!',
|
||||||
@ -210,7 +211,8 @@ module.exports = {
|
|||||||
deleteSchema: 'Schema löschen',
|
deleteSchema: 'Schema löschen',
|
||||||
markdownSupported: 'Unterstützt Markdown',
|
markdownSupported: 'Unterstützt Markdown',
|
||||||
plantATree: 'Pflanze einen Baum',
|
plantATree: 'Pflanze einen Baum',
|
||||||
dataTabPageSize: 'Einträge pro Tab / Seite'
|
dataTabPageSize: 'Einträge pro Tab / Seite',
|
||||||
|
enableSsh: 'Aktiviere SSH'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Adresse',
|
address: 'Adresse',
|
||||||
|
@ -106,6 +106,7 @@ module.exports = {
|
|||||||
array: 'Array',
|
array: 'Array',
|
||||||
changelog: 'Changelog',
|
changelog: 'Changelog',
|
||||||
format: 'Format',
|
format: 'Format',
|
||||||
|
sshTunnel: 'SSH tunnel',
|
||||||
structure: 'Structure',
|
structure: 'Structure',
|
||||||
small: 'Small',
|
small: 'Small',
|
||||||
medium: 'Medium',
|
medium: 'Medium',
|
||||||
@ -219,6 +220,7 @@ module.exports = {
|
|||||||
markdownSupported: 'Markdown supported',
|
markdownSupported: 'Markdown supported',
|
||||||
plantATree: 'Plant a Tree',
|
plantATree: 'Plant a Tree',
|
||||||
dataTabPageSize: 'DATA tab page size',
|
dataTabPageSize: 'DATA tab page size',
|
||||||
|
enableSsh: 'Enable SSH',
|
||||||
pageNumber: 'Page number',
|
pageNumber: 'Page number',
|
||||||
duplicateTable: 'Duplicate table'
|
duplicateTable: 'Duplicate table'
|
||||||
},
|
},
|
||||||
|
@ -93,7 +93,8 @@ module.exports = {
|
|||||||
ciphers: 'Chiffrement',
|
ciphers: 'Chiffrement',
|
||||||
upload: 'Charger',
|
upload: 'Charger',
|
||||||
browse: 'Parcourir',
|
browse: 'Parcourir',
|
||||||
faker: 'Faker'
|
faker: 'Faker',
|
||||||
|
sshTunnel: 'SSH tunnel'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Bienvenu sur le client SQL Antares!',
|
appWelcome: 'Bienvenu sur le client SQL Antares!',
|
||||||
@ -183,7 +184,8 @@ module.exports = {
|
|||||||
preserveOnCompletion: 'Préserver à l\'achèvement',
|
preserveOnCompletion: 'Préserver à l\'achèvement',
|
||||||
enableSsl: 'Activer le SSL',
|
enableSsl: 'Activer le SSL',
|
||||||
manualValue: 'Valeur manuelle',
|
manualValue: 'Valeur manuelle',
|
||||||
tableFiller: 'Remplisseur de table'
|
tableFiller: 'Remplisseur de table',
|
||||||
|
enableSsh: 'Activer le SSH'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Adresse',
|
address: 'Adresse',
|
||||||
|
@ -105,7 +105,8 @@ module.exports = {
|
|||||||
scratchpad: 'Blocco appunti',
|
scratchpad: 'Blocco appunti',
|
||||||
array: 'Array',
|
array: 'Array',
|
||||||
changelog: 'Changelog',
|
changelog: 'Changelog',
|
||||||
format: 'Formatta'
|
format: 'Formatta',
|
||||||
|
sshTunnel: 'SSH tunnel'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Benvenuto in Antares SQL Client!',
|
appWelcome: 'Benvenuto in Antares SQL Client!',
|
||||||
@ -210,7 +211,8 @@ module.exports = {
|
|||||||
editSchema: 'Modifica schema',
|
editSchema: 'Modifica schema',
|
||||||
deleteSchema: 'Elimina schema',
|
deleteSchema: 'Elimina schema',
|
||||||
markdownSupported: 'Markdown supportato',
|
markdownSupported: 'Markdown supportato',
|
||||||
plantATree: 'Pianta un albero'
|
plantATree: 'Pianta un albero',
|
||||||
|
enableSsh: 'Abilita SSH'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Indirizzo',
|
address: 'Indirizzo',
|
||||||
|
@ -105,7 +105,8 @@ module.exports = {
|
|||||||
scratchpad: 'Rascunho',
|
scratchpad: 'Rascunho',
|
||||||
array: 'Array',
|
array: 'Array',
|
||||||
changelog: 'Logs de alteração',
|
changelog: 'Logs de alteração',
|
||||||
format: 'Formato'
|
format: 'Formato',
|
||||||
|
sshTunnel: 'SSH túnel'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Bem vindo ao Antares SQL Client!',
|
appWelcome: 'Bem vindo ao Antares SQL Client!',
|
||||||
@ -210,7 +211,8 @@ module.exports = {
|
|||||||
editSchema: 'Editar schema',
|
editSchema: 'Editar schema',
|
||||||
deleteSchema: 'Apagar schema',
|
deleteSchema: 'Apagar schema',
|
||||||
markdownSupported: 'Markdown suportado',
|
markdownSupported: 'Markdown suportado',
|
||||||
plantATree: 'Plante uma árvore'
|
plantATree: 'Plante uma árvore',
|
||||||
|
enableSsh: 'Habilitar SSH'
|
||||||
},
|
},
|
||||||
faker: {
|
faker: {
|
||||||
address: 'Endereço',
|
address: 'Endereço',
|
||||||
|
@ -215,8 +215,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bg-checkered {
|
.bg-checkered {
|
||||||
background-image: linear-gradient(to right, rgba(192, 192, 192, 0.75), rgba(192, 192, 192, 0.75)),
|
background-image:
|
||||||
linear-gradient(to right, black 50%, white 50%), linear-gradient(to bottom, black 50%, white 50%);
|
linear-gradient(to right, rgba(192, 192, 192, 0.75), rgba(192, 192, 192, 0.75)),
|
||||||
|
linear-gradient(to right, black 50%, white 50%),
|
||||||
|
linear-gradient(to bottom, black 50%, white 50%);
|
||||||
background-blend-mode: normal, difference, normal;
|
background-blend-mode: normal, difference, normal;
|
||||||
background-size: 2em 2em;
|
background-size: 2em 2em;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user