Merge branch 'master' into feature/duckdb-2

This commit is contained in:
SPRINX0\prochazka
2025-04-02 14:16:38 +02:00
committed by Nybkox
83 changed files with 1418 additions and 312 deletions

View File

@@ -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;

View File

@@ -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;
},

View File

@@ -38,6 +38,8 @@ function start() {
detail: formatErrorDetail(e, connection),
});
}
process.exit(0);
});
}

View File

@@ -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,
};

View File

@@ -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>`;