mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-29 06:26:00 +00:00
SYNC: Merge pull request #19 from dbgate/feature/sfill
This commit is contained in:
@@ -22,6 +22,7 @@
|
|||||||
"start:api:auth": "yarn workspace dbgate-api start:auth | pino-pretty",
|
"start:api:auth": "yarn workspace dbgate-api start:auth | pino-pretty",
|
||||||
"start:api:dblogin": "yarn workspace dbgate-api start:dblogin | pino-pretty",
|
"start:api:dblogin": "yarn workspace dbgate-api start:dblogin | pino-pretty",
|
||||||
"start:api:storage": "yarn workspace dbgate-api start:storage | pino-pretty",
|
"start:api:storage": "yarn workspace dbgate-api start:storage | pino-pretty",
|
||||||
|
"start:api:sfill": "yarn workspace dbgate-api start:sfill | pino-pretty",
|
||||||
"start:api:storage:built": "yarn workspace dbgate-api start:storage:built | pino-pretty",
|
"start:api:storage:built": "yarn workspace dbgate-api start:storage:built | pino-pretty",
|
||||||
"start:api:azure": "yarn workspace dbgate-api start:azure | pino-pretty",
|
"start:api:azure": "yarn workspace dbgate-api start:azure | pino-pretty",
|
||||||
"start:api:e2e:team": "yarn workspace dbgate-api start:e2e:team | pino-pretty",
|
"start:api:e2e:team": "yarn workspace dbgate-api start:e2e:team | pino-pretty",
|
||||||
|
|||||||
46
packages/api/env/sfill/.env
vendored
Normal file
46
packages/api/env/sfill/.env
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
DEVMODE=1
|
||||||
|
DEVWEB=1
|
||||||
|
|
||||||
|
STORAGE_SERVER=localhost
|
||||||
|
STORAGE_USER=root
|
||||||
|
STORAGE_PASSWORD=Pwd2020Db
|
||||||
|
STORAGE_PORT=3306
|
||||||
|
STORAGE_DATABASE=dbgate-filled
|
||||||
|
STORAGE_ENGINE=mysql@dbgate-plugin-mysql
|
||||||
|
|
||||||
|
CONNECTIONS=mysql,postgres,mongo,redis
|
||||||
|
|
||||||
|
LABEL_mysql=MySql
|
||||||
|
SERVER_mysql=dbgatedckstage1.sprinx.cz
|
||||||
|
USER_mysql=root
|
||||||
|
PASSWORD_mysql=Pwd2020Db
|
||||||
|
PORT_mysql=3306
|
||||||
|
ENGINE_mysql=mysql@dbgate-plugin-mysql
|
||||||
|
|
||||||
|
LABEL_postgres=Postgres
|
||||||
|
SERVER_postgres=dbgatedckstage1.sprinx.cz
|
||||||
|
USER_postgres=postgres
|
||||||
|
PASSWORD_postgres=Pwd2020Db
|
||||||
|
PORT_postgres=5432
|
||||||
|
ENGINE_postgres=postgres@dbgate-plugin-postgres
|
||||||
|
|
||||||
|
LABEL_mongo=Mongo
|
||||||
|
SERVER_mongo=dbgatedckstage1.sprinx.cz
|
||||||
|
USER_mongo=root
|
||||||
|
PASSWORD_mongo=Pwd2020Db
|
||||||
|
PORT_mongo=27017
|
||||||
|
ENGINE_mongo=mongo@dbgate-plugin-mongo
|
||||||
|
|
||||||
|
LABEL_redis=Redis
|
||||||
|
SERVER_redis=dbgatedckstage1.sprinx.cz
|
||||||
|
ENGINE_redis=redis@dbgate-plugin-redis
|
||||||
|
PORT_redis=6379
|
||||||
|
|
||||||
|
ROLE_test1_CONNECTIONS=mysql
|
||||||
|
ROLE_test1_PERMISSIONS=widgets/*
|
||||||
|
ROLE_test1_DATABASES_db1_CONNECTION=mysql
|
||||||
|
ROLE_test1_DATABASES_db1_PERMISSION=run_script
|
||||||
|
ROLE_test1_DATABASES_db1_DATABASES=db1
|
||||||
|
ROLE_test1_DATABASES_db2_CONNECTION=redis
|
||||||
|
ROLE_test1_DATABASES_db2_PERMISSION=run_script
|
||||||
|
ROLE_test1_DATABASES_db2_DATABASES=db2
|
||||||
@@ -75,6 +75,7 @@
|
|||||||
"start:dblogin": "env-cmd -f env/dblogin/.env node src/index.js --listen-api",
|
"start:dblogin": "env-cmd -f env/dblogin/.env node src/index.js --listen-api",
|
||||||
"start:filedb": "env-cmd node src/index.js /home/jena/test/chinook/Chinook.db --listen-api",
|
"start:filedb": "env-cmd node src/index.js /home/jena/test/chinook/Chinook.db --listen-api",
|
||||||
"start:storage": "env-cmd -f env/storage/.env node src/index.js --listen-api",
|
"start:storage": "env-cmd -f env/storage/.env node src/index.js --listen-api",
|
||||||
|
"start:sfill": "env-cmd -f env/sfill/.env node src/index.js --listen-api",
|
||||||
"start:storage:built": "env-cmd -f env/storage/.env cross-env DEVMODE= BUILTWEBMODE=1 node dist/bundle.js --listen-api",
|
"start:storage:built": "env-cmd -f env/storage/.env cross-env DEVMODE= BUILTWEBMODE=1 node dist/bundle.js --listen-api",
|
||||||
"start:singleconn": "env-cmd node src/index.js --server localhost --user root --port 3307 --engine mysql@dbgate-plugin-mysql --password test --listen-api",
|
"start:singleconn": "env-cmd node src/index.js --server localhost --user root --port 3307 --engine mysql@dbgate-plugin-mysql --password test --listen-api",
|
||||||
"start:azure": "env-cmd -f env/azure/.env node src/index.js --listen-api",
|
"start:azure": "env-cmd -f env/azure/.env node src/index.js --listen-api",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ const pipeForkLogs = require('../utility/pipeForkLogs');
|
|||||||
const requireEngineDriver = require('../utility/requireEngineDriver');
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
||||||
const { getAuthProviderById } = require('../auth/authProvider');
|
const { getAuthProviderById } = require('../auth/authProvider');
|
||||||
const { startTokenChecking } = require('../utility/authProxy');
|
const { startTokenChecking } = require('../utility/authProxy');
|
||||||
|
const { extractConnectionsFromEnv } = require('../utility/envtools');
|
||||||
|
|
||||||
const logger = getLogger('connections');
|
const logger = getLogger('connections');
|
||||||
|
|
||||||
@@ -61,55 +62,7 @@ function getDatabaseFileLabel(databaseFile) {
|
|||||||
|
|
||||||
function getPortalCollections() {
|
function getPortalCollections() {
|
||||||
if (process.env.CONNECTIONS) {
|
if (process.env.CONNECTIONS) {
|
||||||
const connections = _.compact(process.env.CONNECTIONS.split(',')).map(id => ({
|
const connections = extractConnectionsFromEnv(process.env);
|
||||||
_id: id,
|
|
||||||
engine: process.env[`ENGINE_${id}`],
|
|
||||||
server: process.env[`SERVER_${id}`],
|
|
||||||
user: process.env[`USER_${id}`],
|
|
||||||
password: process.env[`PASSWORD_${id}`],
|
|
||||||
passwordMode: process.env[`PASSWORD_MODE_${id}`],
|
|
||||||
port: process.env[`PORT_${id}`],
|
|
||||||
databaseUrl: process.env[`URL_${id}`],
|
|
||||||
useDatabaseUrl: !!process.env[`URL_${id}`],
|
|
||||||
databaseFile: process.env[`FILE_${id}`]?.replace(
|
|
||||||
'%%E2E_TEST_DATA_DIRECTORY%%',
|
|
||||||
path.join(path.dirname(path.dirname(__dirname)), 'e2e-tests', 'tmpdata')
|
|
||||||
),
|
|
||||||
socketPath: process.env[`SOCKET_PATH_${id}`],
|
|
||||||
serviceName: process.env[`SERVICE_NAME_${id}`],
|
|
||||||
authType: process.env[`AUTH_TYPE_${id}`] || (process.env[`SOCKET_PATH_${id}`] ? 'socket' : undefined),
|
|
||||||
defaultDatabase:
|
|
||||||
process.env[`DATABASE_${id}`] ||
|
|
||||||
(process.env[`FILE_${id}`] ? getDatabaseFileLabel(process.env[`FILE_${id}`]) : null),
|
|
||||||
singleDatabase: !!process.env[`DATABASE_${id}`] || !!process.env[`FILE_${id}`],
|
|
||||||
displayName: process.env[`LABEL_${id}`],
|
|
||||||
isReadOnly: process.env[`READONLY_${id}`],
|
|
||||||
databases: process.env[`DBCONFIG_${id}`] ? safeJsonParse(process.env[`DBCONFIG_${id}`]) : null,
|
|
||||||
allowedDatabases: process.env[`ALLOWED_DATABASES_${id}`]?.replace(/\|/g, '\n'),
|
|
||||||
allowedDatabasesRegex: process.env[`ALLOWED_DATABASES_REGEX_${id}`],
|
|
||||||
parent: process.env[`PARENT_${id}`] || undefined,
|
|
||||||
useSeparateSchemas: !!process.env[`USE_SEPARATE_SCHEMAS_${id}`],
|
|
||||||
localDataCenter: process.env[`LOCAL_DATA_CENTER_${id}`],
|
|
||||||
|
|
||||||
// SSH tunnel
|
|
||||||
useSshTunnel: process.env[`USE_SSH_${id}`],
|
|
||||||
sshHost: process.env[`SSH_HOST_${id}`],
|
|
||||||
sshPort: process.env[`SSH_PORT_${id}`],
|
|
||||||
sshMode: process.env[`SSH_MODE_${id}`],
|
|
||||||
sshLogin: process.env[`SSH_LOGIN_${id}`],
|
|
||||||
sshPassword: process.env[`SSH_PASSWORD_${id}`],
|
|
||||||
sshKeyfile: process.env[`SSH_KEY_FILE_${id}`],
|
|
||||||
sshKeyfilePassword: process.env[`SSH_KEY_FILE_PASSWORD_${id}`],
|
|
||||||
|
|
||||||
// SSL
|
|
||||||
useSsl: process.env[`USE_SSL_${id}`],
|
|
||||||
sslCaFile: process.env[`SSL_CA_FILE_${id}`],
|
|
||||||
sslCertFile: process.env[`SSL_CERT_FILE_${id}`],
|
|
||||||
sslCertFilePassword: process.env[`SSL_CERT_FILE_PASSWORD_${id}`],
|
|
||||||
sslKeyFile: process.env[`SSL_KEY_FILE_${id}`],
|
|
||||||
sslRejectUnauthorized: process.env[`SSL_REJECT_UNAUTHORIZED_${id}`],
|
|
||||||
trustServerCertificate: process.env[`SSL_TRUST_CERTIFICATE_${id}`],
|
|
||||||
}));
|
|
||||||
|
|
||||||
for (const conn of connections) {
|
for (const conn of connections) {
|
||||||
for (const prop in process.env) {
|
for (const prop in process.env) {
|
||||||
@@ -229,6 +182,15 @@ module.exports = {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
await this.checkUnsavedConnectionsLimit();
|
await this.checkUnsavedConnectionsLimit();
|
||||||
|
|
||||||
|
if (process.env.STORAGE_DATABASE && process.env.CONNECTIONS) {
|
||||||
|
const storage = require('./storage');
|
||||||
|
try {
|
||||||
|
await storage.fillStorageConnectionsFromEnv();
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(extractErrorLogData(err), 'DBGM-00268 Error filling storage connections from env');
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
list_meta: true,
|
list_meta: true,
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ async function copyStream(input, output, options) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error(extractErrorLogData(err, { progressName }), 'DBGM-00157 Import/export job failed');
|
||||||
|
|
||||||
process.send({
|
process.send({
|
||||||
msgtype: 'copyStreamError',
|
msgtype: 'copyStreamError',
|
||||||
copyStreamError: {
|
copyStreamError: {
|
||||||
@@ -82,8 +84,6 @@ async function copyStream(input, output, options) {
|
|||||||
errorMessage: extractErrorMessage(err),
|
errorMessage: extractErrorMessage(err),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.error(extractErrorLogData(err, { progressName }), 'DBGM-00157 Import/export job failed');
|
|
||||||
// throw err;
|
// throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -686,9 +686,34 @@ module.exports = {
|
|||||||
"columnName": "connectionDefinition",
|
"columnName": "connectionDefinition",
|
||||||
"dataType": "text",
|
"dataType": "text",
|
||||||
"notNull": false
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pureName": "connections",
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"dataType": "int",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pureName": "connections",
|
||||||
|
"columnName": "id_original",
|
||||||
|
"dataType": "varchar(250)",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"constraintType": "foreignKey",
|
||||||
|
"constraintName": "FK_connections_import_source_id",
|
||||||
|
"pureName": "connections",
|
||||||
|
"refTableName": "import_sources",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"refColumnName": "id"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"foreignKeys": [],
|
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
"pureName": "connections",
|
"pureName": "connections",
|
||||||
"constraintType": "primaryKey",
|
"constraintType": "primaryKey",
|
||||||
@@ -790,6 +815,41 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pureName": "import_sources",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"pureName": "import_sources",
|
||||||
|
"columnName": "id",
|
||||||
|
"dataType": "int",
|
||||||
|
"autoIncrement": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pureName": "import_sources",
|
||||||
|
"columnName": "name",
|
||||||
|
"dataType": "varchar(250)",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [],
|
||||||
|
"primaryKey": {
|
||||||
|
"pureName": "import_sources",
|
||||||
|
"constraintType": "primaryKey",
|
||||||
|
"constraintName": "PK_import_sources",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"columnName": "id"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"preloadedRows": [
|
||||||
|
{
|
||||||
|
"id": -1,
|
||||||
|
"name": "env"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pureName": "roles",
|
"pureName": "roles",
|
||||||
"columns": [
|
"columns": [
|
||||||
@@ -805,9 +865,34 @@ module.exports = {
|
|||||||
"columnName": "name",
|
"columnName": "name",
|
||||||
"dataType": "varchar(250)",
|
"dataType": "varchar(250)",
|
||||||
"notNull": false
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pureName": "roles",
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"dataType": "int",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pureName": "roles",
|
||||||
|
"columnName": "id_original",
|
||||||
|
"dataType": "varchar(250)",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"constraintType": "foreignKey",
|
||||||
|
"constraintName": "FK_roles_import_source_id",
|
||||||
|
"pureName": "roles",
|
||||||
|
"refTableName": "import_sources",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"refColumnName": "id"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"foreignKeys": [],
|
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
"pureName": "roles",
|
"pureName": "roles",
|
||||||
"constraintType": "primaryKey",
|
"constraintType": "primaryKey",
|
||||||
@@ -854,6 +939,12 @@ module.exports = {
|
|||||||
"columnName": "connection_id",
|
"columnName": "connection_id",
|
||||||
"dataType": "int",
|
"dataType": "int",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pureName": "role_connections",
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"dataType": "int",
|
||||||
|
"notNull": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"foreignKeys": [
|
"foreignKeys": [
|
||||||
@@ -882,6 +973,18 @@ module.exports = {
|
|||||||
"refColumnName": "id"
|
"refColumnName": "id"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constraintType": "foreignKey",
|
||||||
|
"constraintName": "FK_role_connections_import_source_id",
|
||||||
|
"pureName": "role_connections",
|
||||||
|
"refTableName": "import_sources",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"refColumnName": "id"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
@@ -934,6 +1037,18 @@ module.exports = {
|
|||||||
"columnName": "database_permission_role_id",
|
"columnName": "database_permission_role_id",
|
||||||
"dataType": "int",
|
"dataType": "int",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pureName": "role_databases",
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"dataType": "int",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pureName": "role_databases",
|
||||||
|
"columnName": "id_original",
|
||||||
|
"dataType": "varchar(250)",
|
||||||
|
"notNull": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"foreignKeys": [
|
"foreignKeys": [
|
||||||
@@ -974,6 +1089,18 @@ module.exports = {
|
|||||||
"refColumnName": "id"
|
"refColumnName": "id"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constraintType": "foreignKey",
|
||||||
|
"constraintName": "FK_role_databases_import_source_id",
|
||||||
|
"pureName": "role_databases",
|
||||||
|
"refTableName": "import_sources",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"refColumnName": "id"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
@@ -1087,6 +1214,12 @@ module.exports = {
|
|||||||
"columnName": "permission",
|
"columnName": "permission",
|
||||||
"dataType": "varchar(250)",
|
"dataType": "varchar(250)",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pureName": "role_permissions",
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"dataType": "int",
|
||||||
|
"notNull": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"foreignKeys": [
|
"foreignKeys": [
|
||||||
@@ -1102,6 +1235,18 @@ module.exports = {
|
|||||||
"refColumnName": "id"
|
"refColumnName": "id"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constraintType": "foreignKey",
|
||||||
|
"constraintName": "FK_role_permissions_import_source_id",
|
||||||
|
"pureName": "role_permissions",
|
||||||
|
"refTableName": "import_sources",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"refColumnName": "id"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
@@ -1184,6 +1329,18 @@ module.exports = {
|
|||||||
"columnName": "table_permission_scope_id",
|
"columnName": "table_permission_scope_id",
|
||||||
"dataType": "int",
|
"dataType": "int",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pureName": "role_tables",
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"dataType": "int",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pureName": "role_tables",
|
||||||
|
"columnName": "id_original",
|
||||||
|
"dataType": "varchar(250)",
|
||||||
|
"notNull": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"foreignKeys": [
|
"foreignKeys": [
|
||||||
@@ -1236,6 +1393,18 @@ module.exports = {
|
|||||||
"refColumnName": "id"
|
"refColumnName": "id"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constraintType": "foreignKey",
|
||||||
|
"constraintName": "FK_role_tables_import_source_id",
|
||||||
|
"pureName": "role_tables",
|
||||||
|
"refTableName": "import_sources",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"columnName": "import_source_id",
|
||||||
|
"refColumnName": "id"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
|
|||||||
445
packages/api/src/utility/envtools.js
Normal file
445
packages/api/src/utility/envtools.js
Normal file
@@ -0,0 +1,445 @@
|
|||||||
|
const path = require('path');
|
||||||
|
const _ = require('lodash');
|
||||||
|
const { safeJsonParse, getDatabaseFileLabel } = require('dbgate-tools');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
function extractConnectionsFromEnv(env) {
|
||||||
|
if (!env?.CONNECTIONS) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const connections = _.compact(env.CONNECTIONS.split(',')).map(id => ({
|
||||||
|
_id: id,
|
||||||
|
engine: env[`ENGINE_${id}`],
|
||||||
|
server: env[`SERVER_${id}`],
|
||||||
|
user: env[`USER_${id}`],
|
||||||
|
password: env[`PASSWORD_${id}`],
|
||||||
|
passwordMode: env[`PASSWORD_MODE_${id}`],
|
||||||
|
port: env[`PORT_${id}`],
|
||||||
|
databaseUrl: env[`URL_${id}`],
|
||||||
|
useDatabaseUrl: !!env[`URL_${id}`],
|
||||||
|
databaseFile: env[`FILE_${id}`]?.replace(
|
||||||
|
'%%E2E_TEST_DATA_DIRECTORY%%',
|
||||||
|
path.join(path.dirname(path.dirname(__dirname)), 'e2e-tests', 'tmpdata')
|
||||||
|
),
|
||||||
|
socketPath: env[`SOCKET_PATH_${id}`],
|
||||||
|
serviceName: env[`SERVICE_NAME_${id}`],
|
||||||
|
authType: env[`AUTH_TYPE_${id}`] || (env[`SOCKET_PATH_${id}`] ? 'socket' : undefined),
|
||||||
|
defaultDatabase: env[`DATABASE_${id}`] || (env[`FILE_${id}`] ? getDatabaseFileLabel(env[`FILE_${id}`]) : null),
|
||||||
|
singleDatabase: !!env[`DATABASE_${id}`] || !!env[`FILE_${id}`],
|
||||||
|
displayName: env[`LABEL_${id}`],
|
||||||
|
isReadOnly: env[`READONLY_${id}`],
|
||||||
|
databases: env[`DBCONFIG_${id}`] ? safeJsonParse(env[`DBCONFIG_${id}`]) : null,
|
||||||
|
allowedDatabases: env[`ALLOWED_DATABASES_${id}`]?.replace(/\|/g, '\n'),
|
||||||
|
allowedDatabasesRegex: env[`ALLOWED_DATABASES_REGEX_${id}`],
|
||||||
|
parent: env[`PARENT_${id}`] || undefined,
|
||||||
|
useSeparateSchemas: !!env[`USE_SEPARATE_SCHEMAS_${id}`],
|
||||||
|
localDataCenter: env[`LOCAL_DATA_CENTER_${id}`],
|
||||||
|
|
||||||
|
// SSH tunnel
|
||||||
|
useSshTunnel: env[`USE_SSH_${id}`],
|
||||||
|
sshHost: env[`SSH_HOST_${id}`],
|
||||||
|
sshPort: env[`SSH_PORT_${id}`],
|
||||||
|
sshMode: env[`SSH_MODE_${id}`],
|
||||||
|
sshLogin: env[`SSH_LOGIN_${id}`],
|
||||||
|
sshPassword: env[`SSH_PASSWORD_${id}`],
|
||||||
|
sshKeyfile: env[`SSH_KEY_FILE_${id}`],
|
||||||
|
sshKeyfilePassword: env[`SSH_KEY_FILE_PASSWORD_${id}`],
|
||||||
|
|
||||||
|
// SSL
|
||||||
|
useSsl: env[`USE_SSL_${id}`],
|
||||||
|
sslCaFile: env[`SSL_CA_FILE_${id}`],
|
||||||
|
sslCertFile: env[`SSL_CERT_FILE_${id}`],
|
||||||
|
sslCertFilePassword: env[`SSL_CERT_FILE_PASSWORD_${id}`],
|
||||||
|
sslKeyFile: env[`SSL_KEY_FILE_${id}`],
|
||||||
|
sslRejectUnauthorized: env[`SSL_REJECT_UNAUTHORIZED_${id}`],
|
||||||
|
trustServerCertificate: env[`SSL_TRUST_CERTIFICATE_${id}`],
|
||||||
|
}));
|
||||||
|
|
||||||
|
return connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractImportEntitiesFromEnv(env) {
|
||||||
|
const portalConnections = extractConnectionsFromEnv(env) || [];
|
||||||
|
|
||||||
|
const connections = portalConnections.map((conn, index) => ({
|
||||||
|
...conn,
|
||||||
|
id_original: conn._id,
|
||||||
|
import_source_id: -1,
|
||||||
|
conid: crypto.randomUUID(),
|
||||||
|
_id: undefined,
|
||||||
|
id: index + 1, // autoincrement id
|
||||||
|
}));
|
||||||
|
|
||||||
|
const connectionEnvIdToDbId = {};
|
||||||
|
for (const conn of connections) {
|
||||||
|
connectionEnvIdToDbId[conn.id_original] = conn.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const connectionsRegex = /^ROLE_(.+)_CONNECTIONS$/;
|
||||||
|
const permissionsRegex = /^ROLE_(.+)_PERMISSIONS$/;
|
||||||
|
|
||||||
|
const dbConnectionRegex = /^ROLE_(.+)_DATABASES_(.+)_CONNECTION$/;
|
||||||
|
const dbDatabasesRegex = /^ROLE_(.+)_DATABASES_(.+)_DATABASES$/;
|
||||||
|
const dbDatabasesRegexRegex = /^ROLE_(.+)_DATABASES_(.+)_DATABASES_REGEX$/;
|
||||||
|
const dbPermissionRegex = /^ROLE_(.+)_DATABASES_(.+)_PERMISSION$/;
|
||||||
|
|
||||||
|
const tableConnectionRegex = /^ROLE_(.+)_TABLES_(.+)_CONNECTION$/;
|
||||||
|
const tableDatabasesRegex = /^ROLE_(.+)_TABLES_(.+)_DATABASES$/;
|
||||||
|
const tableDatabasesRegexRegex = /^ROLE_(.+)_TABLES_(.+)_DATABASES_REGEX$/;
|
||||||
|
const tableSchemasRegex = /^ROLE_(.+)_TABLES_(.+)_SCHEMAS$/;
|
||||||
|
const tableSchemasRegexRegex = /^ROLE_(.+)_TABLES_(.+)_SCHEMAS_REGEX$/;
|
||||||
|
const tableTablesRegex = /^ROLE_(.+)_TABLES_(.+)_TABLES$/;
|
||||||
|
const tableTablesRegexRegex = /^ROLE_(.+)_TABLES_(.+)_TABLES_REGEX$/;
|
||||||
|
const tablePermissionRegex = /^ROLE_(.+)_TABLES_(.+)_PERMISSION$/;
|
||||||
|
const tableScopeRegex = /^ROLE_(.+)_TABLES_(.+)_SCOPE$/;
|
||||||
|
|
||||||
|
const roles = [];
|
||||||
|
const role_connections = [];
|
||||||
|
const role_permissions = [];
|
||||||
|
const role_databases = [];
|
||||||
|
const role_tables = [];
|
||||||
|
|
||||||
|
// Permission name to ID mappings
|
||||||
|
const databasePermissionMap = {
|
||||||
|
view: -1,
|
||||||
|
read_content: -2,
|
||||||
|
write_data: -3,
|
||||||
|
run_script: -4,
|
||||||
|
deny: -5,
|
||||||
|
};
|
||||||
|
|
||||||
|
const tablePermissionMap = {
|
||||||
|
read: -1,
|
||||||
|
update_only: -2,
|
||||||
|
create_update_delete: -3,
|
||||||
|
run_script: -4,
|
||||||
|
deny: -5,
|
||||||
|
};
|
||||||
|
|
||||||
|
const tableScopeMap = {
|
||||||
|
all_objects: -1,
|
||||||
|
tables: -2,
|
||||||
|
views: -3,
|
||||||
|
tables_views_collections: -4,
|
||||||
|
procedures: -5,
|
||||||
|
functions: -6,
|
||||||
|
triggers: -7,
|
||||||
|
sql_objects: -8,
|
||||||
|
collections: -9,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Collect database and table permissions data
|
||||||
|
const databasePermissions = {};
|
||||||
|
const tablePermissions = {};
|
||||||
|
|
||||||
|
// First pass: collect all database and table permission data
|
||||||
|
for (const key in env) {
|
||||||
|
const dbConnMatch = key.match(dbConnectionRegex);
|
||||||
|
const dbDatabasesMatch = key.match(dbDatabasesRegex);
|
||||||
|
const dbDatabasesRegexMatch = key.match(dbDatabasesRegexRegex);
|
||||||
|
const dbPermMatch = key.match(dbPermissionRegex);
|
||||||
|
|
||||||
|
const tableConnMatch = key.match(tableConnectionRegex);
|
||||||
|
const tableDatabasesMatch = key.match(tableDatabasesRegex);
|
||||||
|
const tableDatabasesRegexMatch = key.match(tableDatabasesRegexRegex);
|
||||||
|
const tableSchemasMatch = key.match(tableSchemasRegex);
|
||||||
|
const tableSchemasRegexMatch = key.match(tableSchemasRegexRegex);
|
||||||
|
const tableTablesMatch = key.match(tableTablesRegex);
|
||||||
|
const tableTablesRegexMatch = key.match(tableTablesRegexRegex);
|
||||||
|
const tablePermMatch = key.match(tablePermissionRegex);
|
||||||
|
const tableScopeMatch = key.match(tableScopeRegex);
|
||||||
|
|
||||||
|
// Database permissions
|
||||||
|
if (dbConnMatch) {
|
||||||
|
const [, roleName, permId] = dbConnMatch;
|
||||||
|
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
||||||
|
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
||||||
|
databasePermissions[roleName][permId].connection = env[key];
|
||||||
|
}
|
||||||
|
if (dbDatabasesMatch) {
|
||||||
|
const [, roleName, permId] = dbDatabasesMatch;
|
||||||
|
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
||||||
|
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
||||||
|
databasePermissions[roleName][permId].databases = env[key]?.replace(/\|/g, '\n');
|
||||||
|
}
|
||||||
|
if (dbDatabasesRegexMatch) {
|
||||||
|
const [, roleName, permId] = dbDatabasesRegexMatch;
|
||||||
|
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
||||||
|
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
||||||
|
databasePermissions[roleName][permId].databasesRegex = env[key];
|
||||||
|
}
|
||||||
|
if (dbPermMatch) {
|
||||||
|
const [, roleName, permId] = dbPermMatch;
|
||||||
|
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
||||||
|
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
||||||
|
databasePermissions[roleName][permId].permission = env[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table permissions
|
||||||
|
if (tableConnMatch) {
|
||||||
|
const [, roleName, permId] = tableConnMatch;
|
||||||
|
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||||
|
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||||
|
tablePermissions[roleName][permId].connection = env[key];
|
||||||
|
}
|
||||||
|
if (tableDatabasesMatch) {
|
||||||
|
const [, roleName, permId] = tableDatabasesMatch;
|
||||||
|
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||||
|
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||||
|
tablePermissions[roleName][permId].databases = env[key]?.replace(/\|/g, '\n');
|
||||||
|
}
|
||||||
|
if (tableDatabasesRegexMatch) {
|
||||||
|
const [, roleName, permId] = tableDatabasesRegexMatch;
|
||||||
|
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||||
|
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||||
|
tablePermissions[roleName][permId].databasesRegex = env[key];
|
||||||
|
}
|
||||||
|
if (tableSchemasMatch) {
|
||||||
|
const [, roleName, permId] = tableSchemasMatch;
|
||||||
|
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||||
|
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||||
|
tablePermissions[roleName][permId].schemas = env[key];
|
||||||
|
}
|
||||||
|
if (tableSchemasRegexMatch) {
|
||||||
|
const [, roleName, permId] = tableSchemasRegexMatch;
|
||||||
|
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||||
|
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||||
|
tablePermissions[roleName][permId].schemasRegex = env[key];
|
||||||
|
}
|
||||||
|
if (tableTablesMatch) {
|
||||||
|
const [, roleName, permId] = tableTablesMatch;
|
||||||
|
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||||
|
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||||
|
tablePermissions[roleName][permId].tables = env[key]?.replace(/\|/g, '\n');
|
||||||
|
}
|
||||||
|
if (tableTablesRegexMatch) {
|
||||||
|
const [, roleName, permId] = tableTablesRegexMatch;
|
||||||
|
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||||
|
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||||
|
tablePermissions[roleName][permId].tablesRegex = env[key];
|
||||||
|
}
|
||||||
|
if (tablePermMatch) {
|
||||||
|
const [, roleName, permId] = tablePermMatch;
|
||||||
|
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||||
|
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||||
|
tablePermissions[roleName][permId].permission = env[key];
|
||||||
|
}
|
||||||
|
if (tableScopeMatch) {
|
||||||
|
const [, roleName, permId] = tableScopeMatch;
|
||||||
|
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
||||||
|
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
||||||
|
tablePermissions[roleName][permId].scope = env[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second pass: process roles, connections, and permissions
|
||||||
|
for (const key in env) {
|
||||||
|
const connMatch = key.match(connectionsRegex);
|
||||||
|
const permMatch = key.match(permissionsRegex);
|
||||||
|
if (connMatch) {
|
||||||
|
const roleName = connMatch[1];
|
||||||
|
let role = roles.find(r => r.name === roleName);
|
||||||
|
if (!role) {
|
||||||
|
role = {
|
||||||
|
id: roles.length + 1,
|
||||||
|
name: roleName,
|
||||||
|
import_source_id: -1,
|
||||||
|
};
|
||||||
|
roles.push(role);
|
||||||
|
}
|
||||||
|
const connIds = env[key]
|
||||||
|
.split(',')
|
||||||
|
.map(id => id.trim())
|
||||||
|
.filter(id => id.length > 0);
|
||||||
|
for (const connId of connIds) {
|
||||||
|
const dbId = connectionEnvIdToDbId[connId];
|
||||||
|
if (dbId) {
|
||||||
|
role_connections.push({
|
||||||
|
role_id: role.id,
|
||||||
|
connection_id: dbId,
|
||||||
|
import_source_id: -1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (permMatch) {
|
||||||
|
const roleName = permMatch[1];
|
||||||
|
let role = roles.find(r => r.name === roleName);
|
||||||
|
if (!role) {
|
||||||
|
role = {
|
||||||
|
id: roles.length + 1,
|
||||||
|
name: roleName,
|
||||||
|
import_source_id: -1,
|
||||||
|
};
|
||||||
|
roles.push(role);
|
||||||
|
}
|
||||||
|
const permissions = env[key]
|
||||||
|
.split(',')
|
||||||
|
.map(p => p.trim())
|
||||||
|
.filter(p => p.length > 0);
|
||||||
|
for (const permission of permissions) {
|
||||||
|
role_permissions.push({
|
||||||
|
role_id: role.id,
|
||||||
|
permission,
|
||||||
|
import_source_id: -1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process database permissions
|
||||||
|
for (const roleName in databasePermissions) {
|
||||||
|
let role = roles.find(r => r.name === roleName);
|
||||||
|
if (!role) {
|
||||||
|
role = {
|
||||||
|
id: roles.length + 1,
|
||||||
|
name: roleName,
|
||||||
|
import_source_id: -1,
|
||||||
|
};
|
||||||
|
roles.push(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const permId in databasePermissions[roleName]) {
|
||||||
|
const perm = databasePermissions[roleName][permId];
|
||||||
|
if (perm.connection && perm.permission) {
|
||||||
|
const dbId = connectionEnvIdToDbId[perm.connection];
|
||||||
|
const permissionId = databasePermissionMap[perm.permission];
|
||||||
|
if (dbId && permissionId) {
|
||||||
|
role_databases.push({
|
||||||
|
role_id: role.id,
|
||||||
|
connection_id: dbId,
|
||||||
|
database_names_list: perm.databases || null,
|
||||||
|
database_names_regex: perm.databasesRegex || null,
|
||||||
|
database_permission_role_id: permissionId,
|
||||||
|
id_original: permId,
|
||||||
|
import_source_id: -1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process table permissions
|
||||||
|
for (const roleName in tablePermissions) {
|
||||||
|
let role = roles.find(r => r.name === roleName);
|
||||||
|
if (!role) {
|
||||||
|
role = {
|
||||||
|
id: roles.length + 1,
|
||||||
|
name: roleName,
|
||||||
|
import_source_id: -1,
|
||||||
|
};
|
||||||
|
roles.push(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const permId in tablePermissions[roleName]) {
|
||||||
|
const perm = tablePermissions[roleName][permId];
|
||||||
|
if (perm.connection && perm.permission) {
|
||||||
|
const dbId = connectionEnvIdToDbId[perm.connection];
|
||||||
|
const permissionId = tablePermissionMap[perm.permission];
|
||||||
|
const scopeId = tableScopeMap[perm.scope || 'all_objects'];
|
||||||
|
if (dbId && permissionId && scopeId) {
|
||||||
|
role_tables.push({
|
||||||
|
role_id: role.id,
|
||||||
|
connection_id: dbId,
|
||||||
|
database_names_list: perm.databases || null,
|
||||||
|
database_names_regex: perm.databasesRegex || null,
|
||||||
|
schema_names_list: perm.schemas || null,
|
||||||
|
schema_names_regex: perm.schemasRegex || null,
|
||||||
|
table_names_list: perm.tables || null,
|
||||||
|
table_names_regex: perm.tablesRegex || null,
|
||||||
|
table_permission_role_id: permissionId,
|
||||||
|
table_permission_scope_id: scopeId,
|
||||||
|
id_original: permId,
|
||||||
|
import_source_id: -1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connections.length == 0 && roles.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
connections,
|
||||||
|
roles,
|
||||||
|
role_connections,
|
||||||
|
role_permissions,
|
||||||
|
role_databases,
|
||||||
|
role_tables,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function createStorageFromEnvReplicatorItems(importEntities) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: 'connections',
|
||||||
|
findExisting: true,
|
||||||
|
createNew: true,
|
||||||
|
updateExisting: true,
|
||||||
|
matchColumns: ['id_original', 'import_source_id'],
|
||||||
|
deleteMissing: true,
|
||||||
|
deleteRestrictionColumns: ['import_source_id'],
|
||||||
|
skipUpdateColumns: ['conid'],
|
||||||
|
jsonArray: importEntities.connections,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'roles',
|
||||||
|
findExisting: true,
|
||||||
|
createNew: true,
|
||||||
|
updateExisting: true,
|
||||||
|
matchColumns: ['name', 'import_source_id'],
|
||||||
|
deleteMissing: true,
|
||||||
|
deleteRestrictionColumns: ['import_source_id'],
|
||||||
|
jsonArray: importEntities.roles,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'role_connections',
|
||||||
|
findExisting: true,
|
||||||
|
createNew: true,
|
||||||
|
updateExisting: false,
|
||||||
|
deleteMissing: true,
|
||||||
|
matchColumns: ['role_id', 'connection_id', 'import_source_id'],
|
||||||
|
jsonArray: importEntities.role_connections,
|
||||||
|
deleteRestrictionColumns: ['import_source_id'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'role_permissions',
|
||||||
|
findExisting: true,
|
||||||
|
createNew: true,
|
||||||
|
updateExisting: false,
|
||||||
|
deleteMissing: true,
|
||||||
|
matchColumns: ['role_id', 'permission', 'import_source_id'],
|
||||||
|
jsonArray: importEntities.role_permissions,
|
||||||
|
deleteRestrictionColumns: ['import_source_id'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'role_databases',
|
||||||
|
findExisting: true,
|
||||||
|
createNew: true,
|
||||||
|
updateExisting: true,
|
||||||
|
deleteMissing: true,
|
||||||
|
matchColumns: ['role_id', 'id_original', 'import_source_id'],
|
||||||
|
jsonArray: importEntities.role_databases,
|
||||||
|
deleteRestrictionColumns: ['import_source_id'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'role_tables',
|
||||||
|
findExisting: true,
|
||||||
|
createNew: true,
|
||||||
|
updateExisting: true,
|
||||||
|
deleteMissing: true,
|
||||||
|
matchColumns: ['role_id', 'id_original', 'import_source_id'],
|
||||||
|
jsonArray: importEntities.role_tables,
|
||||||
|
deleteRestrictionColumns: ['import_source_id'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
extractConnectionsFromEnv,
|
||||||
|
extractImportEntitiesFromEnv,
|
||||||
|
createStorageFromEnvReplicatorItems,
|
||||||
|
};
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
export let arg;
|
export let arg;
|
||||||
export let namePrefix;
|
export let namePrefix;
|
||||||
|
export let isReadOnly = false;
|
||||||
|
|
||||||
$: name = `${namePrefix}${arg.name}`;
|
$: name = `${namePrefix}${arg.name}`;
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@
|
|||||||
defaultValue={arg.default}
|
defaultValue={arg.default}
|
||||||
focused={arg.focused}
|
focused={arg.focused}
|
||||||
placeholder={arg.placeholder}
|
placeholder={arg.placeholder}
|
||||||
disabled={arg.disabledFn ? arg.disabledFn($values) : arg.disabled}
|
disabled={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||||
/>
|
/>
|
||||||
{:else if arg.type == 'stringlist'}
|
{:else if arg.type == 'stringlist'}
|
||||||
<FormStringList
|
<FormStringList
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
addButtonLabel={_tval(arg.addButtonLabel)}
|
addButtonLabel={_tval(arg.addButtonLabel)}
|
||||||
{name}
|
{name}
|
||||||
placeholder={arg.placeholder}
|
placeholder={arg.placeholder}
|
||||||
|
isReadOnly={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||||
/>
|
/>
|
||||||
{:else if arg.type == 'number'}
|
{:else if arg.type == 'number'}
|
||||||
<FormTextField
|
<FormTextField
|
||||||
@@ -41,14 +43,14 @@
|
|||||||
defaultValue={arg.default}
|
defaultValue={arg.default}
|
||||||
focused={arg.focused}
|
focused={arg.focused}
|
||||||
placeholder={arg.placeholder}
|
placeholder={arg.placeholder}
|
||||||
disabled={arg.disabledFn ? arg.disabledFn($values) : arg.disabled}
|
disabled={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||||
/>
|
/>
|
||||||
{:else if arg.type == 'checkbox'}
|
{:else if arg.type == 'checkbox'}
|
||||||
<FormCheckboxField
|
<FormCheckboxField
|
||||||
label={_tval(arg.label)}
|
label={_tval(arg.label)}
|
||||||
{name}
|
{name}
|
||||||
defaultValue={arg.default}
|
defaultValue={arg.default}
|
||||||
disabled={arg.disabledFn ? arg.disabledFn($values) : arg.disabled}
|
disabled={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||||
/>
|
/>
|
||||||
{:else if arg.type == 'select'}
|
{:else if arg.type == 'select'}
|
||||||
<FormSelectField
|
<FormSelectField
|
||||||
@@ -59,7 +61,7 @@
|
|||||||
options={arg.options.map(opt =>
|
options={arg.options.map(opt =>
|
||||||
_.isString(opt) ? { label: opt, value: opt } : { label: opt.name, value: opt.value }
|
_.isString(opt) ? { label: opt, value: opt } : { label: opt.name, value: opt.value }
|
||||||
)}
|
)}
|
||||||
disabled={arg.disabledFn ? arg.disabledFn($values) : arg.disabled}
|
disabled={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||||
/>
|
/>
|
||||||
{:else if arg.type == 'dropdowntext'}
|
{:else if arg.type == 'dropdowntext'}
|
||||||
<FormDropDownTextField
|
<FormDropDownTextField
|
||||||
@@ -72,6 +74,6 @@
|
|||||||
onClick: () => setFieldValue(name, _.isString(opt) ? opt : opt.value),
|
onClick: () => setFieldValue(name, _.isString(opt) ? opt : opt.value),
|
||||||
}));
|
}));
|
||||||
}}
|
}}
|
||||||
disabled={arg.disabledFn ? arg.disabledFn($values) : arg.disabled}
|
disabled={isReadOnly || (arg.disabledFn ? arg.disabledFn($values) : arg.disabled)}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
|
|
||||||
export let namePrefix = '';
|
export let namePrefix = '';
|
||||||
export let args: any[];
|
export let args: any[];
|
||||||
|
export let isReadOnly = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{#each args as arg (arg.name)}
|
{#each args as arg (arg.name)}
|
||||||
<FormArgument {arg} {namePrefix} />
|
<FormArgument {arg} {namePrefix} {isReadOnly} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
export let addButtonLabel;
|
export let addButtonLabel;
|
||||||
export let placeholder;
|
export let placeholder;
|
||||||
export let templateProps;
|
export let templateProps;
|
||||||
|
export let isReadOnly = false;
|
||||||
|
|
||||||
const { template, values, setFieldValue } = getFormContext();
|
const { template, values, setFieldValue } = getFormContext();
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@
|
|||||||
|
|
||||||
<svelte:component this={template} type="text" {label} {...templateProps}>
|
<svelte:component this={template} type="text" {label} {...templateProps}>
|
||||||
{#each stringList as value, index}
|
{#each stringList as value, index}
|
||||||
<div class='input-line-flex'>
|
<div class="input-line-flex">
|
||||||
<TextField
|
<TextField
|
||||||
{value}
|
{value}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
@@ -28,12 +29,14 @@
|
|||||||
const newValues = stringList.map((v, i) => (i === index ? e.target['value'] : v));
|
const newValues = stringList.map((v, i) => (i === index ? e.target['value'] : v));
|
||||||
setFieldValue(name, newValues);
|
setFieldValue(name, newValues);
|
||||||
}}
|
}}
|
||||||
|
disabled={isReadOnly}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<InlineButton
|
<InlineButton
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
setFieldValue(name, [...stringList.slice(0, index), ...stringList.slice(index + 1)]);
|
setFieldValue(name, [...stringList.slice(0, index), ...stringList.slice(index + 1)]);
|
||||||
}}
|
}}
|
||||||
|
disabled={isReadOnly}
|
||||||
>
|
>
|
||||||
<FontIcon icon="icon delete" />
|
<FontIcon icon="icon delete" />
|
||||||
</InlineButton>
|
</InlineButton>
|
||||||
@@ -45,6 +48,7 @@
|
|||||||
on:click={() => {
|
on:click={() => {
|
||||||
setFieldValue(name, [...stringList, '']);
|
setFieldValue(name, [...stringList, '']);
|
||||||
}}
|
}}
|
||||||
|
disabled={isReadOnly}
|
||||||
/>
|
/>
|
||||||
</svelte:component>
|
</svelte:component>
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
import FormArgumentList from '../forms/FormArgumentList.svelte';
|
import FormArgumentList from '../forms/FormArgumentList.svelte';
|
||||||
import { _t } from '../translations';
|
import { _t } from '../translations';
|
||||||
|
|
||||||
|
export let isFormReadOnly;
|
||||||
|
|
||||||
const { values } = getFormContext();
|
const { values } = getFormContext();
|
||||||
|
|
||||||
$: engine = $values.engine;
|
$: engine = $values.engine;
|
||||||
@@ -17,9 +19,18 @@
|
|||||||
$: advancedFields = driver?.getAdvancedConnectionFields ? driver?.getAdvancedConnectionFields() : null;
|
$: advancedFields = driver?.getAdvancedConnectionFields ? driver?.getAdvancedConnectionFields() : null;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FormTextAreaField label={_t('connection.allowedDatabases', { defaultMessage: 'Allowed databases, one per line' })} name="allowedDatabases" disabled={isConnected} rows={8} />
|
<FormTextAreaField
|
||||||
<FormTextField label={_t('connection.allowedDatabasesRegex', { defaultMessage: 'Allowed databases regular expression' })} name="allowedDatabasesRegex" disabled={isConnected} />
|
label={_t('connection.allowedDatabases', { defaultMessage: 'Allowed databases, one per line' })}
|
||||||
|
name="allowedDatabases"
|
||||||
|
disabled={isConnected || isFormReadOnly}
|
||||||
|
rows={8}
|
||||||
|
/>
|
||||||
|
<FormTextField
|
||||||
|
label={_t('connection.allowedDatabasesRegex', { defaultMessage: 'Allowed databases regular expression' })}
|
||||||
|
name="allowedDatabasesRegex"
|
||||||
|
disabled={isConnected || isFormReadOnly}
|
||||||
|
/>
|
||||||
|
|
||||||
{#if advancedFields}
|
{#if advancedFields}
|
||||||
<FormArgumentList args={advancedFields} />
|
<FormArgumentList args={advancedFields} isReadOnly={isFormReadOnly} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
export let getDatabaseList;
|
export let getDatabaseList;
|
||||||
export let currentConnection;
|
export let currentConnection;
|
||||||
|
export let isFormReadOnly;
|
||||||
|
|
||||||
const { values, setFieldValue } = getFormContext();
|
const { values, setFieldValue } = getFormContext();
|
||||||
const electron = getElectron();
|
const electron = getElectron();
|
||||||
@@ -90,10 +91,10 @@
|
|||||||
label={_t('connection.type', { defaultMessage: 'Connection type' })}
|
label={_t('connection.type', { defaultMessage: 'Connection type' })}
|
||||||
name="engine"
|
name="engine"
|
||||||
isNative
|
isNative
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
data-testid="ConnectionDriverFields_connectionType"
|
data-testid="ConnectionDriverFields_connectionType"
|
||||||
options={[
|
options={[
|
||||||
{ label: _t('connection.selectType', { defaultMessage: '(select connection type)' })},
|
{ label: _t('connection.selectType', { defaultMessage: '(select connection type)' }) },
|
||||||
..._.sortBy(
|
..._.sortBy(
|
||||||
$extensions.drivers
|
$extensions.drivers
|
||||||
// .filter(driver => !driver.isElectronOnly || electron)
|
// .filter(driver => !driver.isElectronOnly || electron)
|
||||||
@@ -113,7 +114,7 @@
|
|||||||
data-testid="ConnectionDriverFields_authType"
|
data-testid="ConnectionDriverFields_authType"
|
||||||
name="authType"
|
name="authType"
|
||||||
isNative
|
isNative
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
defaultValue={driver?.defaultAuthTypeName}
|
defaultValue={driver?.defaultAuthTypeName}
|
||||||
options={$authTypes.map(auth => ({
|
options={$authTypes.map(auth => ({
|
||||||
value: auth.name,
|
value: auth.name,
|
||||||
@@ -127,16 +128,18 @@
|
|||||||
<FormClusterNodesField
|
<FormClusterNodesField
|
||||||
label={_t('connection.clusterNodes', { defaultMessage: 'Cluster nodes' })}
|
label={_t('connection.clusterNodes', { defaultMessage: 'Cluster nodes' })}
|
||||||
name="clusterNodes"
|
name="clusterNodes"
|
||||||
disabled={isConnected || disabledFields.includes('clusterNodes')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('clusterNodes')}
|
||||||
data-testid="ConnectionDriverFields_clusterNodes"
|
data-testid="ConnectionDriverFields_clusterNodes"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if driver?.showConnectionField('autoDetectNatMap', $values, showConnectionFieldArgs)}
|
{#if driver?.showConnectionField('autoDetectNatMap', $values, showConnectionFieldArgs)}
|
||||||
<FormCheckboxField
|
<FormCheckboxField
|
||||||
label={_t('connection.autoDetectNatMap', { defaultMessage: 'Auto detect NAT map (use for Redis Cluster in Docker network)' })}
|
label={_t('connection.autoDetectNatMap', {
|
||||||
|
defaultMessage: 'Auto detect NAT map (use for Redis Cluster in Docker network)',
|
||||||
|
})}
|
||||||
name="autoDetectNatMap"
|
name="autoDetectNatMap"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
data-testid="ConnectionDriverFields_autoDetectNatMap"
|
data-testid="ConnectionDriverFields_autoDetectNatMap"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -146,13 +149,13 @@
|
|||||||
<FormElectronFileSelector
|
<FormElectronFileSelector
|
||||||
label={_t('connection.databaseFile', { defaultMessage: 'Database file' })}
|
label={_t('connection.databaseFile', { defaultMessage: 'Database file' })}
|
||||||
name="databaseFile"
|
name="databaseFile"
|
||||||
disabled={isConnected || disabledFields.includes('databaseFile')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('databaseFile')}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<FormTextField
|
<FormTextField
|
||||||
label={_t('connection.databaseFilePath', { defaultMessage: 'Database file (path on server)' })}
|
label={_t('connection.databaseFilePath', { defaultMessage: 'Database file (path on server)' })}
|
||||||
name="databaseFile"
|
name="databaseFile"
|
||||||
disabled={isConnected || disabledFields.includes('databaseFile')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('databaseFile')}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -160,11 +163,15 @@
|
|||||||
{#if driver?.showConnectionField('useDatabaseUrl', $values, showConnectionFieldArgs)}
|
{#if driver?.showConnectionField('useDatabaseUrl', $values, showConnectionFieldArgs)}
|
||||||
<div class="radio">
|
<div class="radio">
|
||||||
<FormRadioGroupField
|
<FormRadioGroupField
|
||||||
disabled={isConnected || disabledFields.includes('useDatabaseUrl')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('useDatabaseUrl')}
|
||||||
name="useDatabaseUrl"
|
name="useDatabaseUrl"
|
||||||
matchValueToOption={(value, option) => !!option.value == !!value}
|
matchValueToOption={(value, option) => !!option.value == !!value}
|
||||||
options={[
|
options={[
|
||||||
{ label: _t('connection.fillDetails', { defaultMessage: 'Fill database connection details' }), value: '', default: true },
|
{
|
||||||
|
label: _t('connection.fillDetails', { defaultMessage: 'Fill database connection details' }),
|
||||||
|
value: '',
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
{ label: _t('connection.useUrl', { defaultMessage: 'Use database URL' }), value: '1' },
|
{ label: _t('connection.useUrl', { defaultMessage: 'Use database URL' }), value: '1' },
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
@@ -177,7 +184,7 @@
|
|||||||
name="databaseUrl"
|
name="databaseUrl"
|
||||||
data-testid="ConnectionDriverFields_databaseUrl"
|
data-testid="ConnectionDriverFields_databaseUrl"
|
||||||
placeholder={driver?.databaseUrlPlaceholder}
|
placeholder={driver?.databaseUrlPlaceholder}
|
||||||
disabled={isConnected || disabledFields.includes('databaseUrl')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('databaseUrl')}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -187,7 +194,7 @@
|
|||||||
name="localDataCenter"
|
name="localDataCenter"
|
||||||
data-testid="ConnectionDriverFields_localDataCenter"
|
data-testid="ConnectionDriverFields_localDataCenter"
|
||||||
placeholder={driver?.defaultLocalDataCenter}
|
placeholder={driver?.defaultLocalDataCenter}
|
||||||
disabled={isConnected || disabledFields.includes('localDataCenter')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('localDataCenter')}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -196,7 +203,7 @@
|
|||||||
label={_t('connection.authToken', { defaultMessage: 'Auth token' })}
|
label={_t('connection.authToken', { defaultMessage: 'Auth token' })}
|
||||||
name="authToken"
|
name="authToken"
|
||||||
data-testid="ConnectionDriverFields_authToken"
|
data-testid="ConnectionDriverFields_authToken"
|
||||||
disabled={isConnected || disabledFields.includes('authToken')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('authToken')}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -207,7 +214,7 @@
|
|||||||
data-testid="ConnectionDriverFields_authType"
|
data-testid="ConnectionDriverFields_authType"
|
||||||
name="authType"
|
name="authType"
|
||||||
isNative
|
isNative
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
defaultValue={driver?.defaultAuthTypeName}
|
defaultValue={driver?.defaultAuthTypeName}
|
||||||
options={$authTypes.map(auth => ({
|
options={$authTypes.map(auth => ({
|
||||||
value: auth.name,
|
value: auth.name,
|
||||||
@@ -219,9 +226,9 @@
|
|||||||
|
|
||||||
{#if driver?.showConnectionField('endpoint', $values, showConnectionFieldArgs)}
|
{#if driver?.showConnectionField('endpoint', $values, showConnectionFieldArgs)}
|
||||||
<FormTextField
|
<FormTextField
|
||||||
label='Endpoint'
|
label="Endpoint"
|
||||||
name="endpoint"
|
name="endpoint"
|
||||||
disabled={isConnected || disabledFields.includes('endpoint')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('endpoint')}
|
||||||
data-testid="ConnectionDriverFields_endpoint"
|
data-testid="ConnectionDriverFields_endpoint"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -230,7 +237,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label={_t('connection.endpointKey', { defaultMessage: 'Key' })}
|
label={_t('connection.endpointKey', { defaultMessage: 'Key' })}
|
||||||
name="endpointKey"
|
name="endpointKey"
|
||||||
disabled={isConnected || disabledFields.includes('endpointKey')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('endpointKey')}
|
||||||
data-testid="ConnectionDriverFields_endpointKey"
|
data-testid="ConnectionDriverFields_endpointKey"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -239,7 +246,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label={_t('connection.clientLibraryPath', { defaultMessage: 'Client library path' })}
|
label={_t('connection.clientLibraryPath', { defaultMessage: 'Client library path' })}
|
||||||
name="clientLibraryPath"
|
name="clientLibraryPath"
|
||||||
disabled={isConnected || disabledFields.includes('clientLibraryPath')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('clientLibraryPath')}
|
||||||
data-testid="ConnectionDriverFields_clientLibraryPath"
|
data-testid="ConnectionDriverFields_clientLibraryPath"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -250,7 +257,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label={_t('connection.server', { defaultMessage: 'Server' })}
|
label={_t('connection.server', { defaultMessage: 'Server' })}
|
||||||
name="server"
|
name="server"
|
||||||
disabled={isConnected || disabledFields.includes('server')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('server')}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
data-testid="ConnectionDriverFields_server"
|
data-testid="ConnectionDriverFields_server"
|
||||||
/>
|
/>
|
||||||
@@ -260,7 +267,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label="Port"
|
label="Port"
|
||||||
name="port"
|
name="port"
|
||||||
disabled={isConnected || disabledFields.includes('port')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('port')}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
placeholder={driver?.defaultPort}
|
placeholder={driver?.defaultPort}
|
||||||
data-testid="ConnectionDriverFields_port"
|
data-testid="ConnectionDriverFields_port"
|
||||||
@@ -271,7 +278,9 @@
|
|||||||
{#if getCurrentConfig().isDocker}
|
{#if getCurrentConfig().isDocker}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<FontIcon icon="img warn" padRight />
|
<FontIcon icon="img warn" padRight />
|
||||||
{ _t('connection.dockerWarning', { defaultMessage: 'Under docker, localhost and 127.0.0.1 will not work, use dockerhost instead' }) }
|
{_t('connection.dockerWarning', {
|
||||||
|
defaultMessage: 'Under docker, localhost and 127.0.0.1 will not work, use dockerhost instead',
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -280,9 +289,11 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-9 mr-1">
|
<div class="col-9 mr-1">
|
||||||
<FormTextField
|
<FormTextField
|
||||||
label={$values.serviceNameType == 'sid' ? 'SID' : _t('connection.serviceName', { defaultMessage: 'Service name' })}
|
label={$values.serviceNameType == 'sid'
|
||||||
|
? 'SID'
|
||||||
|
: _t('connection.serviceName', { defaultMessage: 'Service name' })}
|
||||||
name="serviceName"
|
name="serviceName"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
data-testid="ConnectionDriverFields_serviceName"
|
data-testid="ConnectionDriverFields_serviceName"
|
||||||
/>
|
/>
|
||||||
@@ -293,7 +304,7 @@
|
|||||||
isNative
|
isNative
|
||||||
name="serviceNameType"
|
name="serviceNameType"
|
||||||
defaultValue="serviceName"
|
defaultValue="serviceName"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
options={[
|
options={[
|
||||||
{ value: 'serviceName', label: _t('connection.serviceName', { defaultMessage: 'Service name' }) },
|
{ value: 'serviceName', label: _t('connection.serviceName', { defaultMessage: 'Service name' }) },
|
||||||
@@ -309,7 +320,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label={_t('connection.socketPath', { defaultMessage: 'Socket path' })}
|
label={_t('connection.socketPath', { defaultMessage: 'Socket path' })}
|
||||||
name="socketPath"
|
name="socketPath"
|
||||||
disabled={isConnected || disabledFields.includes('socketPath')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('socketPath')}
|
||||||
placeholder={driver?.defaultSocketPath}
|
placeholder={driver?.defaultSocketPath}
|
||||||
data-testid="ConnectionDriverFields_scoketPath"
|
data-testid="ConnectionDriverFields_scoketPath"
|
||||||
/>
|
/>
|
||||||
@@ -322,7 +333,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label={_t('connection.user', { defaultMessage: 'User' })}
|
label={_t('connection.user', { defaultMessage: 'User' })}
|
||||||
name="user"
|
name="user"
|
||||||
disabled={isConnected || disabledFields.includes('user')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('user')}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
data-testid="ConnectionDriverFields_user"
|
data-testid="ConnectionDriverFields_user"
|
||||||
/>
|
/>
|
||||||
@@ -333,7 +344,7 @@
|
|||||||
<FormPasswordField
|
<FormPasswordField
|
||||||
label={_t('connection.password', { defaultMessage: 'Password' })}
|
label={_t('connection.password', { defaultMessage: 'Password' })}
|
||||||
name="password"
|
name="password"
|
||||||
disabled={isConnected || disabledFields.includes('password')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('password')}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
data-testid="ConnectionDriverFields_password"
|
data-testid="ConnectionDriverFields_password"
|
||||||
/>
|
/>
|
||||||
@@ -345,7 +356,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label={_t('connection.user', { defaultMessage: 'User' })}
|
label={_t('connection.user', { defaultMessage: 'User' })}
|
||||||
name="user"
|
name="user"
|
||||||
disabled={isConnected || disabledFields.includes('user')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('user')}
|
||||||
data-testid="ConnectionDriverFields_user"
|
data-testid="ConnectionDriverFields_user"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -353,7 +364,7 @@
|
|||||||
<FormPasswordField
|
<FormPasswordField
|
||||||
label={_t('connection.password', { defaultMessage: 'Password' })}
|
label={_t('connection.password', { defaultMessage: 'Password' })}
|
||||||
name="password"
|
name="password"
|
||||||
disabled={isConnected || disabledFields.includes('password')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('password')}
|
||||||
data-testid="ConnectionDriverFields_password"
|
data-testid="ConnectionDriverFields_password"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -380,7 +391,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label={_t('connection.accessKeyId', { defaultMessage: 'Access Key ID' })}
|
label={_t('connection.accessKeyId', { defaultMessage: 'Access Key ID' })}
|
||||||
name="accessKeyId"
|
name="accessKeyId"
|
||||||
disabled={isConnected || disabledFields.includes('accessKeyId')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('accessKeyId')}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
data-testid="ConnectionDriverFields_accesKeyId"
|
data-testid="ConnectionDriverFields_accesKeyId"
|
||||||
/>
|
/>
|
||||||
@@ -391,7 +402,7 @@
|
|||||||
<FormPasswordField
|
<FormPasswordField
|
||||||
label={_t('connection.secretAccessKey', { defaultMessage: 'Secret access key' })}
|
label={_t('connection.secretAccessKey', { defaultMessage: 'Secret access key' })}
|
||||||
name="secretAccessKey"
|
name="secretAccessKey"
|
||||||
disabled={isConnected || disabledFields.includes('secretAccessKey')}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('secretAccessKey')}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
data-testid="ConnectionDriverFields_secretAccessKey"
|
data-testid="ConnectionDriverFields_secretAccessKey"
|
||||||
/>
|
/>
|
||||||
@@ -405,12 +416,15 @@
|
|||||||
isNative
|
isNative
|
||||||
name="passwordMode"
|
name="passwordMode"
|
||||||
defaultValue="saveEncrypted"
|
defaultValue="saveEncrypted"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
options={[
|
options={[
|
||||||
{ value: 'saveEncrypted', label: _t('connection.saveEncrypted', { defaultMessage: 'Save and encrypt' }) },
|
{ value: 'saveEncrypted', label: _t('connection.saveEncrypted', { defaultMessage: 'Save and encrypt' }) },
|
||||||
{ value: 'saveRaw', label: _t('connection.saveRaw', { defaultMessage: 'Save raw (UNSAFE!!)' }) },
|
{ value: 'saveRaw', label: _t('connection.saveRaw', { defaultMessage: 'Save raw (UNSAFE!!)' }) },
|
||||||
{ value: 'askPassword', label: _t('connection.askPassword', { defaultMessage: "Don't save, ask for password" }) },
|
{ value: 'askPassword', label: _t('connection.askPassword', { defaultMessage: "Don't save, ask for password" }) },
|
||||||
{ value: 'askUser', label: _t('connection.askUser', { defaultMessage: "Don't save, ask for login and password" }) },
|
{
|
||||||
|
value: 'askUser',
|
||||||
|
label: _t('connection.askUser', { defaultMessage: "Don't save, ask for login and password" }),
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
data-testid="ConnectionDriverFields_passwordMode"
|
data-testid="ConnectionDriverFields_passwordMode"
|
||||||
/>
|
/>
|
||||||
@@ -420,7 +434,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label={_t('connection.keySeparator', { defaultMessage: 'Key separator' })}
|
label={_t('connection.keySeparator', { defaultMessage: 'Key separator' })}
|
||||||
name="treeKeySeparator"
|
name="treeKeySeparator"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
placeholder=":"
|
placeholder=":"
|
||||||
data-testid="ConnectionDriverFields_treeKeySeparator"
|
data-testid="ConnectionDriverFields_treeKeySeparator"
|
||||||
/>
|
/>
|
||||||
@@ -430,7 +444,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label={_t('connection.windowsDomain', { defaultMessage: 'Domain (specify to use NTLM authentication)' })}
|
label={_t('connection.windowsDomain', { defaultMessage: 'Domain (specify to use NTLM authentication)' })}
|
||||||
name="windowsDomain"
|
name="windowsDomain"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
data-testid="ConnectionDriverFields_windowsDomain"
|
data-testid="ConnectionDriverFields_windowsDomain"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -439,7 +453,7 @@
|
|||||||
<FormCheckboxField
|
<FormCheckboxField
|
||||||
label={_t('connection.isReadOnly', { defaultMessage: 'Is read only' })}
|
label={_t('connection.isReadOnly', { defaultMessage: 'Is read only' })}
|
||||||
name="isReadOnly"
|
name="isReadOnly"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
data-testid="ConnectionDriverFields_isReadOnly"
|
data-testid="ConnectionDriverFields_isReadOnly"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -448,7 +462,7 @@
|
|||||||
<FormCheckboxField
|
<FormCheckboxField
|
||||||
label={_t('connection.trustServerCertificate', { defaultMessage: 'Trust server certificate' })}
|
label={_t('connection.trustServerCertificate', { defaultMessage: 'Trust server certificate' })}
|
||||||
name="trustServerCertificate"
|
name="trustServerCertificate"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
data-testid="ConnectionDriverFields_trustServerCertificate"
|
data-testid="ConnectionDriverFields_trustServerCertificate"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -457,33 +471,42 @@
|
|||||||
<FormDropDownTextField
|
<FormDropDownTextField
|
||||||
label={_t('connection.defaultDatabase', { defaultMessage: 'Default database' })}
|
label={_t('connection.defaultDatabase', { defaultMessage: 'Default database' })}
|
||||||
name="defaultDatabase"
|
name="defaultDatabase"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly || disabledFields.includes('defaultDatabase')}
|
||||||
data-testid="ConnectionDriverFields_defaultDatabase"
|
data-testid="ConnectionDriverFields_defaultDatabase"
|
||||||
asyncMenu={createDatabasesMenu}
|
asyncMenu={createDatabasesMenu}
|
||||||
placeholder={_t('common.notSelectedOptional', { defaultMessage : "(not selected - optional)"})}
|
placeholder={_t('common.notSelectedOptional', { defaultMessage: '(not selected - optional)' })}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if defaultDatabase && driver?.showConnectionField('singleDatabase', $values, showConnectionFieldArgs)}
|
{#if defaultDatabase && driver?.showConnectionField('singleDatabase', $values, showConnectionFieldArgs)}
|
||||||
<FormCheckboxField
|
<FormCheckboxField
|
||||||
label={_t('connection.singleDatabase', { defaultMessage: 'Use only database {defaultDatabase}', values: { defaultDatabase } })}
|
label={_t('connection.singleDatabase', {
|
||||||
|
defaultMessage: 'Use only database {defaultDatabase}',
|
||||||
|
values: { defaultDatabase },
|
||||||
|
})}
|
||||||
name="singleDatabase"
|
name="singleDatabase"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
data-testid="ConnectionDriverFields_singleDatabase"
|
data-testid="ConnectionDriverFields_singleDatabase"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if driver?.showConnectionField('useSeparateSchemas', $values, showConnectionFieldArgs)}
|
{#if driver?.showConnectionField('useSeparateSchemas', $values, showConnectionFieldArgs)}
|
||||||
<FormCheckboxField
|
<FormCheckboxField
|
||||||
label={_t('connection.useSeparateSchemas', { defaultMessage: 'Use schemas separately (use this if you have many large schemas)' })}
|
label={_t('connection.useSeparateSchemas', {
|
||||||
|
defaultMessage: 'Use schemas separately (use this if you have many large schemas)',
|
||||||
|
})}
|
||||||
name="useSeparateSchemas"
|
name="useSeparateSchemas"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
data-testid="ConnectionDriverFields_useSeparateSchemas"
|
data-testid="ConnectionDriverFields_useSeparateSchemas"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if driver?.showConnectionField('connectionDefinition', $values, showConnectionFieldArgs)}
|
{#if driver?.showConnectionField('connectionDefinition', $values, showConnectionFieldArgs)}
|
||||||
<FormFileInputField disabled={isConnected} label={_t('connection.connectionDefinition', { defaultMessage: 'Service account key JSON' })} name="connectionDefinition" />
|
<FormFileInputField
|
||||||
|
disabled={isConnected || isFormReadOnly}
|
||||||
|
label={_t('connection.connectionDefinition', { defaultMessage: 'Service account key JSON' })}
|
||||||
|
name="connectionDefinition"
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if driver}
|
{#if driver}
|
||||||
@@ -493,7 +516,7 @@
|
|||||||
label={_t('connection.displayName', { defaultMessage: 'Display name' })}
|
label={_t('connection.displayName', { defaultMessage: 'Display name' })}
|
||||||
name="displayName"
|
name="displayName"
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
data-testid="ConnectionDriverFields_displayName"
|
data-testid="ConnectionDriverFields_displayName"
|
||||||
placeholder={getConnectionLabel(currentConnection)}
|
placeholder={getConnectionLabel(currentConnection)}
|
||||||
/>
|
/>
|
||||||
@@ -505,7 +528,7 @@
|
|||||||
name="connectionColor"
|
name="connectionColor"
|
||||||
emptyLabel="(not selected)"
|
emptyLabel="(not selected)"
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
data-testid="ConnectionDriverFields_connectionColor"
|
data-testid="ConnectionDriverFields_connectionColor"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
import { extensions, openedConnections, openedSingleDatabaseConnections } from '../stores';
|
import { extensions, openedConnections, openedSingleDatabaseConnections } from '../stores';
|
||||||
import { _t } from '../translations';
|
import { _t } from '../translations';
|
||||||
|
|
||||||
|
export let isFormReadOnly;
|
||||||
|
|
||||||
const { values, setFieldValue } = getFormContext();
|
const { values, setFieldValue } = getFormContext();
|
||||||
const electron = getElectron();
|
const electron = getElectron();
|
||||||
|
|
||||||
@@ -30,9 +32,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FormCheckboxField
|
<FormCheckboxField
|
||||||
label={_t('connection.sshTunnel.use', {defaultMessage: "Use SSH tunnel"})}
|
label={_t('connection.sshTunnel.use', { defaultMessage: 'Use SSH tunnel' })}
|
||||||
name="useSshTunnel"
|
name="useSshTunnel"
|
||||||
disabled={isConnected}
|
disabled={isConnected || isFormReadOnly}
|
||||||
data-testid="ConnectionSshTunnelFields_useSshTunnel"
|
data-testid="ConnectionSshTunnelFields_useSshTunnel"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label="Host"
|
label="Host"
|
||||||
name="sshHost"
|
name="sshHost"
|
||||||
disabled={isConnected || !useSshTunnel}
|
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
data-testid="ConnectionSshTunnelFields_sshHost"
|
data-testid="ConnectionSshTunnelFields_sshHost"
|
||||||
/>
|
/>
|
||||||
@@ -50,23 +52,30 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label="Port"
|
label="Port"
|
||||||
name="sshPort"
|
name="sshPort"
|
||||||
disabled={isConnected || !useSshTunnel}
|
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
placeholder="22"
|
placeholder="22"
|
||||||
data-testid="ConnectionSshTunnelFields_sshPort"
|
data-testid="ConnectionSshTunnelFields_sshPort"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<FormTextField label="Bastion host (Jump host)" name="sshBastionHost" disabled={isConnected || !useSshTunnel} />
|
<FormTextField
|
||||||
|
label="Bastion host (Jump host)"
|
||||||
|
name="sshBastionHost"
|
||||||
|
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||||
|
/>
|
||||||
|
|
||||||
<FormSelectField
|
<FormSelectField
|
||||||
label={_t('connection.sshTunnel.authentication', {defaultMessage: "SSH Authentication"})}
|
label={_t('connection.sshTunnel.authentication', { defaultMessage: 'SSH Authentication' })}
|
||||||
name="sshMode"
|
name="sshMode"
|
||||||
isNative
|
isNative
|
||||||
defaultSelectValue="userPassword"
|
defaultSelectValue="userPassword"
|
||||||
disabled={isConnected || !useSshTunnel}
|
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||||
options={[
|
options={[
|
||||||
{ value: 'userPassword', label: _t('connection.sshTunnel.authMethod.userPassword', {defaultMessage: "Username & password"}) },
|
{
|
||||||
|
value: 'userPassword',
|
||||||
|
label: _t('connection.sshTunnel.authMethod.userPassword', { defaultMessage: 'Username & password' }),
|
||||||
|
},
|
||||||
{ value: 'agent', label: 'SSH agent' },
|
{ value: 'agent', label: 'SSH agent' },
|
||||||
{ value: 'keyFile', label: 'Key file' },
|
{ value: 'keyFile', label: 'Key file' },
|
||||||
]}
|
]}
|
||||||
@@ -77,7 +86,7 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label="Login"
|
label="Login"
|
||||||
name="sshLogin"
|
name="sshLogin"
|
||||||
disabled={isConnected || !useSshTunnel}
|
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||||
data-testid="ConnectionSshTunnelFields_sshLogin"
|
data-testid="ConnectionSshTunnelFields_sshLogin"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -88,16 +97,16 @@
|
|||||||
<FormTextField
|
<FormTextField
|
||||||
label="Login"
|
label="Login"
|
||||||
name="sshLogin"
|
name="sshLogin"
|
||||||
disabled={isConnected || !useSshTunnel}
|
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
data-testid="ConnectionSshTunnelFields_sshLogin"
|
data-testid="ConnectionSshTunnelFields_sshLogin"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<FormPasswordField
|
<FormPasswordField
|
||||||
label={_t('connection.password', {defaultMessage: 'Password'})}
|
label={_t('connection.password', { defaultMessage: 'Password' })}
|
||||||
name="sshPassword"
|
name="sshPassword"
|
||||||
disabled={isConnected || !useSshTunnel}
|
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
data-testid="ConnectionSshTunnelFields_sshPassword"
|
data-testid="ConnectionSshTunnelFields_sshPassword"
|
||||||
/>
|
/>
|
||||||
@@ -110,18 +119,18 @@
|
|||||||
<div class="col-6 mr-1">
|
<div class="col-6 mr-1">
|
||||||
{#if electron}
|
{#if electron}
|
||||||
<FormElectronFileSelector
|
<FormElectronFileSelector
|
||||||
label={_t('connection.sshTunnel.privateKeyFile', {defaultMessage: "Private key file"})}
|
label={_t('connection.sshTunnel.privateKeyFile', { defaultMessage: 'Private key file' })}
|
||||||
name="sshKeyfile"
|
name="sshKeyfile"
|
||||||
disabled={isConnected || !useSshTunnel}
|
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
defaultFileName={$platformInfo?.defaultKeyfile}
|
defaultFileName={$platformInfo?.defaultKeyfile}
|
||||||
data-testid="ConnectionSshTunnelFields_sshKeyfile"
|
data-testid="ConnectionSshTunnelFields_sshKeyfile"
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<FormTextField
|
<FormTextField
|
||||||
label={_t('connection.sshTunnel.privateKeyFilePath', {defaultMessage: "Private key file (path on server)"})}
|
label={_t('connection.sshTunnel.privateKeyFilePath', { defaultMessage: 'Private key file (path on server)' })}
|
||||||
name="sshKeyfile"
|
name="sshKeyfile"
|
||||||
disabled={isConnected || !useSshTunnel}
|
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
placeholder={$platformInfo?.defaultKeyfile}
|
placeholder={$platformInfo?.defaultKeyfile}
|
||||||
data-testid="ConnectionSshTunnelFields_sshKeyfile"
|
data-testid="ConnectionSshTunnelFields_sshKeyfile"
|
||||||
@@ -130,9 +139,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<FormPasswordField
|
<FormPasswordField
|
||||||
label={_t('connection.sshTunnel.keyFilePassphrase', {defaultMessage: "Key file passphrase"})}
|
label={_t('connection.sshTunnel.keyFilePassphrase', { defaultMessage: 'Key file passphrase' })}
|
||||||
name="sshKeyfilePassword"
|
name="sshKeyfilePassword"
|
||||||
disabled={isConnected || !useSshTunnel}
|
disabled={isConnected || !useSshTunnel || isFormReadOnly}
|
||||||
templateProps={{ noMargin: true }}
|
templateProps={{ noMargin: true }}
|
||||||
data-testid="ConnectionSshTunnelFields_sshKeyfilePassword"
|
data-testid="ConnectionSshTunnelFields_sshKeyfilePassword"
|
||||||
/>
|
/>
|
||||||
@@ -143,9 +152,10 @@
|
|||||||
{#if useSshTunnel && $values.sshMode == 'agent'}
|
{#if useSshTunnel && $values.sshMode == 'agent'}
|
||||||
<div class="ml-3 mb-3">
|
<div class="ml-3 mb-3">
|
||||||
{#if $platformInfo && $platformInfo.sshAuthSock}
|
{#if $platformInfo && $platformInfo.sshAuthSock}
|
||||||
<FontIcon icon="img ok" /> {_t('connection.sshTunnel.agentFound', {defaultMessage: "SSH Agent found"})}
|
<FontIcon icon="img ok" /> {_t('connection.sshTunnel.agentFound', { defaultMessage: 'SSH Agent found' })}
|
||||||
{:else}
|
{:else}
|
||||||
<FontIcon icon="img error" /> {_t('connection.sshTunnel.agentNotFound', {defaultMessage: "SSH Agent not found"})}
|
<FontIcon icon="img error" />
|
||||||
|
{_t('connection.sshTunnel.agentNotFound', { defaultMessage: 'SSH Agent not found' })}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
import { openedConnections, openedSingleDatabaseConnections } from '../stores';
|
import { openedConnections, openedSingleDatabaseConnections } from '../stores';
|
||||||
import { _t } from '../translations';
|
import { _t } from '../translations';
|
||||||
|
|
||||||
|
export let isFormReadOnly;
|
||||||
|
|
||||||
const { values, setFieldValue } = getFormContext();
|
const { values, setFieldValue } = getFormContext();
|
||||||
const electron = getElectron();
|
const electron = getElectron();
|
||||||
|
|
||||||
@@ -16,21 +18,35 @@
|
|||||||
$: isConnected = $openedConnections.includes($values._id) || $openedSingleDatabaseConnections.includes($values._id);
|
$: isConnected = $openedConnections.includes($values._id) || $openedSingleDatabaseConnections.includes($values._id);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FormCheckboxField label={_t('connection.ssl.use', {defaultMessage: "Use SSL"})} name="useSsl" disabled={isConnected} />
|
<FormCheckboxField
|
||||||
<FormElectronFileSelector label={_t('connection.ssl.caCert', {defaultMessage: "CA Cert (optional)"})} name="sslCaFile" disabled={isConnected || !useSsl || !electron} />
|
label={_t('connection.ssl.use', { defaultMessage: 'Use SSL' })}
|
||||||
|
name="useSsl"
|
||||||
|
disabled={isConnected || isFormReadOnly}
|
||||||
|
/>
|
||||||
<FormElectronFileSelector
|
<FormElectronFileSelector
|
||||||
label={_t('connection.ssl.certificate', {defaultMessage: "Certificate (optional)"})}
|
label={_t('connection.ssl.caCert', { defaultMessage: 'CA Cert (optional)' })}
|
||||||
|
name="sslCaFile"
|
||||||
|
disabled={isConnected || !useSsl || !electron || isFormReadOnly}
|
||||||
|
/>
|
||||||
|
<FormElectronFileSelector
|
||||||
|
label={_t('connection.ssl.certificate', { defaultMessage: 'Certificate (optional)' })}
|
||||||
name="sslCertFile"
|
name="sslCertFile"
|
||||||
disabled={isConnected || !useSsl || !electron}
|
disabled={isConnected || !useSsl || !electron || isFormReadOnly}
|
||||||
/>
|
/>
|
||||||
<FormPasswordField
|
<FormPasswordField
|
||||||
label={_t('connection.ssl.certificateKeyFilePassword', {defaultMessage: "Certificate key file password (optional)"})}
|
label={_t('connection.ssl.certificateKeyFilePassword', {
|
||||||
|
defaultMessage: 'Certificate key file password (optional)',
|
||||||
|
})}
|
||||||
name="sslCertFilePassword"
|
name="sslCertFilePassword"
|
||||||
disabled={isConnected || !useSsl || !electron}
|
disabled={isConnected || !useSsl || !electron || isFormReadOnly}
|
||||||
/>
|
/>
|
||||||
<FormElectronFileSelector
|
<FormElectronFileSelector
|
||||||
label={_t('connection.ssl.keyFile', {defaultMessage: "Key file (optional)"})}
|
label={_t('connection.ssl.keyFile', { defaultMessage: 'Key file (optional)' })}
|
||||||
name="sslKeyFile"
|
name="sslKeyFile"
|
||||||
disabled={isConnected || !useSsl || !electron}
|
disabled={isConnected || !useSsl || !electron || isFormReadOnly}
|
||||||
|
/>
|
||||||
|
<FormCheckboxField
|
||||||
|
label={_t('connection.ssl.rejectUnauthorized', { defaultMessage: 'Reject unauthorized' })}
|
||||||
|
name="sslRejectUnauthorized"
|
||||||
|
disabled={isConnected || !useSsl || isFormReadOnly}
|
||||||
/>
|
/>
|
||||||
<FormCheckboxField label={_t('connection.ssl.rejectUnauthorized', {defaultMessage: "Reject unauthorized"})} name="sslRejectUnauthorized" disabled={isConnected || !useSsl} />
|
|
||||||
|
|||||||
@@ -59,6 +59,8 @@
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$: isFormReadOnly = !!$values.import_source_id;
|
||||||
|
|
||||||
// $: console.log('ConnectionTab.$values', $values);
|
// $: console.log('ConnectionTab.$values', $values);
|
||||||
// $: console.log('ConnectionTab.driver', driver);
|
// $: console.log('ConnectionTab.driver', driver);
|
||||||
|
|
||||||
@@ -302,22 +304,25 @@
|
|||||||
{
|
{
|
||||||
label: _t('common.general', { defaultMessage: 'General' }),
|
label: _t('common.general', { defaultMessage: 'General' }),
|
||||||
component: ConnectionDriverFields,
|
component: ConnectionDriverFields,
|
||||||
props: { getDatabaseList, currentConnection },
|
props: { getDatabaseList, currentConnection, isFormReadOnly },
|
||||||
testid: 'ConnectionTab_tabGeneral',
|
testid: 'ConnectionTab_tabGeneral',
|
||||||
},
|
},
|
||||||
driver?.showConnectionTab('sshTunnel', $values) && {
|
driver?.showConnectionTab('sshTunnel', $values) && {
|
||||||
label: 'SSH Tunnel',
|
label: 'SSH Tunnel',
|
||||||
component: ConnectionSshTunnelFields,
|
component: ConnectionSshTunnelFields,
|
||||||
|
props: { isFormReadOnly },
|
||||||
testid: 'ConnectionTab_tabSshTunnel',
|
testid: 'ConnectionTab_tabSshTunnel',
|
||||||
},
|
},
|
||||||
driver?.showConnectionTab('ssl', $values) && {
|
driver?.showConnectionTab('ssl', $values) && {
|
||||||
label: 'SSL',
|
label: 'SSL',
|
||||||
component: ConnectionSslFields,
|
component: ConnectionSslFields,
|
||||||
|
props: { isFormReadOnly },
|
||||||
testid: 'ConnectionTab_tabSsl',
|
testid: 'ConnectionTab_tabSsl',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: _t('common.advanced', { defaultMessage: 'Advanced' }),
|
label: _t('common.advanced', { defaultMessage: 'Advanced' }),
|
||||||
component: ConnectionAdvancedDriverFields,
|
component: ConnectionAdvancedDriverFields,
|
||||||
|
props: { isFormReadOnly },
|
||||||
testid: 'ConnectionTab_tabAdvanced',
|
testid: 'ConnectionTab_tabAdvanced',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
@@ -383,7 +388,8 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{#if isTesting}
|
{#if isTesting}
|
||||||
<div>
|
<div>
|
||||||
<FontIcon icon="icon loading" /> {_t('common.testingConnection', { defaultMessage: 'Testing connection' })}
|
<FontIcon icon="icon loading" />
|
||||||
|
{_t('common.testingConnection', { defaultMessage: 'Testing connection' })}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ export function __t(key: string, options: TranslateOptions): DefferedTranslation
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function _tval(x: string | DefferedTranslationResult): string {
|
export function _tval(x: any | DefferedTranslationResult): string {
|
||||||
if (typeof x === 'string') return x;
|
if (typeof x === 'string') return x;
|
||||||
if (typeof x?._transKey === 'string') {
|
if (typeof x?._transKey === 'string') {
|
||||||
return _t(x._transKey, x._transOptions);
|
return _t(x._transKey, x._transOptions);
|
||||||
@@ -132,7 +132,7 @@ export function _tval(x: string | DefferedTranslationResult): string {
|
|||||||
if (typeof x?._transCallback === 'function') {
|
if (typeof x?._transCallback === 'function') {
|
||||||
return x._transCallback();
|
return x._transCallback();
|
||||||
}
|
}
|
||||||
return '';
|
return x?.toString() || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isDefferedTranslationResult(x: string | DefferedTranslationResult): x is DefferedTranslationResult {
|
export function isDefferedTranslationResult(x: string | DefferedTranslationResult): x is DefferedTranslationResult {
|
||||||
|
|||||||
Reference in New Issue
Block a user