From 23f8a12922a019e74b464016c167bed6efdc8f8f Mon Sep 17 00:00:00 2001 From: Richard Hansen Date: Fri, 26 Nov 2021 01:35:02 -0500 Subject: [PATCH] ImportEtherpad: Don't make any changes if data is bad --- src/node/utils/ImportEtherpad.js | 14 ++++++++++++-- src/tests/backend/specs/ImportEtherpad.js | 10 ++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/node/utils/ImportEtherpad.js b/src/node/utils/ImportEtherpad.js index cfa6a2643..bc54e9ca1 100644 --- a/src/node/utils/ImportEtherpad.js +++ b/src/node/utils/ImportEtherpad.js @@ -47,6 +47,11 @@ exports.setPadRaw = async (padId, r) => { if (originalPadId !== padId) throw new Error('unexpected pad ID in record'); }; + // First validate and transform values. Do not commit any records to the database yet in case + // there is a problem with the data. + + const dbRecords = new Map(); + const existingAuthors = new Set(); await Promise.all(Object.entries(records).map(async ([key, value]) => { if (!value) { return; @@ -62,7 +67,7 @@ exports.setPadRaw = async (padId, r) => { } checkOriginalPadId(value.padIDs); if (await authorManager.doesAuthorExist(id)) { - await authorManager.addPad(id, padId); + existingAuthors.add(id); return; } value.padIDs = {[padId]: 1}; @@ -79,11 +84,16 @@ exports.setPadRaw = async (padId, r) => { logger.warn(`(pad ${padId}) Ignoring record with unsupported key: ${key}`); return; } - await db.set(key, value); + dbRecords.set(key, value); })); if (unsupportedElements.size) { logger.warn('Ignoring unsupported elements (you might want to install a plugin): ' + `${[...unsupportedElements].join(', ')}`); } + + await Promise.all([ + ...[...dbRecords].map(async ([k, v]) => await db.set(k, v)), + ...[...existingAuthors].map(async (authorId) => await authorManager.addPad(authorId, padId)), + ]); }; diff --git a/src/tests/backend/specs/ImportEtherpad.js b/src/tests/backend/specs/ImportEtherpad.js index 7906c3afb..6dfd11112 100644 --- a/src/tests/backend/specs/ImportEtherpad.js +++ b/src/tests/backend/specs/ImportEtherpad.js @@ -62,6 +62,16 @@ describe(__filename, function () { assert(await db.get(badKey) == null); }); + it('changes are all or nothing', async function () { + const authorId = makeAuthorId(); + const data = makeExport(authorId); + data['pad:differentPadId:revs:0'] = data['pad:testing:revs:0']; + delete data['pad:testing:revs:0']; + assert.rejects(importEtherpad.setPadRaw(padId, JSON.stringify(data)), /unexpected pad ID/); + assert(!await authorManager.doesAuthorExist(authorId)); + assert(!await padManager.doesPadExist(padId)); + }); + describe('author pad IDs', function () { let existingAuthorId; let newAuthorId;