v1.7.2 (#364)
* Feature request: Add delete confirmation dialog to file manager (#344) * Feature request: Add delete confirmation dialog to file manager - Added confirmation dialog before deleting files/folders - Users must confirm deletion with a warning message - Works for both Delete key and right-click delete - Shows different messages for single file, folder, or multiple items - Includes permanent deletion warning - Follows existing design patterns using confirmWithToast * Adds confirmation for deletion of items including folders Updates the file deletion confirmation logic to distinguish between deleting multiple items with or without folders. Introduces a new translation string for a clearer user prompt when folders and their contents are included in the deletion. Improves clarity and reduces user error when performing bulk deletions. * feat: Add Chinese translations for delete confirmation messages * Adds camelCase support for encrypted field mappings (#342) Extends encrypted field mappings to include camelCase variants to support consistency and compatibility with different naming conventions. Updates reverse mappings for Drizzle ORM to allow conversion between camelCase and snake_case field names. Improves integration with systems using mixed naming styles. * Run code cleanup, add sidebar persistence, fix OIDC credentials, force SSH password. * Fix snake case mismatching * Add real client IP * Fix OIDC credential persistence issue The issue was that OIDC users were getting a new random Data Encryption Key (DEK) on every login, which made previously encrypted credentials inaccessible. Changes: - Modified setupOIDCUserEncryption() to persist the DEK encrypted with a system-derived key - Updated authenticateOIDCUser() to properly retrieve and use the persisted DEK - Ensured OIDC users now have the same encryption persistence as password-based users This fix ensures that credentials created by OIDC users remain accessible across multiple login sessions. * Fix race condition and remove redundant kekSalt for OIDC users Critical fixes: 1. Race Condition Mitigation: - Added read-after-write verification in setupOIDCUserEncryption() - Ensures session uses the DEK that's actually in the database - Prevents data loss when concurrent logins occur for new OIDC users - If race is detected, discards generated DEK and uses stored one 2. Remove Redundant kekSalt Logic: - Removed unnecessary kekSalt generation and checks for OIDC users - kekSalt is not used in OIDC key derivation (uses userId as salt) - Reduces database operations from 4 to 2 per authentication - Simplifies code and removes potential confusion 3. Improved Error Handling: - systemKey cleanup moved to finally block - Ensures sensitive key material is always cleared from memory These changes ensure data consistency and prevent potential data loss in high-concurrency scenarios. * Cleanup OIDC pr and run prettier --------- Co-authored-by: Ved Prakash <54140516+thorved@users.noreply.github.com>
This commit was merged in pull request #364.
This commit is contained in:
@@ -91,7 +91,7 @@ router.get("/db/host/internal", async (req: Request, res: Response) => {
|
||||
username: host.username,
|
||||
password: host.autostartPassword,
|
||||
key: host.autostartKey,
|
||||
keyPassword: host.autostartKeyPassword,
|
||||
key_password: host.autostartKeyPassword,
|
||||
autostartPassword: host.autostartPassword,
|
||||
autostartKey: host.autostartKey,
|
||||
autostartKeyPassword: host.autostartKeyPassword,
|
||||
@@ -151,7 +151,7 @@ router.get("/db/host/internal/all", async (req: Request, res: Response) => {
|
||||
username: host.username,
|
||||
password: host.autostartPassword || host.password,
|
||||
key: host.autostartKey || host.key,
|
||||
keyPassword: host.autostartKeyPassword || host.keyPassword,
|
||||
key_password: host.autostartKeyPassword || host.key_password,
|
||||
autostartPassword: host.autostartPassword,
|
||||
autostartKey: host.autostartKey,
|
||||
autostartKeyPassword: host.autostartKeyPassword,
|
||||
@@ -226,7 +226,7 @@ router.post(
|
||||
authType,
|
||||
credentialId,
|
||||
key,
|
||||
keyPassword,
|
||||
key_password,
|
||||
keyType,
|
||||
pin,
|
||||
enableTerminal,
|
||||
@@ -274,17 +274,17 @@ router.post(
|
||||
if (effectiveAuthType === "password") {
|
||||
sshDataObj.password = password || null;
|
||||
sshDataObj.key = null;
|
||||
sshDataObj.keyPassword = null;
|
||||
sshDataObj.key_password = null;
|
||||
sshDataObj.keyType = null;
|
||||
} else if (effectiveAuthType === "key") {
|
||||
sshDataObj.key = key || null;
|
||||
sshDataObj.keyPassword = keyPassword || null;
|
||||
sshDataObj.key_password = key_password || null;
|
||||
sshDataObj.keyType = keyType;
|
||||
sshDataObj.password = null;
|
||||
} else {
|
||||
sshDataObj.password = null;
|
||||
sshDataObj.key = null;
|
||||
sshDataObj.keyPassword = null;
|
||||
sshDataObj.key_password = null;
|
||||
sshDataObj.keyType = null;
|
||||
}
|
||||
|
||||
@@ -407,7 +407,7 @@ router.put(
|
||||
authType,
|
||||
credentialId,
|
||||
key,
|
||||
keyPassword,
|
||||
key_password,
|
||||
keyType,
|
||||
pin,
|
||||
enableTerminal,
|
||||
@@ -458,14 +458,14 @@ router.put(
|
||||
sshDataObj.password = password;
|
||||
}
|
||||
sshDataObj.key = null;
|
||||
sshDataObj.keyPassword = null;
|
||||
sshDataObj.key_password = null;
|
||||
sshDataObj.keyType = null;
|
||||
} else if (effectiveAuthType === "key") {
|
||||
if (key) {
|
||||
sshDataObj.key = key;
|
||||
}
|
||||
if (keyPassword !== undefined) {
|
||||
sshDataObj.keyPassword = keyPassword || null;
|
||||
if (key_password !== undefined) {
|
||||
sshDataObj.key_password = key_password || null;
|
||||
}
|
||||
if (keyType) {
|
||||
sshDataObj.keyType = keyType;
|
||||
@@ -474,7 +474,7 @@ router.put(
|
||||
} else {
|
||||
sshDataObj.password = null;
|
||||
sshDataObj.key = null;
|
||||
sshDataObj.keyPassword = null;
|
||||
sshDataObj.key_password = null;
|
||||
sshDataObj.keyType = null;
|
||||
}
|
||||
|
||||
@@ -711,7 +711,7 @@ router.get(
|
||||
authType: resolvedHost.authType,
|
||||
password: resolvedHost.password || null,
|
||||
key: resolvedHost.key || null,
|
||||
keyPassword: resolvedHost.keyPassword || null,
|
||||
key_password: resolvedHost.key_password || null,
|
||||
keyType: resolvedHost.keyType || null,
|
||||
folder: resolvedHost.folder,
|
||||
tags:
|
||||
@@ -1234,7 +1234,7 @@ async function resolveHostCredentials(host: any): Promise<any> {
|
||||
authType: credential.auth_type || credential.authType,
|
||||
password: credential.password,
|
||||
key: credential.key,
|
||||
keyPassword: credential.key_password || credential.keyPassword,
|
||||
key_password: credential.key_password || credential.key_password,
|
||||
keyType: credential.key_type || credential.keyType,
|
||||
};
|
||||
}
|
||||
@@ -1404,8 +1404,8 @@ router.post(
|
||||
credentialId:
|
||||
hostData.authType === "credential" ? hostData.credentialId : null,
|
||||
key: hostData.authType === "key" ? hostData.key : null,
|
||||
keyPassword:
|
||||
hostData.authType === "key" ? hostData.keyPassword : null,
|
||||
key_password:
|
||||
hostData.authType === "key" ? hostData.key_password : null,
|
||||
keyType:
|
||||
hostData.authType === "key" ? hostData.keyType || "auto" : null,
|
||||
pin: hostData.pin || false,
|
||||
@@ -1540,7 +1540,7 @@ router.post(
|
||||
...tunnel,
|
||||
endpointPassword: decryptedEndpoint.password || null,
|
||||
endpointKey: decryptedEndpoint.key || null,
|
||||
endpointKeyPassword: decryptedEndpoint.keyPassword || null,
|
||||
endpointKeyPassword: decryptedEndpoint.key_password || null,
|
||||
endpointAuthType: endpointHost.authType,
|
||||
};
|
||||
}
|
||||
@@ -1563,7 +1563,7 @@ router.post(
|
||||
.set({
|
||||
autostartPassword: decryptedConfig.password || null,
|
||||
autostartKey: decryptedConfig.key || null,
|
||||
autostartKeyPassword: decryptedConfig.keyPassword || null,
|
||||
autostartKeyPassword: decryptedConfig.key_password || null,
|
||||
tunnelConnections: updatedTunnelConnections,
|
||||
})
|
||||
.where(eq(sshData.id, sshConfigId));
|
||||
|
||||
Reference in New Issue
Block a user