coolify/docker/coolify-realtime/terminal-utils.js
2026-03-10 20:37:22 +01:00

127 lines
3.5 KiB
JavaScript

export function extractTimeout(commandString) {
const timeoutMatch = commandString.match(/timeout (\d+)/);
return timeoutMatch ? parseInt(timeoutMatch[1], 10) : null;
}
function normalizeShellArgument(argument) {
if (!argument) {
return argument;
}
return argument
.replace(/'([^']*)'/g, '$1')
.replace(/"([^"]*)"/g, '$1');
}
export function extractSshArgs(commandString) {
const sshCommandMatch = commandString.match(/ssh (.+?) 'bash -se'/);
if (!sshCommandMatch) return [];
const argsString = sshCommandMatch[1];
let sshArgs = [];
let current = '';
let inQuotes = false;
let quoteChar = '';
let i = 0;
while (i < argsString.length) {
const char = argsString[i];
if (!inQuotes && (char === '"' || char === "'")) {
inQuotes = true;
quoteChar = char;
current += char;
} else if (inQuotes && char === quoteChar) {
inQuotes = false;
current += char;
quoteChar = '';
} else if (!inQuotes && char === ' ') {
if (current.trim()) {
sshArgs.push(current.trim());
current = '';
}
} else {
current += char;
}
i++;
}
if (current.trim()) {
sshArgs.push(current.trim());
}
sshArgs = sshArgs.map((arg) => normalizeShellArgument(arg));
sshArgs = sshArgs.map(arg => arg === 'RequestTTY=no' ? 'RequestTTY=yes' : arg);
if (!sshArgs.includes('RequestTTY=yes') && !sshArgs.some(arg => arg.includes('RequestTTY='))) {
sshArgs.push('-o', 'RequestTTY=yes');
}
return sshArgs;
}
export function extractHereDocContent(commandString) {
const delimiterMatch = commandString.match(/<< (\S+)/);
const delimiter = delimiterMatch ? delimiterMatch[1] : null;
const escapedDelimiter = delimiter?.slice(1).trim().replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
if (!escapedDelimiter) {
return '';
}
const hereDocRegex = new RegExp(`<< \\\\${escapedDelimiter}([\\s\\S\\.]*?)${escapedDelimiter}`);
const hereDocMatch = commandString.match(hereDocRegex);
return hereDocMatch ? hereDocMatch[1] : '';
}
export function normalizeHostForAuthorization(host) {
if (!host) {
return null;
}
let normalizedHost = host.trim();
while (
normalizedHost.length >= 2 &&
((normalizedHost.startsWith("'") && normalizedHost.endsWith("'")) ||
(normalizedHost.startsWith('"') && normalizedHost.endsWith('"')))
) {
normalizedHost = normalizedHost.slice(1, -1).trim();
}
if (normalizedHost.startsWith('[') && normalizedHost.endsWith(']')) {
normalizedHost = normalizedHost.slice(1, -1);
}
return normalizedHost.toLowerCase();
}
export function extractTargetHost(sshArgs) {
const userAtHost = sshArgs.find(arg => {
if (arg.includes('storage/app/ssh/keys/')) {
return false;
}
return /^[^@]+@[^@]+$/.test(arg);
});
if (!userAtHost) {
return null;
}
const atIndex = userAtHost.indexOf('@');
return normalizeHostForAuthorization(userAtHost.slice(atIndex + 1));
}
export function isAuthorizedTargetHost(targetHost, authorizedHosts = []) {
const normalizedTargetHost = normalizeHostForAuthorization(targetHost);
if (!normalizedTargetHost) {
return false;
}
return authorizedHosts
.map(host => normalizeHostForAuthorization(host))
.includes(normalizedTargetHost);
}