Files
backstor-ui/server/ssh_service.js
2025-12-08 12:12:07 +07:00

66 lines
2.0 KiB
JavaScript

const { Client } = require('ssh2');
const fs = require('fs');
require('dotenv').config();
const getSSHConfig = () => {
const config = {
host: process.env.SSH_HOST,
username: process.env.SSH_USER,
port: 22,
};
let privateKeyPath = process.env.SSH_KEY_PATH;
if (privateKeyPath && privateKeyPath.endsWith('.pub')) {
privateKeyPath = privateKeyPath.replace('.pub', '');
}
if (privateKeyPath) {
config.privateKey = fs.readFileSync(privateKeyPath);
} else if (process.env.SSH_PASSWORD) {
config.password = process.env.SSH_PASSWORD;
}
return config;
};
const execCommand = (command) => {
return new Promise((resolve, reject) => {
const conn = new Client();
conn.on('ready', () => {
conn.exec(command, (err, stream) => {
if (err) {
conn.end();
return reject(err);
}
let output = '';
let errorOutput = '';
stream.on('close', (code, signal) => {
conn.end();
if (code !== 0) return reject(new Error(`Command failed with code ${code}: ${errorOutput}`));
resolve(output.trim());
}).on('data', (data) => {
output += data;
}).stderr.on('data', (data) => {
errorOutput += data;
});
});
}).on('error', (err) => {
reject(err);
}).connect(getSSHConfig());
});
};
const readFile = (filePath) => {
return execCommand(`cat "${filePath}"`);
};
const writeFile = (filePath, content) => {
// Basic implementation: echo content to file.
// WARNING: Not safe for large files or complex headers, but start simple.
// Ideally use SFTP for robustness later.
const escapedContent = content.replace(/"/g, '\\"');
return execCommand(`echo "${escapedContent}" > "${filePath}"`);
};
module.exports = { execCommand, readFile, writeFile };