feat: migrate from static config to database and add authentication
- Replaced static hosts.json and staticConfig.ts with SQLite database (Prisma) - Implemented JWT authentication and Login UI - Added dynamic API routes for hosts, topology, and settings - Updated UI components to fetch and manage state dynamically - Added Settings interface for managing hosts and topology nodes
This commit is contained in:
@@ -1,76 +1,31 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { homedir } from 'os';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import { HostConfig } from './types';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const CONFIG_FILE = path.join(__dirname, 'hosts.json');
|
||||
|
||||
function parseEnvHosts(): HostConfig[] {
|
||||
const hostsEnv = process.env.SSH_HOSTS;
|
||||
if (!hostsEnv) return [];
|
||||
|
||||
const hosts: HostConfig[] = [];
|
||||
const entries = hostsEnv.split(',').map(h => h.trim()).filter(Boolean);
|
||||
|
||||
for (const entry of entries) {
|
||||
const [name, ip] = entry.split(':');
|
||||
if (name && ip) {
|
||||
hosts.push({
|
||||
name: name.trim(),
|
||||
ip: ip.trim(),
|
||||
sshUser: process.env.SSH_USER || 'bear',
|
||||
sshKeyPath: process.env.SSH_KEY,
|
||||
sshPort: process.env.SSH_PORT ? parseInt(process.env.SSH_PORT, 10) : 22,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return hosts;
|
||||
}
|
||||
|
||||
function parseJsonConfig(): HostConfig[] {
|
||||
if (!fs.existsSync(CONFIG_FILE)) {
|
||||
console.error('Config file not found:', CONFIG_FILE);
|
||||
return [];
|
||||
}
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export async function getHostConfigs(): Promise<HostConfig[]> {
|
||||
try {
|
||||
const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
||||
const data = JSON.parse(content);
|
||||
|
||||
if (!data.hosts || !Array.isArray(data.hosts)) {
|
||||
console.error('No hosts array in config');
|
||||
return [];
|
||||
}
|
||||
|
||||
const hosts = data.hosts.map((h: Partial<HostConfig>) => ({
|
||||
name: h.name || '',
|
||||
ip: h.ip || '',
|
||||
const dbConfigs = await prisma.hostConfig.findMany();
|
||||
return dbConfigs.map(h => ({
|
||||
name: h.name,
|
||||
ip: h.ip,
|
||||
sshUser: h.sshUser || 'bear',
|
||||
sshKeyPath: h.sshKeyPath?.replace(/^~/, homedir()),
|
||||
sshPort: h.sshPort || 22,
|
||||
})).filter((h: HostConfig) => h.name && h.ip);
|
||||
|
||||
console.error('Loaded hosts:', JSON.stringify(hosts));
|
||||
return hosts;
|
||||
} catch (e: any) {
|
||||
console.error('Config parse error:', e.message);
|
||||
hostType: h.hostType,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Error fetching host configs from DB:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function getHostConfigs(): HostConfig[] {
|
||||
const envHosts = parseEnvHosts();
|
||||
if (envHosts.length > 0) {
|
||||
return envHosts;
|
||||
export async function hasConfig(): Promise<boolean> {
|
||||
try {
|
||||
const count = await prisma.hostConfig.count();
|
||||
return count > 0;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parseJsonConfig();
|
||||
}
|
||||
|
||||
export function hasConfig(): boolean {
|
||||
return getHostConfigs().length > 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user