wallet-core: make primitive backup import work

This commit is contained in:
Florian Dold 2023-08-30 17:18:18 +02:00
parent 183aed4ba5
commit 0a4782a0da
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
2 changed files with 29 additions and 62 deletions

View File

@ -883,6 +883,16 @@ backupCli.subcommand("exportDb", "export-db").action(async (args) => {
}); });
}); });
backupCli.subcommand("importDb", "import-db").action(async (args) => {
await withWallet(args, async (wallet) => {
const dumpRaw = await read(process.stdin);
const dump = JSON.parse(dumpRaw);
await wallet.client.call(WalletApiOperation.ImportDb, {
dump,
});
});
});
const depositCli = walletCli.subcommand("depositArgs", "deposit", { const depositCli = walletCli.subcommand("depositArgs", "deposit", {
help: "Subcommands for depositing money to payto:// accounts", help: "Subcommands for depositing money to payto:// accounts",
}); });
@ -1600,6 +1610,3 @@ async function read(stream: NodeJS.ReadStream) {
export function main() { export function main() {
walletCli.run(); walletCli.run();
} }
function classifyTalerUri(uri: string) {
throw new Error("Function not implemented.");
}

View File

@ -2890,15 +2890,9 @@ export async function exportDb(idb: IDBFactory): Promise<DbDump> {
return dbDump; return dbDump;
} }
export interface DatabaseDump {
name: string;
stores: { [s: string]: any };
version: string;
}
async function recoverFromDump( async function recoverFromDump(
db: IDBDatabase, db: IDBDatabase,
dump: DatabaseDump, dbDump: DbDumpDatabase,
): Promise<void> { ): Promise<void> {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite"); const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite");
@ -2907,67 +2901,33 @@ async function recoverFromDump(
}); });
for (let i = 0; i < db.objectStoreNames.length; i++) { for (let i = 0; i < db.objectStoreNames.length; i++) {
const name = db.objectStoreNames[i]; const name = db.objectStoreNames[i];
const storeDump = dump.stores[name]; const storeDump = dbDump.stores[name];
if (!storeDump) continue; if (!storeDump) continue;
Object.keys(storeDump).forEach(async (key) => { for (let rec of storeDump.records) {
const value = storeDump[key]; tx.objectStore(name).put(rec.value, rec.key);
if (!value) return; }
tx.objectStore(name).put(value);
});
} }
tx.commit(); tx.commit();
}); });
} }
export async function importDb(db: IDBDatabase, object: any): Promise<void> { function checkDbDump(x: any): x is DbDump {
if ("name" in object && "stores" in object && "version" in object) { return "databases" in x;
// looks like a database dump }
const dump = object as DatabaseDump;
return recoverFromDump(db, dump);
}
if ("databases" in object && "$types" in object) { export async function importDb(db: IDBDatabase, dumpJson: any): Promise<void> {
// looks like a IDBDatabase const d = dumpJson;
const someDatabase = object.databases; if (checkDbDump(d)) {
const walletDb = d.databases[TALER_WALLET_MAIN_DB_NAME];
if (TALER_WALLET_META_DB_NAME in someDatabase) { if (!walletDb) {
//looks like a taler database throw Error(
const currentMainDbValue = `unable to import, main wallet database (${TALER_WALLET_MAIN_DB_NAME}) not found`,
someDatabase[TALER_WALLET_META_DB_NAME].objectStores.metaConfig );
.records[0].value.value;
if (currentMainDbValue !== TALER_WALLET_MAIN_DB_NAME) {
console.log("not the current database version");
}
const talerDb = someDatabase[currentMainDbValue];
const objectStoreNames = Object.keys(talerDb.objectStores);
const dump: DatabaseDump = {
name: talerDb.schema.databaseName,
version: talerDb.schema.databaseVersion,
stores: {},
};
for (let i = 0; i < objectStoreNames.length; i++) {
const name = objectStoreNames[i];
const storeDump = {} as { [s: string]: any };
dump.stores[name] = storeDump;
talerDb.objectStores[name].records.map((r: any) => {
const pkey = r.primaryKey;
const key =
typeof pkey === "string" || typeof pkey === "number"
? pkey
: pkey.join(",");
storeDump[key] = r.value;
});
}
return recoverFromDump(db, dump);
} }
await recoverFromDump(db, walletDb);
} else {
throw Error("unable to import, doesn't look like a valid DB dump");
} }
throw Error("could not import database");
} }
export interface FixupDescription { export interface FixupDescription {