feat(sqlite): support RC4 Legacy databases
This commit is contained in:
19 files changed
+187
-49
No files matched your search
@@ -297,6 +297,35 @@ describe("connectionStore save_password opt-out", () => {
|
||||
expect(store.getConfig("mysql-1")?.password).toBe("typed-pw");
|
||||
});
|
||||
|
||||
it("prompts and retries when an encrypted SQLite file is opened without a password", async () => {
|
||||
const connectDb = vi.fn().mockRejectedValueOnce(new Error("Selected file is not a valid SQLite database file.")).mockResolvedValueOnce("sqlite-1");
|
||||
installApiMocks({ connectDb });
|
||||
installPasswordPromptMock();
|
||||
requestPassword.mockResolvedValue({ password: "123456", rememberPassword: true });
|
||||
const { useConnectionStore } = await import("@/stores/connectionStore");
|
||||
const store = useConnectionStore();
|
||||
const connection = postgresConnection({
|
||||
id: "sqlite-1",
|
||||
name: "Encrypted SQLite",
|
||||
db_type: "sqlite",
|
||||
host: "/tmp/encrypted.db",
|
||||
port: 0,
|
||||
username: "",
|
||||
database: undefined,
|
||||
save_password: true,
|
||||
password: "",
|
||||
});
|
||||
store.connections = [connection];
|
||||
|
||||
await store.connect(connection);
|
||||
|
||||
expect(requestPassword).toHaveBeenCalledWith({ connectionId: "sqlite-1", connectionName: "Encrypted SQLite" });
|
||||
expect(connectDb).toHaveBeenCalledTimes(2);
|
||||
expect(connectDb).toHaveBeenNthCalledWith(1, expect.objectContaining({ password: "" }), expect.any(Number));
|
||||
expect(connectDb).toHaveBeenNthCalledWith(2, expect.objectContaining({ password: "123456" }), expect.any(Number));
|
||||
expect(store.getConfig("sqlite-1")?.password).toBe("123456");
|
||||
});
|
||||
|
||||
it("does not persist a recovered password after the connection config changes", async () => {
|
||||
const connected = deferred<string>();
|
||||
const connectDb = vi
|
||||
|
||||
@@ -141,7 +141,7 @@ import { REDIS_SCAN_PAGE_SIZE_DEFAULT } from "@/lib/redis/redisKeyPattern";
|
||||
import { normalizeRedisDatabaseAliases, redisDatabaseAlias, redisDatabaseLabel } from "@/lib/redis/redisDatabaseAlias";
|
||||
import { normalizeRedisKeyTemplates } from "@/lib/redis/redisKeyTemplates";
|
||||
import { appendAgentDriverUpdateHint, hasAgentDriverUpdate, hasInstalledAgentVersion, type AgentDriverInstallState } from "@/lib/connection/agentDriverInstallHint";
|
||||
import { appendConnectionErrorHints, isMysqlMissingPasswordFailure } from "@/lib/connection/connectionErrorHints";
|
||||
import { appendConnectionErrorHints, isMysqlMissingPasswordFailure, isSqliteMissingEncryptionPasswordFailure } from "@/lib/connection/connectionErrorHints";
|
||||
import { connectionNeedsPasswordPrompt } from "@/lib/connection/connectionPassword";
|
||||
import { appendVisibleDatabaseSelection } from "@/lib/connection/connectionVisibleDatabases";
|
||||
import { buildXuguTypeMemberNodes, isXuguTypeMemberContainer } from "@/lib/sidebar/xuguTypeMembers";
|
||||
@@ -3630,12 +3630,13 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
rebuildTreeNodes();
|
||||
}
|
||||
|
||||
async function connectDbWithMissingPasswordRetry(config: ConnectionConfig, localAttempt: number): Promise<{ config: ConnectionConfig; id: string; rememberPassword: boolean }> {
|
||||
async function connectDbWithPasswordRetry(config: ConnectionConfig, localAttempt: number): Promise<{ config: ConnectionConfig; id: string; rememberPassword: boolean }> {
|
||||
try {
|
||||
const id = await withConnectionAttemptTimeout(api.connectDb(config, localAttempt), config);
|
||||
return { config, id, rememberPassword: false };
|
||||
} catch (error) {
|
||||
if (!isMysqlMissingPasswordFailure(config, connectionErrorMessage(error))) throw error;
|
||||
const message = connectionErrorMessage(error);
|
||||
if (!isMysqlMissingPasswordFailure(config, message) && !isSqliteMissingEncryptionPasswordFailure(config, message)) throw error;
|
||||
const prompted = await ensureConnectionPassword(config, true);
|
||||
config = prompted.config;
|
||||
ensureLocalConnectionAttemptActive(config.id, localAttempt);
|
||||
@@ -3661,7 +3662,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
await ensureSqlServerLegacyCompatibilityComponentInstalled(config);
|
||||
}
|
||||
ensureLocalConnectionAttemptActive(config.id, localAttempt);
|
||||
const connection = await connectDbWithMissingPasswordRetry(config, localAttempt);
|
||||
const connection = await connectDbWithPasswordRetry(config, localAttempt);
|
||||
config = connection.config;
|
||||
rememberPassword ||= connection.rememberPassword;
|
||||
const id = connection.id;
|
||||
@@ -3904,7 +3905,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
await ensureSqlServerLegacyCompatibilityComponentInstalled(config);
|
||||
}
|
||||
ensureLocalConnectionAttemptActive(connectionId, localAttempt);
|
||||
const connection = await connectDbWithMissingPasswordRetry(config, localAttempt);
|
||||
const connection = await connectDbWithPasswordRetry(config, localAttempt);
|
||||
config = connection.config;
|
||||
rememberPassword ||= connection.rememberPassword;
|
||||
const id = connection.id;
|
||||
|
||||
Reference in new issue
Block a user