fix: base64 decoding
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
|||||||
recentActivity,
|
recentActivity,
|
||||||
hostAccess,
|
hostAccess,
|
||||||
userRoles,
|
userRoles,
|
||||||
|
sessionRecordings,
|
||||||
} from "../db/schema.js";
|
} from "../db/schema.js";
|
||||||
import {
|
import {
|
||||||
eq,
|
eq,
|
||||||
@@ -1069,60 +1070,40 @@ router.delete(
|
|||||||
|
|
||||||
const numericHostId = Number(hostId);
|
const numericHostId = Number(hostId);
|
||||||
|
|
||||||
|
// Delete all related data in correct order (child tables first)
|
||||||
await db
|
await db
|
||||||
.delete(fileManagerRecent)
|
.delete(fileManagerRecent)
|
||||||
.where(
|
.where(eq(fileManagerRecent.hostId, numericHostId));
|
||||||
and(
|
|
||||||
eq(fileManagerRecent.hostId, numericHostId),
|
|
||||||
eq(fileManagerRecent.userId, userId),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.delete(fileManagerPinned)
|
.delete(fileManagerPinned)
|
||||||
.where(
|
.where(eq(fileManagerPinned.hostId, numericHostId));
|
||||||
and(
|
|
||||||
eq(fileManagerPinned.hostId, numericHostId),
|
|
||||||
eq(fileManagerPinned.userId, userId),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.delete(fileManagerShortcuts)
|
.delete(fileManagerShortcuts)
|
||||||
.where(
|
.where(eq(fileManagerShortcuts.hostId, numericHostId));
|
||||||
and(
|
|
||||||
eq(fileManagerShortcuts.hostId, numericHostId),
|
|
||||||
eq(fileManagerShortcuts.userId, userId),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.delete(commandHistory)
|
.delete(commandHistory)
|
||||||
.where(
|
.where(eq(commandHistory.hostId, numericHostId));
|
||||||
and(
|
|
||||||
eq(commandHistory.hostId, numericHostId),
|
|
||||||
eq(commandHistory.userId, userId),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.delete(sshCredentialUsage)
|
.delete(sshCredentialUsage)
|
||||||
.where(
|
.where(eq(sshCredentialUsage.hostId, numericHostId));
|
||||||
and(
|
|
||||||
eq(sshCredentialUsage.hostId, numericHostId),
|
|
||||||
eq(sshCredentialUsage.userId, userId),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.delete(recentActivity)
|
.delete(recentActivity)
|
||||||
.where(
|
.where(eq(recentActivity.hostId, numericHostId));
|
||||||
and(
|
|
||||||
eq(recentActivity.hostId, numericHostId),
|
|
||||||
eq(recentActivity.userId, userId),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
// Delete RBAC host access entries
|
||||||
|
await db.delete(hostAccess).where(eq(hostAccess.hostId, numericHostId));
|
||||||
|
|
||||||
|
// Delete session recordings
|
||||||
|
await db
|
||||||
|
.delete(sessionRecordings)
|
||||||
|
.where(eq(sessionRecordings.hostId, numericHostId));
|
||||||
|
|
||||||
|
// Finally delete the host itself
|
||||||
await db
|
await db
|
||||||
.delete(sshData)
|
.delete(sshData)
|
||||||
.where(and(eq(sshData.id, numericHostId), eq(sshData.userId, userId)));
|
.where(and(eq(sshData.id, numericHostId), eq(sshData.userId, userId)));
|
||||||
@@ -1887,10 +1868,49 @@ router.delete(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hostIds = hostsToDelete.map((host) => host.id);
|
||||||
|
|
||||||
|
// Delete all related data for all hosts in the folder (child tables first)
|
||||||
|
if (hostIds.length > 0) {
|
||||||
|
await db
|
||||||
|
.delete(fileManagerRecent)
|
||||||
|
.where(inArray(fileManagerRecent.hostId, hostIds));
|
||||||
|
|
||||||
|
await db
|
||||||
|
.delete(fileManagerPinned)
|
||||||
|
.where(inArray(fileManagerPinned.hostId, hostIds));
|
||||||
|
|
||||||
|
await db
|
||||||
|
.delete(fileManagerShortcuts)
|
||||||
|
.where(inArray(fileManagerShortcuts.hostId, hostIds));
|
||||||
|
|
||||||
|
await db
|
||||||
|
.delete(commandHistory)
|
||||||
|
.where(inArray(commandHistory.hostId, hostIds));
|
||||||
|
|
||||||
|
await db
|
||||||
|
.delete(sshCredentialUsage)
|
||||||
|
.where(inArray(sshCredentialUsage.hostId, hostIds));
|
||||||
|
|
||||||
|
await db
|
||||||
|
.delete(recentActivity)
|
||||||
|
.where(inArray(recentActivity.hostId, hostIds));
|
||||||
|
|
||||||
|
// Delete RBAC host access entries
|
||||||
|
await db.delete(hostAccess).where(inArray(hostAccess.hostId, hostIds));
|
||||||
|
|
||||||
|
// Delete session recordings
|
||||||
|
await db
|
||||||
|
.delete(sessionRecordings)
|
||||||
|
.where(inArray(sessionRecordings.hostId, hostIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now delete the hosts themselves
|
||||||
await db
|
await db
|
||||||
.delete(sshData)
|
.delete(sshData)
|
||||||
.where(and(eq(sshData.userId, userId), eq(sshData.folder, folderName)));
|
.where(and(eq(sshData.userId, userId), eq(sshData.folder, folderName)));
|
||||||
|
|
||||||
|
// Finally delete the folder metadata
|
||||||
await db
|
await db
|
||||||
.delete(sshFolders)
|
.delete(sshFolders)
|
||||||
.where(
|
.where(
|
||||||
|
|||||||
@@ -824,12 +824,17 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => {
|
|||||||
useSocks5,
|
useSocks5,
|
||||||
socks5Host,
|
socks5Host,
|
||||||
socks5Port,
|
socks5Port,
|
||||||
hasSocks5ProxyChain: !!(socks5ProxyChain && (socks5ProxyChain as any).length > 0),
|
hasSocks5ProxyChain: !!(
|
||||||
|
socks5ProxyChain && (socks5ProxyChain as any).length > 0
|
||||||
|
),
|
||||||
proxyChainLength: socks5ProxyChain ? (socks5ProxyChain as any).length : 0,
|
proxyChainLength: socks5ProxyChain ? (socks5ProxyChain as any).length : 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check if SOCKS5 proxy is enabled (either single proxy or chain)
|
// Check if SOCKS5 proxy is enabled (either single proxy or chain)
|
||||||
if (useSocks5 && (socks5Host || (socks5ProxyChain && (socks5ProxyChain as any).length > 0))) {
|
if (
|
||||||
|
useSocks5 &&
|
||||||
|
(socks5Host || (socks5ProxyChain && (socks5ProxyChain as any).length > 0))
|
||||||
|
) {
|
||||||
fileLogger.info("SOCKS5 enabled for SFTP, creating connection", {
|
fileLogger.info("SOCKS5 enabled for SFTP, creating connection", {
|
||||||
operation: "sftp_socks5_enabled",
|
operation: "sftp_socks5_enabled",
|
||||||
sessionId,
|
sessionId,
|
||||||
@@ -839,18 +844,14 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const socks5Socket = await createSocks5Connection(
|
const socks5Socket = await createSocks5Connection(ip, port, {
|
||||||
ip,
|
useSocks5,
|
||||||
port,
|
socks5Host,
|
||||||
{
|
socks5Port,
|
||||||
useSocks5,
|
socks5Username,
|
||||||
socks5Host,
|
socks5Password,
|
||||||
socks5Port,
|
socks5ProxyChain: socks5ProxyChain as any,
|
||||||
socks5Username,
|
});
|
||||||
socks5Password,
|
|
||||||
socks5ProxyChain: socks5ProxyChain as any,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (socks5Socket) {
|
if (socks5Socket) {
|
||||||
fileLogger.info("SOCKS5 socket created for SFTP", {
|
fileLogger.info("SOCKS5 socket created for SFTP", {
|
||||||
@@ -1545,7 +1546,22 @@ app.post("/ssh/file_manager/ssh/writeFile", async (req, res) => {
|
|||||||
|
|
||||||
const tryFallbackMethod = () => {
|
const tryFallbackMethod = () => {
|
||||||
try {
|
try {
|
||||||
const base64Content = Buffer.from(content, "utf8").toString("base64");
|
let contentBuffer: Buffer;
|
||||||
|
if (typeof content === "string") {
|
||||||
|
try {
|
||||||
|
contentBuffer = Buffer.from(content, "base64");
|
||||||
|
if (contentBuffer.toString("base64") !== content) {
|
||||||
|
contentBuffer = Buffer.from(content, "utf8");
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
contentBuffer = Buffer.from(content, "utf8");
|
||||||
|
}
|
||||||
|
} else if (Buffer.isBuffer(content)) {
|
||||||
|
contentBuffer = content;
|
||||||
|
} else {
|
||||||
|
contentBuffer = Buffer.from(content);
|
||||||
|
}
|
||||||
|
const base64Content = contentBuffer.toString("base64");
|
||||||
const escapedPath = filePath.replace(/'/g, "'\"'\"'");
|
const escapedPath = filePath.replace(/'/g, "'\"'\"'");
|
||||||
|
|
||||||
const writeCommand = `echo '${base64Content}' | base64 -d > '${escapedPath}' && echo "SUCCESS"`;
|
const writeCommand = `echo '${base64Content}' | base64 -d > '${escapedPath}' && echo "SUCCESS"`;
|
||||||
@@ -1746,7 +1762,22 @@ app.post("/ssh/file_manager/ssh/uploadFile", async (req, res) => {
|
|||||||
|
|
||||||
const tryFallbackMethod = () => {
|
const tryFallbackMethod = () => {
|
||||||
try {
|
try {
|
||||||
const base64Content = Buffer.from(content, "utf8").toString("base64");
|
let contentBuffer: Buffer;
|
||||||
|
if (typeof content === "string") {
|
||||||
|
try {
|
||||||
|
contentBuffer = Buffer.from(content, "base64");
|
||||||
|
if (contentBuffer.toString("base64") !== content) {
|
||||||
|
contentBuffer = Buffer.from(content, "utf8");
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
contentBuffer = Buffer.from(content, "utf8");
|
||||||
|
}
|
||||||
|
} else if (Buffer.isBuffer(content)) {
|
||||||
|
contentBuffer = content;
|
||||||
|
} else {
|
||||||
|
contentBuffer = Buffer.from(content);
|
||||||
|
}
|
||||||
|
const base64Content = contentBuffer.toString("base64");
|
||||||
const chunkSize = 1000000;
|
const chunkSize = 1000000;
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user