Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 (api) fix performing api operations for local e2e encrypted files #2698

Merged
merged 3 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 41 additions & 24 deletions packages/loot-core/src/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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');
Expand All @@ -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 () {
Expand Down
3 changes: 3 additions & 0 deletions packages/loot-core/src/server/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions packages/loot-core/src/types/budget.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export type Budget = {
id: string;
cloudFileId?: string;
encryptKeyId?: string;
groupId?: string;
name: string;
};
6 changes: 6 additions & 0 deletions upcoming-release-notes/2698.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Bugfix
authors: [MatissJanis]
---

Fix API remote-server sync for budget files that are e2e encrypted.
Loading