wallet-core: implement exportDb API call

This commit is contained in:
Florian Dold 2021-12-01 18:16:40 +01:00
parent b0c2a73146
commit 668ffa7302
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
4 changed files with 57 additions and 5 deletions

View File

@ -41,6 +41,7 @@ import {
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { RetryInfo } from "./util/retries.js"; import { RetryInfo } from "./util/retries.js";
import { PayCoinSelection } from "./util/coinSelection.js"; import { PayCoinSelection } from "./util/coinSelection.js";
import { Event, IDBDatabase } from "@gnu-taler/idb-bridge";
/** /**
* Name of the Taler database. This is effectively the major * Name of the Taler database. This is effectively the major
@ -1773,3 +1774,33 @@ export const walletMetadataStore = {
{}, {},
), ),
}; };
export function exportDb(db: IDBDatabase): Promise<any> {
const dump = {
name: db.name,
stores: {} as { [s: string]: any },
version: db.version,
};
return new Promise((resolve, reject) => {
const tx = db.transaction(Array.from(db.objectStoreNames));
tx.addEventListener("complete", () => {
resolve(dump);
});
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < db.objectStoreNames.length; i++) {
const name = db.objectStoreNames[i];
const storeDump = {} as { [s: string]: any };
dump.stores[name] = storeDump;
tx.objectStore(name)
.openCursor()
.addEventListener("success", (e: Event) => {
const cursor = (e.target as any).result;
if (cursor) {
storeDump[cursor.key] = cursor.value;
cursor.continue();
}
});
}
});
}

View File

@ -488,9 +488,12 @@ function makeReadContext(
return new ResultStream<any>(req); return new ResultStream<any>(req);
}, },
getAll(query, count) { getAll(query, count) {
const req = tx.objectStore(storeName).index(indexName).getAll(query, count); const req = tx
.objectStore(storeName)
.index(indexName)
.getAll(query, count);
return requestToPromise(req); return requestToPromise(req);
} },
}; };
} }
ctx[storeAlias] = { ctx[storeAlias] = {
@ -534,9 +537,12 @@ function makeWriteContext(
return new ResultStream<any>(req); return new ResultStream<any>(req);
}, },
getAll(query, count) { getAll(query, count) {
const req = tx.objectStore(storeName).index(indexName).getAll(query, count); const req = tx
.objectStore(storeName)
.index(indexName)
.getAll(query, count);
return requestToPromise(req); return requestToPromise(req);
} },
}; };
} }
ctx[storeAlias] = { ctx[storeAlias] = {
@ -574,6 +580,10 @@ function makeWriteContext(
export class DbAccess<StoreMap> { export class DbAccess<StoreMap> {
constructor(private db: IDBDatabase, private stores: StoreMap) {} constructor(private db: IDBDatabase, private stores: StoreMap) {}
idbHandle(): IDBDatabase {
return this.db;
}
mktx< mktx<
PickerType extends (x: StoreMap) => unknown, PickerType extends (x: StoreMap) => unknown,
BoundStores extends GetPickerType<PickerType, StoreMap> BoundStores extends GetPickerType<PickerType, StoreMap>

View File

@ -115,6 +115,7 @@ export enum WalletApiOperation {
SetWalletDeviceId = "setWalletDeviceId", SetWalletDeviceId = "setWalletDeviceId",
ExportBackupPlain = "exportBackupPlain", ExportBackupPlain = "exportBackupPlain",
WithdrawFakebank = "withdrawFakebank", WithdrawFakebank = "withdrawFakebank",
ExportDb = "exportDb",
} }
export type WalletOperations = { export type WalletOperations = {
@ -270,6 +271,10 @@ export type WalletOperations = {
request: TestPayArgs; request: TestPayArgs;
response: {}; response: {};
}; };
[WalletApiOperation.ExportDb]: {
request: {};
response: any;
};
}; };
export type RequestType< export type RequestType<

View File

@ -123,6 +123,7 @@ import {
import { import {
AuditorTrustRecord, AuditorTrustRecord,
CoinSourceType, CoinSourceType,
exportDb,
ReserveRecordStatus, ReserveRecordStatus,
WalletStoresV1, WalletStoresV1,
} from "./db.js"; } from "./db.js";
@ -183,6 +184,7 @@ import {
readSuccessResponseJsonOrThrow, readSuccessResponseJsonOrThrow,
} from "./util/http.js"; } from "./util/http.js";
import { getMerchantInfo } from "./operations/merchants.js"; import { getMerchantInfo } from "./operations/merchants.js";
import { Event, IDBDatabase } from "@gnu-taler/idb-bridge";
const builtinAuditors: AuditorTrustRecord[] = [ const builtinAuditors: AuditorTrustRecord[] = [
{ {
@ -953,6 +955,10 @@ async function dispatchRequestInternal(
logger.info(`started fakebank withdrawal: ${j2s(fbResp)}`); logger.info(`started fakebank withdrawal: ${j2s(fbResp)}`);
return {}; return {};
} }
case "exportDb": {
const dbDump = await exportDb(ws.db.idbHandle());
return dbDump;
}
} }
throw OperationFailedError.fromCode( throw OperationFailedError.fromCode(
TalerErrorCode.WALLET_CORE_API_OPERATION_UNKNOWN, TalerErrorCode.WALLET_CORE_API_OPERATION_UNKNOWN,
@ -997,7 +1003,7 @@ export async function handleCoreApiRequest(
try { try {
logger.error("Caught unexpected exception:"); logger.error("Caught unexpected exception:");
logger.error(e.stack); logger.error(e.stack);
} catch (e) { } } catch (e) {}
return { return {
type: "error", type: "error",
operation, operation,