mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-24 19:56:00 +00:00
Merge branch 'master' into feature/duckdb-2
This commit is contained in:
@@ -102,12 +102,21 @@ function getPortalCollections() {
|
||||
trustServerCertificate: process.env[`SSL_TRUST_CERTIFICATE_${id}`],
|
||||
}));
|
||||
|
||||
for(const conn of connections) {
|
||||
for(const prop in process.env) {
|
||||
if (prop.startsWith(`CONNECTION_${conn._id}_`)) {
|
||||
const name = prop.substring(`CONNECTION_${conn._id}_`.length);
|
||||
conn[name] = process.env[prop];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info({ connections: connections.map(pickSafeConnectionInfo) }, 'Using connections from ENV variables');
|
||||
const noengine = connections.filter(x => !x.engine);
|
||||
if (noengine.length > 0) {
|
||||
logger.warn(
|
||||
{ connections: noengine.map(x => x._id) },
|
||||
'Invalid CONNECTIONS configutation, missing ENGINE for connection ID'
|
||||
'Invalid CONNECTIONS configuration, missing ENGINE for connection ID'
|
||||
);
|
||||
}
|
||||
return connections;
|
||||
|
||||
@@ -195,8 +195,8 @@ module.exports = {
|
||||
},
|
||||
|
||||
exportDiagram_meta: true,
|
||||
async exportDiagram({ filePath, html, css, themeType, themeClassName }) {
|
||||
await fs.writeFile(filePath, getDiagramExport(html, css, themeType, themeClassName));
|
||||
async exportDiagram({ filePath, html, css, themeType, themeClassName, watermark }) {
|
||||
await fs.writeFile(filePath, getDiagramExport(html, css, themeType, themeClassName, watermark));
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ function start() {
|
||||
detail: formatErrorDetail(e, connection),
|
||||
});
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,26 @@ function loadEncryptionKey() {
|
||||
return _encryptionKey;
|
||||
}
|
||||
|
||||
async function loadEncryptionKeyFromExternal(storedValue, setStoredValue) {
|
||||
const encryptor = simpleEncryptor.createEncryptor(defaultEncryptionKey);
|
||||
|
||||
if (!storedValue) {
|
||||
const generatedKey = crypto.randomBytes(32);
|
||||
const newKey = generatedKey.toString('hex');
|
||||
const result = {
|
||||
encryptionKey: newKey,
|
||||
};
|
||||
await setStoredValue(encryptor.encrypt(result));
|
||||
|
||||
setEncryptionKey(newKey);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const data = encryptor.decrypt(storedValue);
|
||||
setEncryptionKey(data['encryptionKey']);
|
||||
}
|
||||
|
||||
let _encryptor = null;
|
||||
|
||||
function getEncryptor() {
|
||||
@@ -43,35 +63,32 @@ function getEncryptor() {
|
||||
return _encryptor;
|
||||
}
|
||||
|
||||
function encryptPasswordField(connection, field) {
|
||||
if (
|
||||
connection &&
|
||||
connection[field] &&
|
||||
!connection[field].startsWith('crypt:') &&
|
||||
connection.passwordMode != 'saveRaw'
|
||||
) {
|
||||
function encryptObjectPasswordField(obj, field) {
|
||||
if (obj && obj[field] && !obj[field].startsWith('crypt:')) {
|
||||
return {
|
||||
...connection,
|
||||
[field]: 'crypt:' + getEncryptor().encrypt(connection[field]),
|
||||
...obj,
|
||||
[field]: 'crypt:' + getEncryptor().encrypt(obj[field]),
|
||||
};
|
||||
}
|
||||
return connection;
|
||||
return obj;
|
||||
}
|
||||
|
||||
function decryptPasswordField(connection, field) {
|
||||
if (connection && connection[field] && connection[field].startsWith('crypt:')) {
|
||||
function decryptObjectPasswordField(obj, field) {
|
||||
if (obj && obj[field] && obj[field].startsWith('crypt:')) {
|
||||
return {
|
||||
...connection,
|
||||
[field]: getEncryptor().decrypt(connection[field].substring('crypt:'.length)),
|
||||
...obj,
|
||||
[field]: getEncryptor().decrypt(obj[field].substring('crypt:'.length)),
|
||||
};
|
||||
}
|
||||
return connection;
|
||||
return obj;
|
||||
}
|
||||
|
||||
function encryptConnection(connection) {
|
||||
connection = encryptPasswordField(connection, 'password');
|
||||
connection = encryptPasswordField(connection, 'sshPassword');
|
||||
connection = encryptPasswordField(connection, 'sshKeyfilePassword');
|
||||
if (connection.passwordMode != 'saveRaw') {
|
||||
connection = encryptObjectPasswordField(connection, 'password');
|
||||
connection = encryptObjectPasswordField(connection, 'sshPassword');
|
||||
connection = encryptObjectPasswordField(connection, 'sshKeyfilePassword');
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
@@ -81,12 +98,24 @@ function maskConnection(connection) {
|
||||
}
|
||||
|
||||
function decryptConnection(connection) {
|
||||
connection = decryptPasswordField(connection, 'password');
|
||||
connection = decryptPasswordField(connection, 'sshPassword');
|
||||
connection = decryptPasswordField(connection, 'sshKeyfilePassword');
|
||||
connection = decryptObjectPasswordField(connection, 'password');
|
||||
connection = decryptObjectPasswordField(connection, 'sshPassword');
|
||||
connection = decryptObjectPasswordField(connection, 'sshKeyfilePassword');
|
||||
return connection;
|
||||
}
|
||||
|
||||
function encryptUser(user) {
|
||||
if (user.encryptPassword) {
|
||||
user = encryptObjectPasswordField(user, 'password');
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
function decryptUser(user) {
|
||||
user = decryptObjectPasswordField(user, 'password');
|
||||
return user;
|
||||
}
|
||||
|
||||
function pickSafeConnectionInfo(connection) {
|
||||
if (process.env.LOG_CONNECTION_SENSITIVE_VALUES) {
|
||||
return connection;
|
||||
@@ -99,10 +128,18 @@ function pickSafeConnectionInfo(connection) {
|
||||
});
|
||||
}
|
||||
|
||||
function setEncryptionKey(encryptionKey) {
|
||||
_encryptionKey = encryptionKey;
|
||||
_encryptor = null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
loadEncryptionKey,
|
||||
encryptConnection,
|
||||
encryptUser,
|
||||
decryptUser,
|
||||
decryptConnection,
|
||||
maskConnection,
|
||||
pickSafeConnectionInfo,
|
||||
loadEncryptionKeyFromExternal,
|
||||
};
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
const getDiagramExport = (html, css, themeType, themeClassName) => {
|
||||
const getDiagramExport = (html, css, themeType, themeClassName, watermark) => {
|
||||
const watermarkHtml = watermark
|
||||
? `
|
||||
<div style="position: fixed; bottom: 0; right: 0; padding: 5px; font-size: 12px; color: var(--theme-font-2); background-color: var(--theme-bg-2); border-top-left-radius: 5px; border: 1px solid var(--theme-border);">
|
||||
${watermark}
|
||||
</div>
|
||||
`
|
||||
: '';
|
||||
return `<html>
|
||||
<meta charset='utf-8'>
|
||||
|
||||
@@ -13,10 +20,44 @@ const getDiagramExport = (html, css, themeType, themeClassName) => {
|
||||
</style>
|
||||
|
||||
<link rel="stylesheet" href='https://cdn.jsdelivr.net/npm/@mdi/font@6.5.95/css/materialdesignicons.css' />
|
||||
|
||||
<script>
|
||||
let lastX = null;
|
||||
let lastY = null;
|
||||
|
||||
const handleMoveDown = e => {
|
||||
lastX = e.clientX;
|
||||
lastY = e.clientY;
|
||||
document.addEventListener('mousemove', handleMoveMove, true);
|
||||
document.addEventListener('mouseup', handleMoveEnd, true);
|
||||
};
|
||||
|
||||
const handleMoveMove = e => {
|
||||
e.preventDefault();
|
||||
|
||||
document.body.scrollLeft -= e.clientX - lastX;
|
||||
document.body.scrollTop -= e.clientY - lastY;
|
||||
|
||||
lastX = e.clientX;
|
||||
lastY = e.clientY;
|
||||
};
|
||||
const handleMoveEnd = e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
lastX = null;
|
||||
lastY = null;
|
||||
document.removeEventListener('mousemove', handleMoveMove, true);
|
||||
document.removeEventListener('mouseup', handleMoveEnd, true);
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', handleMoveDown);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body class='${themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light'} ${themeClassName}'>
|
||||
<body class='${themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light'} ${themeClassName}' style='user-select:none; cursor:pointer'>
|
||||
${html}
|
||||
${watermarkHtml}
|
||||
</body>
|
||||
|
||||
</html>`;
|
||||
|
||||
Reference in New Issue
Block a user