mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-12 19:57:37 +00:00
refactor: pivot from ssh proxy to distributed api model
- Delete SSHFileAdapter, IFileAdapter, LocalFileAdapter (SSH/SFTP stack)
- Remove ssh2, ssh2-sftp-client dependencies; add http-proxy-middleware, http-proxy
- NodeRegistry: remote nodes no longer use Dockerode TCP; new getProxyTarget() returns {apiUrl, apiToken}
- NodeRegistry.testConnection: remote nodes use HTTP GET /api/auth/check instead of docker.info()
- DatabaseService: Node interface swaps SSH/TLS fields for api_url + api_token; legacy columns preserved for DB compat
- FileSystemService: reverted to clean local-only fs.promises; adapter pattern fully removed
- ComposeService: executeRemote() and SSH log streaming deleted; local-only execution remains
- index.ts: add /api/auth/generate-node-token endpoint (long-lived JWT, scope:node_proxy)
- index.ts: authMiddleware now accepts Bearer token in addition to cookie (Sencho-to-Sencho auth)
- index.ts: remote HTTP proxy middleware intercepts all /api/ requests for remote nodes, strips x-node-id, injects Authorization header, proxies to api_url
- index.ts: WS upgrade handler proxies WebSocket connections for remote nodes via http-proxy wsProxyServer
- NodeManager.tsx: form reduced to Name, API URL, API Token; Generate Node Token button added inline
- NodeContext.tsx: Node interface updated to api_url/api_token
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,19 +5,12 @@ export interface Node {
|
||||
id: number;
|
||||
name: string;
|
||||
type: 'local' | 'remote';
|
||||
host: string;
|
||||
port: number;
|
||||
ssh_port: number;
|
||||
compose_dir: string;
|
||||
is_default: boolean;
|
||||
status: 'online' | 'offline' | 'unknown';
|
||||
created_at: number;
|
||||
ssh_user?: string;
|
||||
ssh_password?: string;
|
||||
ssh_key?: string;
|
||||
tls_ca?: string;
|
||||
tls_cert?: string;
|
||||
tls_key?: string;
|
||||
api_url?: string;
|
||||
api_token?: string;
|
||||
}
|
||||
|
||||
interface NodeContextType {
|
||||
@@ -42,7 +35,6 @@ export function NodeProvider({ children }: { children: React.ReactNode }) {
|
||||
const data = await res.json();
|
||||
setNodes(data);
|
||||
|
||||
// If no active node is set, select the default node
|
||||
if (!activeNode) {
|
||||
const defaultNode = data.find((n: Node) => n.is_default);
|
||||
if (defaultNode) {
|
||||
@@ -51,12 +43,10 @@ export function NodeProvider({ children }: { children: React.ReactNode }) {
|
||||
setActiveNodeState(data[0]);
|
||||
}
|
||||
} else {
|
||||
// Refresh the active node's data in case its status changed
|
||||
const updatedActive = data.find((n: Node) => n.id === activeNode.id);
|
||||
if (updatedActive) {
|
||||
setActiveNodeState(updatedActive);
|
||||
} else {
|
||||
// The active node was deleted! Fallback to default
|
||||
const defaultNode = data.find((n: Node) => n.is_default);
|
||||
if (defaultNode) {
|
||||
setActiveNodeState(defaultNode);
|
||||
|
||||
Reference in New Issue
Block a user