dbgate-api 6.7.3 → 6.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -5
- package/src/controllers/connections.js +11 -49
- package/src/currentVersion.js +2 -2
- package/src/shell/copyStream.js +2 -2
- package/src/shell/dataReplicator.js +1 -0
- package/src/storageModel.js +171 -2
- package/src/utility/envtools.js +445 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dbgate-api",
|
|
3
3
|
"main": "src/index.js",
|
|
4
|
-
"version": "6.
|
|
4
|
+
"version": "6.8.0",
|
|
5
5
|
"homepage": "https://dbgate.org/",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"compare-versions": "^3.6.0",
|
|
31
31
|
"cors": "^2.8.5",
|
|
32
32
|
"cross-env": "^6.0.3",
|
|
33
|
-
"dbgate-datalib": "^6.
|
|
33
|
+
"dbgate-datalib": "^6.8.0",
|
|
34
34
|
"dbgate-query-splitter": "^4.11.9",
|
|
35
|
-
"dbgate-sqltree": "^6.
|
|
36
|
-
"dbgate-tools": "^6.
|
|
35
|
+
"dbgate-sqltree": "^6.8.0",
|
|
36
|
+
"dbgate-tools": "^6.8.0",
|
|
37
37
|
"debug": "^4.3.4",
|
|
38
38
|
"diff": "^5.0.0",
|
|
39
39
|
"diff2html": "^3.4.13",
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
"start:dblogin": "env-cmd -f env/dblogin/.env node src/index.js --listen-api",
|
|
76
76
|
"start:filedb": "env-cmd node src/index.js /home/jena/test/chinook/Chinook.db --listen-api",
|
|
77
77
|
"start:storage": "env-cmd -f env/storage/.env node src/index.js --listen-api",
|
|
78
|
+
"start:sfill": "env-cmd -f env/sfill/.env node src/index.js --listen-api",
|
|
78
79
|
"start:storage:built": "env-cmd -f env/storage/.env cross-env DEVMODE= BUILTWEBMODE=1 node dist/bundle.js --listen-api",
|
|
79
80
|
"start:singleconn": "env-cmd node src/index.js --server localhost --user root --port 3307 --engine mysql@dbgate-plugin-mysql --password test --listen-api",
|
|
80
81
|
"start:azure": "env-cmd -f env/azure/.env node src/index.js --listen-api",
|
|
@@ -86,7 +87,7 @@
|
|
|
86
87
|
"devDependencies": {
|
|
87
88
|
"@types/fs-extra": "^9.0.11",
|
|
88
89
|
"@types/lodash": "^4.14.149",
|
|
89
|
-
"dbgate-types": "^6.
|
|
90
|
+
"dbgate-types": "^6.8.0",
|
|
90
91
|
"env-cmd": "^10.1.0",
|
|
91
92
|
"jsdoc-to-markdown": "^9.0.5",
|
|
92
93
|
"node-loader": "^1.0.2",
|
|
@@ -23,6 +23,7 @@ const pipeForkLogs = require('../utility/pipeForkLogs');
|
|
|
23
23
|
const requireEngineDriver = require('../utility/requireEngineDriver');
|
|
24
24
|
const { getAuthProviderById } = require('../auth/authProvider');
|
|
25
25
|
const { startTokenChecking } = require('../utility/authProxy');
|
|
26
|
+
const { extractConnectionsFromEnv } = require('../utility/envtools');
|
|
26
27
|
|
|
27
28
|
const logger = getLogger('connections');
|
|
28
29
|
|
|
@@ -61,55 +62,7 @@ function getDatabaseFileLabel(databaseFile) {
|
|
|
61
62
|
|
|
62
63
|
function getPortalCollections() {
|
|
63
64
|
if (process.env.CONNECTIONS) {
|
|
64
|
-
const connections =
|
|
65
|
-
_id: id,
|
|
66
|
-
engine: process.env[`ENGINE_${id}`],
|
|
67
|
-
server: process.env[`SERVER_${id}`],
|
|
68
|
-
user: process.env[`USER_${id}`],
|
|
69
|
-
password: process.env[`PASSWORD_${id}`],
|
|
70
|
-
passwordMode: process.env[`PASSWORD_MODE_${id}`],
|
|
71
|
-
port: process.env[`PORT_${id}`],
|
|
72
|
-
databaseUrl: process.env[`URL_${id}`],
|
|
73
|
-
useDatabaseUrl: !!process.env[`URL_${id}`],
|
|
74
|
-
databaseFile: process.env[`FILE_${id}`]?.replace(
|
|
75
|
-
'%%E2E_TEST_DATA_DIRECTORY%%',
|
|
76
|
-
path.join(path.dirname(path.dirname(__dirname)), 'e2e-tests', 'tmpdata')
|
|
77
|
-
),
|
|
78
|
-
socketPath: process.env[`SOCKET_PATH_${id}`],
|
|
79
|
-
serviceName: process.env[`SERVICE_NAME_${id}`],
|
|
80
|
-
authType: process.env[`AUTH_TYPE_${id}`] || (process.env[`SOCKET_PATH_${id}`] ? 'socket' : undefined),
|
|
81
|
-
defaultDatabase:
|
|
82
|
-
process.env[`DATABASE_${id}`] ||
|
|
83
|
-
(process.env[`FILE_${id}`] ? getDatabaseFileLabel(process.env[`FILE_${id}`]) : null),
|
|
84
|
-
singleDatabase: !!process.env[`DATABASE_${id}`] || !!process.env[`FILE_${id}`],
|
|
85
|
-
displayName: process.env[`LABEL_${id}`],
|
|
86
|
-
isReadOnly: process.env[`READONLY_${id}`],
|
|
87
|
-
databases: process.env[`DBCONFIG_${id}`] ? safeJsonParse(process.env[`DBCONFIG_${id}`]) : null,
|
|
88
|
-
allowedDatabases: process.env[`ALLOWED_DATABASES_${id}`]?.replace(/\|/g, '\n'),
|
|
89
|
-
allowedDatabasesRegex: process.env[`ALLOWED_DATABASES_REGEX_${id}`],
|
|
90
|
-
parent: process.env[`PARENT_${id}`] || undefined,
|
|
91
|
-
useSeparateSchemas: !!process.env[`USE_SEPARATE_SCHEMAS_${id}`],
|
|
92
|
-
localDataCenter: process.env[`LOCAL_DATA_CENTER_${id}`],
|
|
93
|
-
|
|
94
|
-
// SSH tunnel
|
|
95
|
-
useSshTunnel: process.env[`USE_SSH_${id}`],
|
|
96
|
-
sshHost: process.env[`SSH_HOST_${id}`],
|
|
97
|
-
sshPort: process.env[`SSH_PORT_${id}`],
|
|
98
|
-
sshMode: process.env[`SSH_MODE_${id}`],
|
|
99
|
-
sshLogin: process.env[`SSH_LOGIN_${id}`],
|
|
100
|
-
sshPassword: process.env[`SSH_PASSWORD_${id}`],
|
|
101
|
-
sshKeyfile: process.env[`SSH_KEY_FILE_${id}`],
|
|
102
|
-
sshKeyfilePassword: process.env[`SSH_KEY_FILE_PASSWORD_${id}`],
|
|
103
|
-
|
|
104
|
-
// SSL
|
|
105
|
-
useSsl: process.env[`USE_SSL_${id}`],
|
|
106
|
-
sslCaFile: process.env[`SSL_CA_FILE_${id}`],
|
|
107
|
-
sslCertFile: process.env[`SSL_CERT_FILE_${id}`],
|
|
108
|
-
sslCertFilePassword: process.env[`SSL_CERT_FILE_PASSWORD_${id}`],
|
|
109
|
-
sslKeyFile: process.env[`SSL_KEY_FILE_${id}`],
|
|
110
|
-
sslRejectUnauthorized: process.env[`SSL_REJECT_UNAUTHORIZED_${id}`],
|
|
111
|
-
trustServerCertificate: process.env[`SSL_TRUST_CERTIFICATE_${id}`],
|
|
112
|
-
}));
|
|
65
|
+
const connections = extractConnectionsFromEnv(process.env);
|
|
113
66
|
|
|
114
67
|
for (const conn of connections) {
|
|
115
68
|
for (const prop in process.env) {
|
|
@@ -229,6 +182,15 @@ module.exports = {
|
|
|
229
182
|
);
|
|
230
183
|
}
|
|
231
184
|
await this.checkUnsavedConnectionsLimit();
|
|
185
|
+
|
|
186
|
+
if (process.env.STORAGE_DATABASE && process.env.CONNECTIONS) {
|
|
187
|
+
const storage = require('./storage');
|
|
188
|
+
try {
|
|
189
|
+
await storage.fillStorageConnectionsFromEnv();
|
|
190
|
+
} catch (err) {
|
|
191
|
+
logger.error(extractErrorLogData(err), 'DBGM-00268 Error filling storage connections from env');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
232
194
|
},
|
|
233
195
|
|
|
234
196
|
list_meta: true,
|
package/src/currentVersion.js
CHANGED
package/src/shell/copyStream.js
CHANGED
|
@@ -65,6 +65,8 @@ async function copyStream(input, output, options) {
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
} catch (err) {
|
|
68
|
+
logger.error(extractErrorLogData(err, { progressName }), 'DBGM-00157 Import/export job failed');
|
|
69
|
+
|
|
68
70
|
process.send({
|
|
69
71
|
msgtype: 'copyStreamError',
|
|
70
72
|
copyStreamError: {
|
|
@@ -82,8 +84,6 @@ async function copyStream(input, output, options) {
|
|
|
82
84
|
errorMessage: extractErrorMessage(err),
|
|
83
85
|
});
|
|
84
86
|
}
|
|
85
|
-
|
|
86
|
-
logger.error(extractErrorLogData(err, { progressName }), 'DBGM-00157 Import/export job failed');
|
|
87
87
|
// throw err;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -64,6 +64,7 @@ async function dataReplicator({
|
|
|
64
64
|
createNew: compileOperationFunction(item.createNew, item.createCondition),
|
|
65
65
|
updateExisting: compileOperationFunction(item.updateExisting, item.updateCondition),
|
|
66
66
|
deleteMissing: !!item.deleteMissing,
|
|
67
|
+
skipUpdateColumns: item.skipUpdateColumns,
|
|
67
68
|
deleteRestrictionColumns: item.deleteRestrictionColumns ?? [],
|
|
68
69
|
openStream: item.openStream
|
|
69
70
|
? item.openStream
|
package/src/storageModel.js
CHANGED
|
@@ -686,9 +686,34 @@ module.exports = {
|
|
|
686
686
|
"columnName": "connectionDefinition",
|
|
687
687
|
"dataType": "text",
|
|
688
688
|
"notNull": false
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
"pureName": "connections",
|
|
692
|
+
"columnName": "import_source_id",
|
|
693
|
+
"dataType": "int",
|
|
694
|
+
"notNull": false
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
"pureName": "connections",
|
|
698
|
+
"columnName": "id_original",
|
|
699
|
+
"dataType": "varchar(250)",
|
|
700
|
+
"notNull": false
|
|
701
|
+
}
|
|
702
|
+
],
|
|
703
|
+
"foreignKeys": [
|
|
704
|
+
{
|
|
705
|
+
"constraintType": "foreignKey",
|
|
706
|
+
"constraintName": "FK_connections_import_source_id",
|
|
707
|
+
"pureName": "connections",
|
|
708
|
+
"refTableName": "import_sources",
|
|
709
|
+
"columns": [
|
|
710
|
+
{
|
|
711
|
+
"columnName": "import_source_id",
|
|
712
|
+
"refColumnName": "id"
|
|
713
|
+
}
|
|
714
|
+
]
|
|
689
715
|
}
|
|
690
716
|
],
|
|
691
|
-
"foreignKeys": [],
|
|
692
717
|
"primaryKey": {
|
|
693
718
|
"pureName": "connections",
|
|
694
719
|
"constraintType": "primaryKey",
|
|
@@ -790,6 +815,41 @@ module.exports = {
|
|
|
790
815
|
}
|
|
791
816
|
]
|
|
792
817
|
},
|
|
818
|
+
{
|
|
819
|
+
"pureName": "import_sources",
|
|
820
|
+
"columns": [
|
|
821
|
+
{
|
|
822
|
+
"pureName": "import_sources",
|
|
823
|
+
"columnName": "id",
|
|
824
|
+
"dataType": "int",
|
|
825
|
+
"autoIncrement": true,
|
|
826
|
+
"notNull": true
|
|
827
|
+
},
|
|
828
|
+
{
|
|
829
|
+
"pureName": "import_sources",
|
|
830
|
+
"columnName": "name",
|
|
831
|
+
"dataType": "varchar(250)",
|
|
832
|
+
"notNull": true
|
|
833
|
+
}
|
|
834
|
+
],
|
|
835
|
+
"foreignKeys": [],
|
|
836
|
+
"primaryKey": {
|
|
837
|
+
"pureName": "import_sources",
|
|
838
|
+
"constraintType": "primaryKey",
|
|
839
|
+
"constraintName": "PK_import_sources",
|
|
840
|
+
"columns": [
|
|
841
|
+
{
|
|
842
|
+
"columnName": "id"
|
|
843
|
+
}
|
|
844
|
+
]
|
|
845
|
+
},
|
|
846
|
+
"preloadedRows": [
|
|
847
|
+
{
|
|
848
|
+
"id": -1,
|
|
849
|
+
"name": "env"
|
|
850
|
+
}
|
|
851
|
+
]
|
|
852
|
+
},
|
|
793
853
|
{
|
|
794
854
|
"pureName": "roles",
|
|
795
855
|
"columns": [
|
|
@@ -805,9 +865,34 @@ module.exports = {
|
|
|
805
865
|
"columnName": "name",
|
|
806
866
|
"dataType": "varchar(250)",
|
|
807
867
|
"notNull": false
|
|
868
|
+
},
|
|
869
|
+
{
|
|
870
|
+
"pureName": "roles",
|
|
871
|
+
"columnName": "import_source_id",
|
|
872
|
+
"dataType": "int",
|
|
873
|
+
"notNull": false
|
|
874
|
+
},
|
|
875
|
+
{
|
|
876
|
+
"pureName": "roles",
|
|
877
|
+
"columnName": "id_original",
|
|
878
|
+
"dataType": "varchar(250)",
|
|
879
|
+
"notNull": false
|
|
880
|
+
}
|
|
881
|
+
],
|
|
882
|
+
"foreignKeys": [
|
|
883
|
+
{
|
|
884
|
+
"constraintType": "foreignKey",
|
|
885
|
+
"constraintName": "FK_roles_import_source_id",
|
|
886
|
+
"pureName": "roles",
|
|
887
|
+
"refTableName": "import_sources",
|
|
888
|
+
"columns": [
|
|
889
|
+
{
|
|
890
|
+
"columnName": "import_source_id",
|
|
891
|
+
"refColumnName": "id"
|
|
892
|
+
}
|
|
893
|
+
]
|
|
808
894
|
}
|
|
809
895
|
],
|
|
810
|
-
"foreignKeys": [],
|
|
811
896
|
"primaryKey": {
|
|
812
897
|
"pureName": "roles",
|
|
813
898
|
"constraintType": "primaryKey",
|
|
@@ -854,6 +939,12 @@ module.exports = {
|
|
|
854
939
|
"columnName": "connection_id",
|
|
855
940
|
"dataType": "int",
|
|
856
941
|
"notNull": true
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
"pureName": "role_connections",
|
|
945
|
+
"columnName": "import_source_id",
|
|
946
|
+
"dataType": "int",
|
|
947
|
+
"notNull": false
|
|
857
948
|
}
|
|
858
949
|
],
|
|
859
950
|
"foreignKeys": [
|
|
@@ -882,6 +973,18 @@ module.exports = {
|
|
|
882
973
|
"refColumnName": "id"
|
|
883
974
|
}
|
|
884
975
|
]
|
|
976
|
+
},
|
|
977
|
+
{
|
|
978
|
+
"constraintType": "foreignKey",
|
|
979
|
+
"constraintName": "FK_role_connections_import_source_id",
|
|
980
|
+
"pureName": "role_connections",
|
|
981
|
+
"refTableName": "import_sources",
|
|
982
|
+
"columns": [
|
|
983
|
+
{
|
|
984
|
+
"columnName": "import_source_id",
|
|
985
|
+
"refColumnName": "id"
|
|
986
|
+
}
|
|
987
|
+
]
|
|
885
988
|
}
|
|
886
989
|
],
|
|
887
990
|
"primaryKey": {
|
|
@@ -934,6 +1037,18 @@ module.exports = {
|
|
|
934
1037
|
"columnName": "database_permission_role_id",
|
|
935
1038
|
"dataType": "int",
|
|
936
1039
|
"notNull": true
|
|
1040
|
+
},
|
|
1041
|
+
{
|
|
1042
|
+
"pureName": "role_databases",
|
|
1043
|
+
"columnName": "import_source_id",
|
|
1044
|
+
"dataType": "int",
|
|
1045
|
+
"notNull": false
|
|
1046
|
+
},
|
|
1047
|
+
{
|
|
1048
|
+
"pureName": "role_databases",
|
|
1049
|
+
"columnName": "id_original",
|
|
1050
|
+
"dataType": "varchar(250)",
|
|
1051
|
+
"notNull": false
|
|
937
1052
|
}
|
|
938
1053
|
],
|
|
939
1054
|
"foreignKeys": [
|
|
@@ -974,6 +1089,18 @@ module.exports = {
|
|
|
974
1089
|
"refColumnName": "id"
|
|
975
1090
|
}
|
|
976
1091
|
]
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
"constraintType": "foreignKey",
|
|
1095
|
+
"constraintName": "FK_role_databases_import_source_id",
|
|
1096
|
+
"pureName": "role_databases",
|
|
1097
|
+
"refTableName": "import_sources",
|
|
1098
|
+
"columns": [
|
|
1099
|
+
{
|
|
1100
|
+
"columnName": "import_source_id",
|
|
1101
|
+
"refColumnName": "id"
|
|
1102
|
+
}
|
|
1103
|
+
]
|
|
977
1104
|
}
|
|
978
1105
|
],
|
|
979
1106
|
"primaryKey": {
|
|
@@ -1087,6 +1214,12 @@ module.exports = {
|
|
|
1087
1214
|
"columnName": "permission",
|
|
1088
1215
|
"dataType": "varchar(250)",
|
|
1089
1216
|
"notNull": true
|
|
1217
|
+
},
|
|
1218
|
+
{
|
|
1219
|
+
"pureName": "role_permissions",
|
|
1220
|
+
"columnName": "import_source_id",
|
|
1221
|
+
"dataType": "int",
|
|
1222
|
+
"notNull": false
|
|
1090
1223
|
}
|
|
1091
1224
|
],
|
|
1092
1225
|
"foreignKeys": [
|
|
@@ -1102,6 +1235,18 @@ module.exports = {
|
|
|
1102
1235
|
"refColumnName": "id"
|
|
1103
1236
|
}
|
|
1104
1237
|
]
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
"constraintType": "foreignKey",
|
|
1241
|
+
"constraintName": "FK_role_permissions_import_source_id",
|
|
1242
|
+
"pureName": "role_permissions",
|
|
1243
|
+
"refTableName": "import_sources",
|
|
1244
|
+
"columns": [
|
|
1245
|
+
{
|
|
1246
|
+
"columnName": "import_source_id",
|
|
1247
|
+
"refColumnName": "id"
|
|
1248
|
+
}
|
|
1249
|
+
]
|
|
1105
1250
|
}
|
|
1106
1251
|
],
|
|
1107
1252
|
"primaryKey": {
|
|
@@ -1184,6 +1329,18 @@ module.exports = {
|
|
|
1184
1329
|
"columnName": "table_permission_scope_id",
|
|
1185
1330
|
"dataType": "int",
|
|
1186
1331
|
"notNull": true
|
|
1332
|
+
},
|
|
1333
|
+
{
|
|
1334
|
+
"pureName": "role_tables",
|
|
1335
|
+
"columnName": "import_source_id",
|
|
1336
|
+
"dataType": "int",
|
|
1337
|
+
"notNull": false
|
|
1338
|
+
},
|
|
1339
|
+
{
|
|
1340
|
+
"pureName": "role_tables",
|
|
1341
|
+
"columnName": "id_original",
|
|
1342
|
+
"dataType": "varchar(250)",
|
|
1343
|
+
"notNull": false
|
|
1187
1344
|
}
|
|
1188
1345
|
],
|
|
1189
1346
|
"foreignKeys": [
|
|
@@ -1236,6 +1393,18 @@ module.exports = {
|
|
|
1236
1393
|
"refColumnName": "id"
|
|
1237
1394
|
}
|
|
1238
1395
|
]
|
|
1396
|
+
},
|
|
1397
|
+
{
|
|
1398
|
+
"constraintType": "foreignKey",
|
|
1399
|
+
"constraintName": "FK_role_tables_import_source_id",
|
|
1400
|
+
"pureName": "role_tables",
|
|
1401
|
+
"refTableName": "import_sources",
|
|
1402
|
+
"columns": [
|
|
1403
|
+
{
|
|
1404
|
+
"columnName": "import_source_id",
|
|
1405
|
+
"refColumnName": "id"
|
|
1406
|
+
}
|
|
1407
|
+
]
|
|
1239
1408
|
}
|
|
1240
1409
|
],
|
|
1241
1410
|
"primaryKey": {
|
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const _ = require('lodash');
|
|
3
|
+
const { safeJsonParse, getDatabaseFileLabel } = require('dbgate-tools');
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
|
|
6
|
+
function extractConnectionsFromEnv(env) {
|
|
7
|
+
if (!env?.CONNECTIONS) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const connections = _.compact(env.CONNECTIONS.split(',')).map(id => ({
|
|
12
|
+
_id: id,
|
|
13
|
+
engine: env[`ENGINE_${id}`],
|
|
14
|
+
server: env[`SERVER_${id}`],
|
|
15
|
+
user: env[`USER_${id}`],
|
|
16
|
+
password: env[`PASSWORD_${id}`],
|
|
17
|
+
passwordMode: env[`PASSWORD_MODE_${id}`],
|
|
18
|
+
port: env[`PORT_${id}`],
|
|
19
|
+
databaseUrl: env[`URL_${id}`],
|
|
20
|
+
useDatabaseUrl: !!env[`URL_${id}`],
|
|
21
|
+
databaseFile: env[`FILE_${id}`]?.replace(
|
|
22
|
+
'%%E2E_TEST_DATA_DIRECTORY%%',
|
|
23
|
+
path.join(path.dirname(path.dirname(__dirname)), 'e2e-tests', 'tmpdata')
|
|
24
|
+
),
|
|
25
|
+
socketPath: env[`SOCKET_PATH_${id}`],
|
|
26
|
+
serviceName: env[`SERVICE_NAME_${id}`],
|
|
27
|
+
authType: env[`AUTH_TYPE_${id}`] || (env[`SOCKET_PATH_${id}`] ? 'socket' : undefined),
|
|
28
|
+
defaultDatabase: env[`DATABASE_${id}`] || (env[`FILE_${id}`] ? getDatabaseFileLabel(env[`FILE_${id}`]) : null),
|
|
29
|
+
singleDatabase: !!env[`DATABASE_${id}`] || !!env[`FILE_${id}`],
|
|
30
|
+
displayName: env[`LABEL_${id}`],
|
|
31
|
+
isReadOnly: env[`READONLY_${id}`],
|
|
32
|
+
databases: env[`DBCONFIG_${id}`] ? safeJsonParse(env[`DBCONFIG_${id}`]) : null,
|
|
33
|
+
allowedDatabases: env[`ALLOWED_DATABASES_${id}`]?.replace(/\|/g, '\n'),
|
|
34
|
+
allowedDatabasesRegex: env[`ALLOWED_DATABASES_REGEX_${id}`],
|
|
35
|
+
parent: env[`PARENT_${id}`] || undefined,
|
|
36
|
+
useSeparateSchemas: !!env[`USE_SEPARATE_SCHEMAS_${id}`],
|
|
37
|
+
localDataCenter: env[`LOCAL_DATA_CENTER_${id}`],
|
|
38
|
+
|
|
39
|
+
// SSH tunnel
|
|
40
|
+
useSshTunnel: env[`USE_SSH_${id}`],
|
|
41
|
+
sshHost: env[`SSH_HOST_${id}`],
|
|
42
|
+
sshPort: env[`SSH_PORT_${id}`],
|
|
43
|
+
sshMode: env[`SSH_MODE_${id}`],
|
|
44
|
+
sshLogin: env[`SSH_LOGIN_${id}`],
|
|
45
|
+
sshPassword: env[`SSH_PASSWORD_${id}`],
|
|
46
|
+
sshKeyfile: env[`SSH_KEY_FILE_${id}`],
|
|
47
|
+
sshKeyfilePassword: env[`SSH_KEY_FILE_PASSWORD_${id}`],
|
|
48
|
+
|
|
49
|
+
// SSL
|
|
50
|
+
useSsl: env[`USE_SSL_${id}`],
|
|
51
|
+
sslCaFile: env[`SSL_CA_FILE_${id}`],
|
|
52
|
+
sslCertFile: env[`SSL_CERT_FILE_${id}`],
|
|
53
|
+
sslCertFilePassword: env[`SSL_CERT_FILE_PASSWORD_${id}`],
|
|
54
|
+
sslKeyFile: env[`SSL_KEY_FILE_${id}`],
|
|
55
|
+
sslRejectUnauthorized: env[`SSL_REJECT_UNAUTHORIZED_${id}`],
|
|
56
|
+
trustServerCertificate: env[`SSL_TRUST_CERTIFICATE_${id}`],
|
|
57
|
+
}));
|
|
58
|
+
|
|
59
|
+
return connections;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function extractImportEntitiesFromEnv(env) {
|
|
63
|
+
const portalConnections = extractConnectionsFromEnv(env) || [];
|
|
64
|
+
|
|
65
|
+
const connections = portalConnections.map((conn, index) => ({
|
|
66
|
+
...conn,
|
|
67
|
+
id_original: conn._id,
|
|
68
|
+
import_source_id: -1,
|
|
69
|
+
conid: crypto.randomUUID(),
|
|
70
|
+
_id: undefined,
|
|
71
|
+
id: index + 1, // autoincrement id
|
|
72
|
+
}));
|
|
73
|
+
|
|
74
|
+
const connectionEnvIdToDbId = {};
|
|
75
|
+
for (const conn of connections) {
|
|
76
|
+
connectionEnvIdToDbId[conn.id_original] = conn.id;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const connectionsRegex = /^ROLE_(.+)_CONNECTIONS$/;
|
|
80
|
+
const permissionsRegex = /^ROLE_(.+)_PERMISSIONS$/;
|
|
81
|
+
|
|
82
|
+
const dbConnectionRegex = /^ROLE_(.+)_DATABASES_(.+)_CONNECTION$/;
|
|
83
|
+
const dbDatabasesRegex = /^ROLE_(.+)_DATABASES_(.+)_DATABASES$/;
|
|
84
|
+
const dbDatabasesRegexRegex = /^ROLE_(.+)_DATABASES_(.+)_DATABASES_REGEX$/;
|
|
85
|
+
const dbPermissionRegex = /^ROLE_(.+)_DATABASES_(.+)_PERMISSION$/;
|
|
86
|
+
|
|
87
|
+
const tableConnectionRegex = /^ROLE_(.+)_TABLES_(.+)_CONNECTION$/;
|
|
88
|
+
const tableDatabasesRegex = /^ROLE_(.+)_TABLES_(.+)_DATABASES$/;
|
|
89
|
+
const tableDatabasesRegexRegex = /^ROLE_(.+)_TABLES_(.+)_DATABASES_REGEX$/;
|
|
90
|
+
const tableSchemasRegex = /^ROLE_(.+)_TABLES_(.+)_SCHEMAS$/;
|
|
91
|
+
const tableSchemasRegexRegex = /^ROLE_(.+)_TABLES_(.+)_SCHEMAS_REGEX$/;
|
|
92
|
+
const tableTablesRegex = /^ROLE_(.+)_TABLES_(.+)_TABLES$/;
|
|
93
|
+
const tableTablesRegexRegex = /^ROLE_(.+)_TABLES_(.+)_TABLES_REGEX$/;
|
|
94
|
+
const tablePermissionRegex = /^ROLE_(.+)_TABLES_(.+)_PERMISSION$/;
|
|
95
|
+
const tableScopeRegex = /^ROLE_(.+)_TABLES_(.+)_SCOPE$/;
|
|
96
|
+
|
|
97
|
+
const roles = [];
|
|
98
|
+
const role_connections = [];
|
|
99
|
+
const role_permissions = [];
|
|
100
|
+
const role_databases = [];
|
|
101
|
+
const role_tables = [];
|
|
102
|
+
|
|
103
|
+
// Permission name to ID mappings
|
|
104
|
+
const databasePermissionMap = {
|
|
105
|
+
view: -1,
|
|
106
|
+
read_content: -2,
|
|
107
|
+
write_data: -3,
|
|
108
|
+
run_script: -4,
|
|
109
|
+
deny: -5,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const tablePermissionMap = {
|
|
113
|
+
read: -1,
|
|
114
|
+
update_only: -2,
|
|
115
|
+
create_update_delete: -3,
|
|
116
|
+
run_script: -4,
|
|
117
|
+
deny: -5,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const tableScopeMap = {
|
|
121
|
+
all_objects: -1,
|
|
122
|
+
tables: -2,
|
|
123
|
+
views: -3,
|
|
124
|
+
tables_views_collections: -4,
|
|
125
|
+
procedures: -5,
|
|
126
|
+
functions: -6,
|
|
127
|
+
triggers: -7,
|
|
128
|
+
sql_objects: -8,
|
|
129
|
+
collections: -9,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// Collect database and table permissions data
|
|
133
|
+
const databasePermissions = {};
|
|
134
|
+
const tablePermissions = {};
|
|
135
|
+
|
|
136
|
+
// First pass: collect all database and table permission data
|
|
137
|
+
for (const key in env) {
|
|
138
|
+
const dbConnMatch = key.match(dbConnectionRegex);
|
|
139
|
+
const dbDatabasesMatch = key.match(dbDatabasesRegex);
|
|
140
|
+
const dbDatabasesRegexMatch = key.match(dbDatabasesRegexRegex);
|
|
141
|
+
const dbPermMatch = key.match(dbPermissionRegex);
|
|
142
|
+
|
|
143
|
+
const tableConnMatch = key.match(tableConnectionRegex);
|
|
144
|
+
const tableDatabasesMatch = key.match(tableDatabasesRegex);
|
|
145
|
+
const tableDatabasesRegexMatch = key.match(tableDatabasesRegexRegex);
|
|
146
|
+
const tableSchemasMatch = key.match(tableSchemasRegex);
|
|
147
|
+
const tableSchemasRegexMatch = key.match(tableSchemasRegexRegex);
|
|
148
|
+
const tableTablesMatch = key.match(tableTablesRegex);
|
|
149
|
+
const tableTablesRegexMatch = key.match(tableTablesRegexRegex);
|
|
150
|
+
const tablePermMatch = key.match(tablePermissionRegex);
|
|
151
|
+
const tableScopeMatch = key.match(tableScopeRegex);
|
|
152
|
+
|
|
153
|
+
// Database permissions
|
|
154
|
+
if (dbConnMatch) {
|
|
155
|
+
const [, roleName, permId] = dbConnMatch;
|
|
156
|
+
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
|
157
|
+
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
|
158
|
+
databasePermissions[roleName][permId].connection = env[key];
|
|
159
|
+
}
|
|
160
|
+
if (dbDatabasesMatch) {
|
|
161
|
+
const [, roleName, permId] = dbDatabasesMatch;
|
|
162
|
+
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
|
163
|
+
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
|
164
|
+
databasePermissions[roleName][permId].databases = env[key]?.replace(/\|/g, '\n');
|
|
165
|
+
}
|
|
166
|
+
if (dbDatabasesRegexMatch) {
|
|
167
|
+
const [, roleName, permId] = dbDatabasesRegexMatch;
|
|
168
|
+
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
|
169
|
+
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
|
170
|
+
databasePermissions[roleName][permId].databasesRegex = env[key];
|
|
171
|
+
}
|
|
172
|
+
if (dbPermMatch) {
|
|
173
|
+
const [, roleName, permId] = dbPermMatch;
|
|
174
|
+
if (!databasePermissions[roleName]) databasePermissions[roleName] = {};
|
|
175
|
+
if (!databasePermissions[roleName][permId]) databasePermissions[roleName][permId] = {};
|
|
176
|
+
databasePermissions[roleName][permId].permission = env[key];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Table permissions
|
|
180
|
+
if (tableConnMatch) {
|
|
181
|
+
const [, roleName, permId] = tableConnMatch;
|
|
182
|
+
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
|
183
|
+
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
|
184
|
+
tablePermissions[roleName][permId].connection = env[key];
|
|
185
|
+
}
|
|
186
|
+
if (tableDatabasesMatch) {
|
|
187
|
+
const [, roleName, permId] = tableDatabasesMatch;
|
|
188
|
+
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
|
189
|
+
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
|
190
|
+
tablePermissions[roleName][permId].databases = env[key]?.replace(/\|/g, '\n');
|
|
191
|
+
}
|
|
192
|
+
if (tableDatabasesRegexMatch) {
|
|
193
|
+
const [, roleName, permId] = tableDatabasesRegexMatch;
|
|
194
|
+
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
|
195
|
+
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
|
196
|
+
tablePermissions[roleName][permId].databasesRegex = env[key];
|
|
197
|
+
}
|
|
198
|
+
if (tableSchemasMatch) {
|
|
199
|
+
const [, roleName, permId] = tableSchemasMatch;
|
|
200
|
+
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
|
201
|
+
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
|
202
|
+
tablePermissions[roleName][permId].schemas = env[key];
|
|
203
|
+
}
|
|
204
|
+
if (tableSchemasRegexMatch) {
|
|
205
|
+
const [, roleName, permId] = tableSchemasRegexMatch;
|
|
206
|
+
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
|
207
|
+
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
|
208
|
+
tablePermissions[roleName][permId].schemasRegex = env[key];
|
|
209
|
+
}
|
|
210
|
+
if (tableTablesMatch) {
|
|
211
|
+
const [, roleName, permId] = tableTablesMatch;
|
|
212
|
+
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
|
213
|
+
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
|
214
|
+
tablePermissions[roleName][permId].tables = env[key]?.replace(/\|/g, '\n');
|
|
215
|
+
}
|
|
216
|
+
if (tableTablesRegexMatch) {
|
|
217
|
+
const [, roleName, permId] = tableTablesRegexMatch;
|
|
218
|
+
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
|
219
|
+
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
|
220
|
+
tablePermissions[roleName][permId].tablesRegex = env[key];
|
|
221
|
+
}
|
|
222
|
+
if (tablePermMatch) {
|
|
223
|
+
const [, roleName, permId] = tablePermMatch;
|
|
224
|
+
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
|
225
|
+
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
|
226
|
+
tablePermissions[roleName][permId].permission = env[key];
|
|
227
|
+
}
|
|
228
|
+
if (tableScopeMatch) {
|
|
229
|
+
const [, roleName, permId] = tableScopeMatch;
|
|
230
|
+
if (!tablePermissions[roleName]) tablePermissions[roleName] = {};
|
|
231
|
+
if (!tablePermissions[roleName][permId]) tablePermissions[roleName][permId] = {};
|
|
232
|
+
tablePermissions[roleName][permId].scope = env[key];
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Second pass: process roles, connections, and permissions
|
|
237
|
+
for (const key in env) {
|
|
238
|
+
const connMatch = key.match(connectionsRegex);
|
|
239
|
+
const permMatch = key.match(permissionsRegex);
|
|
240
|
+
if (connMatch) {
|
|
241
|
+
const roleName = connMatch[1];
|
|
242
|
+
let role = roles.find(r => r.name === roleName);
|
|
243
|
+
if (!role) {
|
|
244
|
+
role = {
|
|
245
|
+
id: roles.length + 1,
|
|
246
|
+
name: roleName,
|
|
247
|
+
import_source_id: -1,
|
|
248
|
+
};
|
|
249
|
+
roles.push(role);
|
|
250
|
+
}
|
|
251
|
+
const connIds = env[key]
|
|
252
|
+
.split(',')
|
|
253
|
+
.map(id => id.trim())
|
|
254
|
+
.filter(id => id.length > 0);
|
|
255
|
+
for (const connId of connIds) {
|
|
256
|
+
const dbId = connectionEnvIdToDbId[connId];
|
|
257
|
+
if (dbId) {
|
|
258
|
+
role_connections.push({
|
|
259
|
+
role_id: role.id,
|
|
260
|
+
connection_id: dbId,
|
|
261
|
+
import_source_id: -1,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (permMatch) {
|
|
267
|
+
const roleName = permMatch[1];
|
|
268
|
+
let role = roles.find(r => r.name === roleName);
|
|
269
|
+
if (!role) {
|
|
270
|
+
role = {
|
|
271
|
+
id: roles.length + 1,
|
|
272
|
+
name: roleName,
|
|
273
|
+
import_source_id: -1,
|
|
274
|
+
};
|
|
275
|
+
roles.push(role);
|
|
276
|
+
}
|
|
277
|
+
const permissions = env[key]
|
|
278
|
+
.split(',')
|
|
279
|
+
.map(p => p.trim())
|
|
280
|
+
.filter(p => p.length > 0);
|
|
281
|
+
for (const permission of permissions) {
|
|
282
|
+
role_permissions.push({
|
|
283
|
+
role_id: role.id,
|
|
284
|
+
permission,
|
|
285
|
+
import_source_id: -1,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Process database permissions
|
|
292
|
+
for (const roleName in databasePermissions) {
|
|
293
|
+
let role = roles.find(r => r.name === roleName);
|
|
294
|
+
if (!role) {
|
|
295
|
+
role = {
|
|
296
|
+
id: roles.length + 1,
|
|
297
|
+
name: roleName,
|
|
298
|
+
import_source_id: -1,
|
|
299
|
+
};
|
|
300
|
+
roles.push(role);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
for (const permId in databasePermissions[roleName]) {
|
|
304
|
+
const perm = databasePermissions[roleName][permId];
|
|
305
|
+
if (perm.connection && perm.permission) {
|
|
306
|
+
const dbId = connectionEnvIdToDbId[perm.connection];
|
|
307
|
+
const permissionId = databasePermissionMap[perm.permission];
|
|
308
|
+
if (dbId && permissionId) {
|
|
309
|
+
role_databases.push({
|
|
310
|
+
role_id: role.id,
|
|
311
|
+
connection_id: dbId,
|
|
312
|
+
database_names_list: perm.databases || null,
|
|
313
|
+
database_names_regex: perm.databasesRegex || null,
|
|
314
|
+
database_permission_role_id: permissionId,
|
|
315
|
+
id_original: permId,
|
|
316
|
+
import_source_id: -1,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Process table permissions
|
|
324
|
+
for (const roleName in tablePermissions) {
|
|
325
|
+
let role = roles.find(r => r.name === roleName);
|
|
326
|
+
if (!role) {
|
|
327
|
+
role = {
|
|
328
|
+
id: roles.length + 1,
|
|
329
|
+
name: roleName,
|
|
330
|
+
import_source_id: -1,
|
|
331
|
+
};
|
|
332
|
+
roles.push(role);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
for (const permId in tablePermissions[roleName]) {
|
|
336
|
+
const perm = tablePermissions[roleName][permId];
|
|
337
|
+
if (perm.connection && perm.permission) {
|
|
338
|
+
const dbId = connectionEnvIdToDbId[perm.connection];
|
|
339
|
+
const permissionId = tablePermissionMap[perm.permission];
|
|
340
|
+
const scopeId = tableScopeMap[perm.scope || 'all_objects'];
|
|
341
|
+
if (dbId && permissionId && scopeId) {
|
|
342
|
+
role_tables.push({
|
|
343
|
+
role_id: role.id,
|
|
344
|
+
connection_id: dbId,
|
|
345
|
+
database_names_list: perm.databases || null,
|
|
346
|
+
database_names_regex: perm.databasesRegex || null,
|
|
347
|
+
schema_names_list: perm.schemas || null,
|
|
348
|
+
schema_names_regex: perm.schemasRegex || null,
|
|
349
|
+
table_names_list: perm.tables || null,
|
|
350
|
+
table_names_regex: perm.tablesRegex || null,
|
|
351
|
+
table_permission_role_id: permissionId,
|
|
352
|
+
table_permission_scope_id: scopeId,
|
|
353
|
+
id_original: permId,
|
|
354
|
+
import_source_id: -1,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (connections.length == 0 && roles.length == 0) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return {
|
|
366
|
+
connections,
|
|
367
|
+
roles,
|
|
368
|
+
role_connections,
|
|
369
|
+
role_permissions,
|
|
370
|
+
role_databases,
|
|
371
|
+
role_tables,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function createStorageFromEnvReplicatorItems(importEntities) {
|
|
376
|
+
return [
|
|
377
|
+
{
|
|
378
|
+
name: 'connections',
|
|
379
|
+
findExisting: true,
|
|
380
|
+
createNew: true,
|
|
381
|
+
updateExisting: true,
|
|
382
|
+
matchColumns: ['id_original', 'import_source_id'],
|
|
383
|
+
deleteMissing: true,
|
|
384
|
+
deleteRestrictionColumns: ['import_source_id'],
|
|
385
|
+
skipUpdateColumns: ['conid'],
|
|
386
|
+
jsonArray: importEntities.connections,
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
name: 'roles',
|
|
390
|
+
findExisting: true,
|
|
391
|
+
createNew: true,
|
|
392
|
+
updateExisting: true,
|
|
393
|
+
matchColumns: ['name', 'import_source_id'],
|
|
394
|
+
deleteMissing: true,
|
|
395
|
+
deleteRestrictionColumns: ['import_source_id'],
|
|
396
|
+
jsonArray: importEntities.roles,
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
name: 'role_connections',
|
|
400
|
+
findExisting: true,
|
|
401
|
+
createNew: true,
|
|
402
|
+
updateExisting: false,
|
|
403
|
+
deleteMissing: true,
|
|
404
|
+
matchColumns: ['role_id', 'connection_id', 'import_source_id'],
|
|
405
|
+
jsonArray: importEntities.role_connections,
|
|
406
|
+
deleteRestrictionColumns: ['import_source_id'],
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
name: 'role_permissions',
|
|
410
|
+
findExisting: true,
|
|
411
|
+
createNew: true,
|
|
412
|
+
updateExisting: false,
|
|
413
|
+
deleteMissing: true,
|
|
414
|
+
matchColumns: ['role_id', 'permission', 'import_source_id'],
|
|
415
|
+
jsonArray: importEntities.role_permissions,
|
|
416
|
+
deleteRestrictionColumns: ['import_source_id'],
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
name: 'role_databases',
|
|
420
|
+
findExisting: true,
|
|
421
|
+
createNew: true,
|
|
422
|
+
updateExisting: true,
|
|
423
|
+
deleteMissing: true,
|
|
424
|
+
matchColumns: ['role_id', 'id_original', 'import_source_id'],
|
|
425
|
+
jsonArray: importEntities.role_databases,
|
|
426
|
+
deleteRestrictionColumns: ['import_source_id'],
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
name: 'role_tables',
|
|
430
|
+
findExisting: true,
|
|
431
|
+
createNew: true,
|
|
432
|
+
updateExisting: true,
|
|
433
|
+
deleteMissing: true,
|
|
434
|
+
matchColumns: ['role_id', 'id_original', 'import_source_id'],
|
|
435
|
+
jsonArray: importEntities.role_tables,
|
|
436
|
+
deleteRestrictionColumns: ['import_source_id'],
|
|
437
|
+
},
|
|
438
|
+
];
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
module.exports = {
|
|
442
|
+
extractConnectionsFromEnv,
|
|
443
|
+
extractImportEntitiesFromEnv,
|
|
444
|
+
createStorageFromEnvReplicatorItems,
|
|
445
|
+
};
|