pad.libre-service.eu-etherpad/src/tests/backend/specs/ImportEtherpad.js

170 lines
6.3 KiB
JavaScript

'use strict';
const assert = require('assert').strict;
const authorManager = require('../../../node/db/AuthorManager');
const db = require('../../../node/db/DB');
const importEtherpad = require('../../../node/utils/ImportEtherpad');
const padManager = require('../../../node/db/PadManager');
const {randomString} = require('../../../static/js/pad_utils');
describe(__filename, function () {
let padId;
const makeAuthorId = () => `a.${randomString(16)}`;
const makeExport = (authorId) => ({
'pad:testing': {
atext: {
text: 'foo\n',
attribs: '|1+4',
},
pool: {
numToAttrib: {},
nextNum: 0,
},
head: 0,
savedRevisions: [],
},
[`globalAuthor:${authorId}`]: {
colorId: '#000000',
name: 'new',
timestamp: 1598747784631,
padIDs: 'testing',
},
'pad:testing:revs:0': {
changeset: 'Z:1>3+3$foo',
meta: {
author: '',
timestamp: 1597632398288,
pool: {
numToAttrib: {},
nextNum: 0,
},
atext: {
text: 'foo\n',
attribs: '|1+4',
},
},
},
});
beforeEach(async function () {
padId = randomString(10);
assert(!await padManager.doesPadExist(padId));
});
it('unknown db records are ignored', async function () {
const badKey = `maliciousDbKey${randomString(10)}`;
await importEtherpad.setPadRaw(padId, JSON.stringify({
[badKey]: 'value',
...makeExport(makeAuthorId()),
}));
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;
beforeEach(async function () {
existingAuthorId = (await authorManager.createAuthor('existing')).authorID;
assert(await authorManager.doesAuthorExist(existingAuthorId));
assert.deepEqual((await authorManager.listPadsOfAuthor(existingAuthorId)).padIDs, []);
newAuthorId = makeAuthorId();
assert.notEqual(newAuthorId, existingAuthorId);
assert(!await authorManager.doesAuthorExist(newAuthorId));
});
it('author does not yet exist', async function () {
await importEtherpad.setPadRaw(padId, JSON.stringify(makeExport(newAuthorId)));
assert(await authorManager.doesAuthorExist(newAuthorId));
const author = await authorManager.getAuthor(newAuthorId);
assert.equal(author.name, 'new');
assert.equal(author.colorId, '#000000');
assert.deepEqual((await authorManager.listPadsOfAuthor(newAuthorId)).padIDs, [padId]);
});
it('author already exists, no pads', async function () {
newAuthorId = existingAuthorId;
await importEtherpad.setPadRaw(padId, JSON.stringify(makeExport(newAuthorId)));
assert(await authorManager.doesAuthorExist(newAuthorId));
const author = await authorManager.getAuthor(newAuthorId);
assert.equal(author.name, 'existing');
assert.notEqual(author.colorId, '#000000');
assert.deepEqual((await authorManager.listPadsOfAuthor(newAuthorId)).padIDs, [padId]);
});
it('author already exists, on different pad', async function () {
const otherPadId = randomString(10);
await authorManager.addPad(existingAuthorId, otherPadId);
newAuthorId = existingAuthorId;
await importEtherpad.setPadRaw(padId, JSON.stringify(makeExport(newAuthorId)));
assert(await authorManager.doesAuthorExist(newAuthorId));
const author = await authorManager.getAuthor(newAuthorId);
assert.equal(author.name, 'existing');
assert.notEqual(author.colorId, '#000000');
assert.deepEqual(
(await authorManager.listPadsOfAuthor(newAuthorId)).padIDs.sort(),
[otherPadId, padId].sort());
});
it('author already exists, on same pad', async function () {
await authorManager.addPad(existingAuthorId, padId);
newAuthorId = existingAuthorId;
await importEtherpad.setPadRaw(padId, JSON.stringify(makeExport(newAuthorId)));
assert(await authorManager.doesAuthorExist(newAuthorId));
const author = await authorManager.getAuthor(newAuthorId);
assert.equal(author.name, 'existing');
assert.notEqual(author.colorId, '#000000');
assert.deepEqual((await authorManager.listPadsOfAuthor(newAuthorId)).padIDs, [padId]);
});
});
describe('enforces consistent pad ID', function () {
it('pad record has different pad ID', async function () {
const data = makeExport(makeAuthorId());
data['pad:differentPadId'] = data['pad:testing'];
delete data['pad:testing'];
assert.rejects(importEtherpad.setPadRaw(padId, JSON.stringify(data)), /unexpected pad ID/);
});
it('globalAuthor record has different pad ID', async function () {
const authorId = makeAuthorId();
const data = makeExport(authorId);
data[`globalAuthor:${authorId}`].padIDs = 'differentPadId';
assert.rejects(importEtherpad.setPadRaw(padId, JSON.stringify(data)), /unexpected pad ID/);
});
it('pad rev record has different pad ID', async function () {
const data = makeExport(makeAuthorId());
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/);
});
});
describe('order of records does not matter', function () {
for (const perm of [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]) {
it(JSON.stringify(perm), async function () {
const authorId = makeAuthorId();
const records = Object.entries(makeExport(authorId));
assert.equal(records.length, 3);
await importEtherpad.setPadRaw(
padId, JSON.stringify(Object.fromEntries(perm.map((i) => records[i]))));
assert.deepEqual((await authorManager.listPadsOfAuthor(authorId)).padIDs, [padId]);
const pad = await padManager.getPad(padId);
assert.equal(pad.text(), 'foo\n');
});
}
});
});