mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-28 19:27:41 +00:00
fix: separate Docker API port from SSH port, add SSH credential UI, fix compose_dir routing
This commit is contained in:
@@ -1414,7 +1414,7 @@ app.get('/api/nodes/:id', async (req: Request, res: Response) => {
|
||||
// Create a new node
|
||||
app.post('/api/nodes', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { name, type, host, port, compose_dir, is_default } = req.body;
|
||||
const { name, type, host, port, ssh_port, compose_dir, is_default, ssh_user, ssh_password, ssh_key } = req.body;
|
||||
|
||||
if (!name || typeof name !== 'string') {
|
||||
return res.status(400).json({ error: 'Node name is required' });
|
||||
@@ -1431,8 +1431,12 @@ app.post('/api/nodes', async (req: Request, res: Response) => {
|
||||
type,
|
||||
host: host || '',
|
||||
port: port || 2375,
|
||||
ssh_port: ssh_port || 22,
|
||||
compose_dir: compose_dir || '/opt/docker',
|
||||
is_default: is_default || false,
|
||||
ssh_user: ssh_user || '',
|
||||
ssh_password: ssh_password || '',
|
||||
ssh_key: ssh_key || '',
|
||||
});
|
||||
|
||||
res.json({ success: true, id });
|
||||
|
||||
@@ -137,7 +137,7 @@ export class ComposeService {
|
||||
if (throwOnError) reject(err); else resolve();
|
||||
}).connect({
|
||||
host: node.host,
|
||||
port: node.port || 22,
|
||||
port: node.ssh_port || 22,
|
||||
username: node.ssh_user!,
|
||||
password: node.ssh_password,
|
||||
privateKey: node.ssh_key,
|
||||
@@ -305,7 +305,7 @@ export class ComposeService {
|
||||
});
|
||||
}).on('error', handleProcessEnd).connect({
|
||||
host: node!.host,
|
||||
port: node!.port || 22,
|
||||
port: node!.ssh_port || 22,
|
||||
username: node!.ssh_user!,
|
||||
password: node!.ssh_password,
|
||||
privateKey: node!.ssh_key,
|
||||
|
||||
@@ -31,6 +31,7 @@ export interface Node {
|
||||
type: 'local' | 'remote';
|
||||
host: string;
|
||||
port: number;
|
||||
ssh_port: number;
|
||||
compose_dir: string;
|
||||
is_default: boolean;
|
||||
status: 'online' | 'offline' | 'unknown';
|
||||
@@ -146,6 +147,7 @@ export class DatabaseService {
|
||||
const maybeAddCol = (table: string, col: string, def: string) => {
|
||||
try { this.db.prepare(`ALTER TABLE ${table} ADD COLUMN ${col} ${def}`).run(); } catch (e) { /* ignore */ }
|
||||
};
|
||||
maybeAddCol('nodes', 'ssh_port', 'INTEGER DEFAULT 22');
|
||||
maybeAddCol('nodes', 'ssh_user', "TEXT DEFAULT ''");
|
||||
maybeAddCol('nodes', 'ssh_password', "TEXT DEFAULT ''");
|
||||
maybeAddCol('nodes', 'ssh_key', "TEXT DEFAULT ''");
|
||||
@@ -368,13 +370,14 @@ export class DatabaseService {
|
||||
this.db.prepare('UPDATE nodes SET is_default = 0').run();
|
||||
}
|
||||
const stmt = this.db.prepare(
|
||||
'INSERT INTO nodes (name, type, host, port, compose_dir, is_default, status, created_at, ssh_user, ssh_password, ssh_key, tls_ca, tls_cert, tls_key) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
|
||||
'INSERT INTO nodes (name, type, host, port, ssh_port, compose_dir, is_default, status, created_at, ssh_user, ssh_password, ssh_key, tls_ca, tls_cert, tls_key) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
|
||||
);
|
||||
const result = stmt.run(
|
||||
node.name,
|
||||
node.type,
|
||||
node.host,
|
||||
node.port,
|
||||
node.ssh_port || 22,
|
||||
node.compose_dir,
|
||||
node.is_default ? 1 : 0,
|
||||
'unknown',
|
||||
@@ -405,6 +408,7 @@ export class DatabaseService {
|
||||
if (updates.type !== undefined) { fields.push('type = ?'); values.push(updates.type); }
|
||||
if (updates.host !== undefined) { fields.push('host = ?'); values.push(updates.host); }
|
||||
if (updates.port !== undefined) { fields.push('port = ?'); values.push(updates.port); }
|
||||
if (updates.ssh_port !== undefined) { fields.push('ssh_port = ?'); values.push(updates.ssh_port); }
|
||||
if (updates.compose_dir !== undefined) { fields.push('compose_dir = ?'); values.push(updates.compose_dir); }
|
||||
if (updates.is_default !== undefined) { fields.push('is_default = ?'); values.push(updates.is_default ? 1 : 0); }
|
||||
if (updates.status !== undefined) { fields.push('status = ?'); values.push(updates.status); }
|
||||
|
||||
@@ -10,14 +10,15 @@ export class FileSystemService {
|
||||
private nodeId: number;
|
||||
|
||||
constructor(nodeId?: number) {
|
||||
this.baseDir = process.env.COMPOSE_DIR || '/app/compose';
|
||||
this.nodeId = nodeId ?? NodeRegistry.getInstance().getDefaultNodeId();
|
||||
|
||||
const node = NodeRegistry.getInstance().getNode(this.nodeId);
|
||||
|
||||
if (!node || node.type === 'local' || !node.host) {
|
||||
this.baseDir = process.env.COMPOSE_DIR || '/app/compose';
|
||||
this.adapter = new LocalFileAdapter();
|
||||
} else {
|
||||
this.baseDir = node.compose_dir || '/app/compose';
|
||||
this.adapter = new SSHFileAdapter(node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export class SSHFileAdapter implements IFileAdapter {
|
||||
const sftp = new Client();
|
||||
await sftp.connect({
|
||||
host: this.node.host,
|
||||
port: this.node.port || 22,
|
||||
port: this.node.ssh_port || 22,
|
||||
username: this.node.ssh_user!,
|
||||
password: this.node.ssh_password,
|
||||
privateKey: this.node.ssh_key,
|
||||
|
||||
Reference in New Issue
Block a user