From 2d1abf477c26e6f3722d715b9186b1752652da24 Mon Sep 17 00:00:00 2001 From: Matiss Janis Aboltins <matiss@mja.lv> Date: Wed, 15 May 2024 17:10:32 +0100 Subject: [PATCH] :bug: (api) fix performing api operations for local e2e encrypted files (#2698) --- packages/loot-core/src/server/api.ts | 65 +++++++++++++++--------- packages/loot-core/src/server/main.ts | 3 ++ packages/loot-core/src/types/budget.d.ts | 1 + upcoming-release-notes/2698.md | 6 +++ 4 files changed, 51 insertions(+), 24 deletions(-) create mode 100644 upcoming-release-notes/2698.md diff --git a/packages/loot-core/src/server/api.ts b/packages/loot-core/src/server/api.ts index d66c5071d..93457027f 100644 --- a/packages/loot-core/src/server/api.ts +++ b/packages/loot-core/src/server/api.ts @@ -27,6 +27,7 @@ import { } from './api-models'; import { runQuery as aqlQuery } from './aql'; import * as cloudStorage from './cloud-storage'; +import { type RemoteFile } from './cloud-storage'; import * as db from './db'; import { APIError } from './errors'; import { runMutator } from './mutators'; @@ -164,16 +165,12 @@ handlers['api/download-budget'] = async function ({ syncId, password }) { await handlers['close-budget'](); } - const localBudget = (await handlers['get-budgets']()).find( - b => b.groupId === syncId, - ); - if (localBudget) { - await handlers['load-budget']({ id: localBudget.id }); - const result = await handlers['sync-budget'](); - if (result.error) { - throw new Error(getSyncError(result.error, localBudget.id)); - } - } else { + const budgets = await handlers['get-budgets'](); + const localBudget = budgets.find(b => b.groupId === syncId); + let remoteBudget: RemoteFile; + + // Load a remote file if we could not find the file locally + if (!localBudget) { const files = await handlers['get-remote-files'](); if (!files) { throw new Error('Could not get remote files'); @@ -184,28 +181,48 @@ handlers['api/download-budget'] = async function ({ syncId, password }) { `Budget “${syncId}†not found. Check the sync id of your budget in the Advanced section of the settings page.`, ); } - if (file.encryptKeyId && !password) { + + remoteBudget = file; + } + + const activeFile = remoteBudget ? remoteBudget : localBudget; + + // Set the e2e encryption keys + if (activeFile.encryptKeyId) { + if (!password) { throw new Error( - `File ${file.name} is encrypted. Please provide a password.`, + `File ${activeFile.name} is encrypted. Please provide a password.`, ); } - if (password) { - const result = await handlers['key-test']({ - fileId: file.fileId, - password, - }); - if (result.error) { - throw new Error(getTestKeyError(result.error)); - } + + const result = await handlers['key-test']({ + fileId: remoteBudget ? remoteBudget.fileId : localBudget.cloudFileId, + password, + }); + if (result.error) { + throw new Error(getTestKeyError(result.error)); } + } - const result = await handlers['download-budget']({ fileId: file.fileId }); + // Sync the local budget file + if (localBudget) { + await handlers['load-budget']({ id: localBudget.id }); + const result = await handlers['sync-budget'](); if (result.error) { - console.log('Full error details', result.error); - throw new Error(getDownloadError(result.error)); + throw new Error(getSyncError(result.error, localBudget.id)); } - await handlers['load-budget']({ id: result.id }); + return; + } + + // Download the remote file (no need to perform a sync as the file will already be up-to-date) + const result = await handlers['download-budget']({ + fileId: remoteBudget.fileId, + }); + if (result.error) { + console.log('Full error details', result.error); + throw new Error(getDownloadError(result.error)); } + await handlers['load-budget']({ id: result.id }); }; handlers['api/sync'] = async function () { diff --git a/packages/loot-core/src/server/main.ts b/packages/loot-core/src/server/main.ts index 01ec57e50..5b0ee4f93 100644 --- a/packages/loot-core/src/server/main.ts +++ b/packages/loot-core/src/server/main.ts @@ -1592,6 +1592,9 @@ handlers['get-budgets'] = async function () { return { id: name, ...(prefs.cloudFileId ? { cloudFileId: prefs.cloudFileId } : {}), + ...(prefs.encryptKeyId + ? { encryptKeyId: prefs.encryptKeyId } + : {}), ...(prefs.groupId ? { groupId: prefs.groupId } : {}), name: prefs.budgetName || '(no name)', } satisfies Budget; diff --git a/packages/loot-core/src/types/budget.d.ts b/packages/loot-core/src/types/budget.d.ts index f77d9acf5..5d8e394fd 100644 --- a/packages/loot-core/src/types/budget.d.ts +++ b/packages/loot-core/src/types/budget.d.ts @@ -1,6 +1,7 @@ export type Budget = { id: string; cloudFileId?: string; + encryptKeyId?: string; groupId?: string; name: string; }; diff --git a/upcoming-release-notes/2698.md b/upcoming-release-notes/2698.md new file mode 100644 index 000000000..38b91b665 --- /dev/null +++ b/upcoming-release-notes/2698.md @@ -0,0 +1,6 @@ +--- +category: Bugfix +authors: [MatissJanis] +--- + +Fix API remote-server sync for budget files that are e2e encrypted. -- GitLab