mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-31 19:02:59 +01:00
PadMessageHandler: Factor out common USER_CHANGES error message formatting
This commit is contained in:
parent
35b2aeb3b1
commit
1447ab8899
1 changed files with 46 additions and 55 deletions
|
@ -601,53 +601,49 @@ const handleUserChanges = async (socket, message) => {
|
||||||
|
|
||||||
// create the changeset
|
// create the changeset
|
||||||
try {
|
try {
|
||||||
try {
|
// Verify that the changeset has valid syntax and is in canonical form
|
||||||
// Verify that the changeset has valid syntax and is in canonical form
|
Changeset.checkRep(changeset);
|
||||||
Changeset.checkRep(changeset);
|
|
||||||
|
|
||||||
// Verify that the attribute indexes used in the changeset are all
|
// Verify that the attribute indexes used in the changeset are all
|
||||||
// defined in the accompanying attribute pool.
|
// defined in the accompanying attribute pool.
|
||||||
Changeset.eachAttribNumber(changeset, (n) => {
|
Changeset.eachAttribNumber(changeset, (n) => {
|
||||||
if (!wireApool.getAttrib(n)) {
|
if (!wireApool.getAttrib(n)) {
|
||||||
throw new Error(`Attribute pool is missing attribute ${n} for changeset ${changeset}`);
|
throw new Error(`Attribute pool is missing attribute ${n} for changeset ${changeset}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Validate all added 'author' attribs to be the same value as the current user
|
||||||
|
const iterator = Changeset.opIterator(Changeset.unpack(changeset).ops);
|
||||||
|
let op;
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
op = iterator.next();
|
||||||
|
|
||||||
|
// + can add text with attribs
|
||||||
|
// = can change or add attribs
|
||||||
|
// - can have attribs, but they are discarded and don't show up in the attribs -
|
||||||
|
// but do show up in the pool
|
||||||
|
|
||||||
|
op.attribs.split('*').forEach((attr) => {
|
||||||
|
if (!attr) return;
|
||||||
|
|
||||||
|
attr = wireApool.getAttrib(attr);
|
||||||
|
if (!attr) return;
|
||||||
|
|
||||||
|
// the empty author is used in the clearAuthorship functionality so this
|
||||||
|
// should be the only exception
|
||||||
|
if ('author' === attr[0] && (attr[1] !== thisSession.author && attr[1] !== '')) {
|
||||||
|
throw new Error(`Author ${thisSession.author} tried to submit changes as author ` +
|
||||||
|
`${attr[1]} in changeset ${changeset}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Validate all added 'author' attribs to be the same value as the current user
|
|
||||||
const iterator = Changeset.opIterator(Changeset.unpack(changeset).ops);
|
|
||||||
let op;
|
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
op = iterator.next();
|
|
||||||
|
|
||||||
// + can add text with attribs
|
|
||||||
// = can change or add attribs
|
|
||||||
// - can have attribs, but they are discarded and don't show up in the attribs -
|
|
||||||
// but do show up in the pool
|
|
||||||
|
|
||||||
op.attribs.split('*').forEach((attr) => {
|
|
||||||
if (!attr) return;
|
|
||||||
|
|
||||||
attr = wireApool.getAttrib(attr);
|
|
||||||
if (!attr) return;
|
|
||||||
|
|
||||||
// the empty author is used in the clearAuthorship functionality so this
|
|
||||||
// should be the only exception
|
|
||||||
if ('author' === attr[0] && (attr[1] !== thisSession.author && attr[1] !== '')) {
|
|
||||||
throw new Error(`Author ${thisSession.author} tried to submit changes as author ` +
|
|
||||||
`${attr[1]} in changeset ${changeset}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// ex. adoptChangesetAttribs
|
|
||||||
|
|
||||||
// Afaik, it copies the new attributes from the changeset, to the global Attribute Pool
|
|
||||||
changeset = Changeset.moveOpsToNewPool(changeset, wireApool, pad.pool);
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(`Can't apply USER_CHANGES from Socket ${socket.id} because: ${e.message}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ex. adoptChangesetAttribs
|
||||||
|
|
||||||
|
// Afaik, it copies the new attributes from the changeset, to the global Attribute Pool
|
||||||
|
changeset = Changeset.moveOpsToNewPool(changeset, wireApool, pad.pool);
|
||||||
|
|
||||||
// ex. applyUserChanges
|
// ex. applyUserChanges
|
||||||
const apool = pad.pool;
|
const apool = pad.pool;
|
||||||
let r = baseRev;
|
let r = baseRev;
|
||||||
|
@ -665,24 +661,18 @@ const handleUserChanges = async (socket, message) => {
|
||||||
// rebases "changeset" so that it is relative to revision r
|
// rebases "changeset" so that it is relative to revision r
|
||||||
// and can be applied after "c".
|
// and can be applied after "c".
|
||||||
|
|
||||||
try {
|
// a changeset can be based on an old revision with the same changes in it
|
||||||
// a changeset can be based on an old revision with the same changes in it
|
// prevent eplite from accepting it TODO: better send the client a NEW_CHANGES
|
||||||
// prevent eplite from accepting it TODO: better send the client a NEW_CHANGES
|
// of that revision
|
||||||
// of that revision
|
if (baseRev + 1 === r && c === changeset) throw new Error('Changeset already accepted');
|
||||||
if (baseRev + 1 === r && c === changeset) {
|
|
||||||
throw new Error("Won't apply USER_CHANGES, as it contains an already accepted changeset");
|
|
||||||
}
|
|
||||||
|
|
||||||
changeset = Changeset.follow(c, changeset, false, apool);
|
changeset = Changeset.follow(c, changeset, false, apool);
|
||||||
} catch (e) {
|
|
||||||
throw new Error(`Can't apply USER_CHANGES, because ${e.message}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const prevText = pad.text();
|
const prevText = pad.text();
|
||||||
|
|
||||||
if (Changeset.oldLen(changeset) !== prevText.length) {
|
if (Changeset.oldLen(changeset) !== prevText.length) {
|
||||||
throw new Error(`Can't apply USER_CHANGES ${changeset} with oldLen ` +
|
throw new Error(`Can't apply changeset ${changeset} with oldLen ` +
|
||||||
`${Changeset.oldLen(changeset)} to document of length ${prevText.length}`);
|
`${Changeset.oldLen(changeset)} to document of length ${prevText.length}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,7 +693,8 @@ const handleUserChanges = async (socket, message) => {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
socket.json.send({disconnect: 'badChangeset'});
|
socket.json.send({disconnect: 'badChangeset'});
|
||||||
stats.meter('failedChangesets').mark();
|
stats.meter('failedChangesets').mark();
|
||||||
console.warn(err.stack || err);
|
console.warn(`Failed to apply USER_CHANGES from author ${thisSession.author} ` +
|
||||||
|
`(socket ${socket.id}) on pad ${thisSession.padId}: ${err.stack || err}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
stopWatch.end();
|
stopWatch.end();
|
||||||
|
|
Loading…
Reference in a new issue