fix: General bug fixes/small feature improvements

This commit is contained in:
LukeGus
2025-11-10 16:23:46 -06:00
parent 966758ecf8
commit 7e8105a938
31 changed files with 1774 additions and 634 deletions

View File

@@ -235,6 +235,7 @@ router.post(
enableFileManager,
defaultPath,
tunnelConnections,
jumpHosts,
statsConfig,
terminalConfig,
forceKeyboardInteractive,
@@ -271,6 +272,7 @@ router.post(
tunnelConnections: Array.isArray(tunnelConnections)
? JSON.stringify(tunnelConnections)
: null,
jumpHosts: Array.isArray(jumpHosts) ? JSON.stringify(jumpHosts) : null,
enableFileManager: enableFileManager ? 1 : 0,
defaultPath: defaultPath || null,
statsConfig: statsConfig ? JSON.stringify(statsConfig) : null,
@@ -329,6 +331,9 @@ router.post(
tunnelConnections: createdHost.tunnelConnections
? JSON.parse(createdHost.tunnelConnections as string)
: [],
jumpHosts: createdHost.jumpHosts
? JSON.parse(createdHost.jumpHosts as string)
: [],
enableFileManager: !!createdHost.enableFileManager,
statsConfig: createdHost.statsConfig
? JSON.parse(createdHost.statsConfig as string)
@@ -370,6 +375,7 @@ router.post(
router.put(
"/db/host/:id",
authenticateJWT,
requireDataAccess,
upload.single("key"),
async (req: Request, res: Response) => {
const hostId = req.params.id;
@@ -425,6 +431,7 @@ router.put(
enableFileManager,
defaultPath,
tunnelConnections,
jumpHosts,
statsConfig,
terminalConfig,
forceKeyboardInteractive,
@@ -462,6 +469,7 @@ router.put(
tunnelConnections: Array.isArray(tunnelConnections)
? JSON.stringify(tunnelConnections)
: null,
jumpHosts: Array.isArray(jumpHosts) ? JSON.stringify(jumpHosts) : null,
enableFileManager: enableFileManager ? 1 : 0,
defaultPath: defaultPath || null,
statsConfig: statsConfig ? JSON.stringify(statsConfig) : null,
@@ -538,6 +546,9 @@ router.put(
tunnelConnections: updatedHost.tunnelConnections
? JSON.parse(updatedHost.tunnelConnections as string)
: [],
jumpHosts: updatedHost.jumpHosts
? JSON.parse(updatedHost.jumpHosts as string)
: [],
enableFileManager: !!updatedHost.enableFileManager,
statsConfig: updatedHost.statsConfig
? JSON.parse(updatedHost.statsConfig as string)
@@ -577,67 +588,74 @@ router.put(
// Route: Get SSH data for the authenticated user (requires JWT)
// GET /ssh/host
router.get("/db/host", authenticateJWT, async (req: Request, res: Response) => {
const userId = (req as AuthenticatedRequest).userId;
if (!isNonEmptyString(userId)) {
sshLogger.warn("Invalid userId for SSH data fetch", {
operation: "host_fetch",
userId,
});
return res.status(400).json({ error: "Invalid userId" });
}
try {
const data = await SimpleDBOps.select(
db.select().from(sshData).where(eq(sshData.userId, userId)),
"ssh_data",
userId,
);
router.get(
"/db/host",
authenticateJWT,
requireDataAccess,
async (req: Request, res: Response) => {
const userId = (req as AuthenticatedRequest).userId;
if (!isNonEmptyString(userId)) {
sshLogger.warn("Invalid userId for SSH data fetch", {
operation: "host_fetch",
userId,
});
return res.status(400).json({ error: "Invalid userId" });
}
try {
const data = await SimpleDBOps.select(
db.select().from(sshData).where(eq(sshData.userId, userId)),
"ssh_data",
userId,
);
const result = await Promise.all(
data.map(async (row: Record<string, unknown>) => {
const baseHost = {
...row,
tags:
typeof row.tags === "string"
? row.tags
? row.tags.split(",").filter(Boolean)
: []
const result = await Promise.all(
data.map(async (row: Record<string, unknown>) => {
const baseHost = {
...row,
tags:
typeof row.tags === "string"
? row.tags
? row.tags.split(",").filter(Boolean)
: []
: [],
pin: !!row.pin,
enableTerminal: !!row.enableTerminal,
enableTunnel: !!row.enableTunnel,
tunnelConnections: row.tunnelConnections
? JSON.parse(row.tunnelConnections as string)
: [],
pin: !!row.pin,
enableTerminal: !!row.enableTerminal,
enableTunnel: !!row.enableTunnel,
tunnelConnections: row.tunnelConnections
? JSON.parse(row.tunnelConnections as string)
: [],
enableFileManager: !!row.enableFileManager,
statsConfig: row.statsConfig
? JSON.parse(row.statsConfig as string)
: undefined,
terminalConfig: row.terminalConfig
? JSON.parse(row.terminalConfig as string)
: undefined,
forceKeyboardInteractive: row.forceKeyboardInteractive === "true",
};
jumpHosts: row.jumpHosts ? JSON.parse(row.jumpHosts as string) : [],
enableFileManager: !!row.enableFileManager,
statsConfig: row.statsConfig
? JSON.parse(row.statsConfig as string)
: undefined,
terminalConfig: row.terminalConfig
? JSON.parse(row.terminalConfig as string)
: undefined,
forceKeyboardInteractive: row.forceKeyboardInteractive === "true",
};
return (await resolveHostCredentials(baseHost)) || baseHost;
}),
);
return (await resolveHostCredentials(baseHost)) || baseHost;
}),
);
res.json(result);
} catch (err) {
sshLogger.error("Failed to fetch SSH hosts from database", err, {
operation: "host_fetch",
userId,
});
res.status(500).json({ error: "Failed to fetch SSH data" });
}
});
res.json(result);
} catch (err) {
sshLogger.error("Failed to fetch SSH hosts from database", err, {
operation: "host_fetch",
userId,
});
res.status(500).json({ error: "Failed to fetch SSH data" });
}
},
);
// Route: Get SSH host by ID (requires JWT)
// GET /ssh/host/:id
router.get(
"/db/host/:id",
authenticateJWT,
requireDataAccess,
async (req: Request, res: Response) => {
const hostId = req.params.id;
const userId = (req as AuthenticatedRequest).userId;
@@ -813,42 +831,6 @@ router.delete(
const numericHostId = Number(hostId);
await db
.delete(fileManagerRecent)
.where(
and(
eq(fileManagerRecent.userId, userId),
eq(fileManagerRecent.hostId, numericHostId),
),
);
await db
.delete(fileManagerPinned)
.where(
and(
eq(fileManagerPinned.userId, userId),
eq(fileManagerPinned.hostId, numericHostId),
),
);
await db
.delete(fileManagerShortcuts)
.where(
and(
eq(fileManagerShortcuts.userId, userId),
eq(fileManagerShortcuts.hostId, numericHostId),
),
);
await db
.delete(sshCredentialUsage)
.where(
and(
eq(sshCredentialUsage.userId, userId),
eq(sshCredentialUsage.hostId, numericHostId),
),
);
await db
.delete(sshData)
.where(and(eq(sshData.id, numericHostId), eq(sshData.userId, userId)));