43
server/commands/revisionCreator.js
Normal file
43
server/commands/revisionCreator.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// @flow
|
||||||
|
import { Document, User, Event, Revision } from "../models";
|
||||||
|
import { sequelize } from "../sequelize";
|
||||||
|
|
||||||
|
export default async function revisionCreator({
|
||||||
|
document,
|
||||||
|
user,
|
||||||
|
ip,
|
||||||
|
}: {
|
||||||
|
document: Document,
|
||||||
|
user: User,
|
||||||
|
ip?: string,
|
||||||
|
}) {
|
||||||
|
let transaction;
|
||||||
|
|
||||||
|
try {
|
||||||
|
transaction = await sequelize.transaction();
|
||||||
|
|
||||||
|
const revision = await Revision.createFromDocument(document, {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await Event.create(
|
||||||
|
{
|
||||||
|
name: "revisions.create",
|
||||||
|
documentId: document.id,
|
||||||
|
modelId: revision.id,
|
||||||
|
teamId: document.teamId,
|
||||||
|
actorId: user.id,
|
||||||
|
ip: ip || user.lastActiveIp,
|
||||||
|
},
|
||||||
|
{ transaction }
|
||||||
|
);
|
||||||
|
await transaction.commit();
|
||||||
|
|
||||||
|
return revision;
|
||||||
|
} catch (err) {
|
||||||
|
if (transaction) {
|
||||||
|
await transaction.rollback();
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
27
server/commands/revisionCreator.test.js
Normal file
27
server/commands/revisionCreator.test.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// @flow
|
||||||
|
import { Event } from "../models";
|
||||||
|
import { buildDocument, buildUser } from "../test/factories";
|
||||||
|
import { flushdb } from "../test/support";
|
||||||
|
import revisionCreator from "./revisionCreator";
|
||||||
|
|
||||||
|
beforeEach(() => flushdb());
|
||||||
|
|
||||||
|
describe("revisionCreator", () => {
|
||||||
|
const ip = "127.0.0.1";
|
||||||
|
|
||||||
|
it("should create revision model from document", async () => {
|
||||||
|
const user = await buildUser();
|
||||||
|
const document = await buildDocument({
|
||||||
|
userId: user.id,
|
||||||
|
teamId: user.teamId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const revision = await revisionCreator({ document, user, ip });
|
||||||
|
const event = await Event.findOne();
|
||||||
|
|
||||||
|
expect(revision.documentId).toEqual(document.id);
|
||||||
|
expect(revision.userId).toEqual(user.id);
|
||||||
|
expect(event.name).toEqual("revisions.create");
|
||||||
|
expect(event.modelId).toEqual(revision.id);
|
||||||
|
});
|
||||||
|
});
|
@ -67,6 +67,7 @@ Event.ACTIVITY_EVENTS = [
|
|||||||
"documents.delete",
|
"documents.delete",
|
||||||
"documents.permanent_delete",
|
"documents.permanent_delete",
|
||||||
"documents.restore",
|
"documents.restore",
|
||||||
|
"revisions.create",
|
||||||
"users.create",
|
"users.create",
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -96,6 +97,7 @@ Event.AUDIT_EVENTS = [
|
|||||||
"groups.create",
|
"groups.create",
|
||||||
"groups.update",
|
"groups.update",
|
||||||
"groups.delete",
|
"groups.delete",
|
||||||
|
"revisions.create",
|
||||||
"shares.create",
|
"shares.create",
|
||||||
"shares.update",
|
"shares.update",
|
||||||
"shares.revoke",
|
"shares.revoke",
|
||||||
|
@ -49,19 +49,22 @@ Revision.findLatest = function (documentId) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Revision.createFromDocument = function (document) {
|
Revision.createFromDocument = function (document, options) {
|
||||||
return Revision.create({
|
return Revision.create(
|
||||||
title: document.title,
|
{
|
||||||
text: document.text,
|
title: document.title,
|
||||||
userId: document.lastModifiedById,
|
text: document.text,
|
||||||
editorVersion: document.editorVersion,
|
userId: document.lastModifiedById,
|
||||||
version: document.version,
|
editorVersion: document.editorVersion,
|
||||||
documentId: document.id,
|
version: document.version,
|
||||||
|
documentId: document.id,
|
||||||
|
|
||||||
// revision time is set to the last time document was touched as this
|
// revision time is set to the last time document was touched as this
|
||||||
// handler can be debounced in the case of an update
|
// handler can be debounced in the case of an update
|
||||||
createdAt: document.updatedAt,
|
createdAt: document.updatedAt,
|
||||||
});
|
},
|
||||||
|
options
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Revision.prototype.migrateVersion = function () {
|
Revision.prototype.migrateVersion = function () {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
import invariant from "invariant";
|
||||||
|
import revisionCreator from "../commands/revisionCreator";
|
||||||
import type { DocumentEvent, RevisionEvent } from "../events";
|
import type { DocumentEvent, RevisionEvent } from "../events";
|
||||||
import { Revision, Document } from "../models";
|
import { Revision, Document, User } from "../models";
|
||||||
|
|
||||||
export default class Revisions {
|
export default class Revisions {
|
||||||
async on(event: DocumentEvent | RevisionEvent) {
|
async on(event: DocumentEvent | RevisionEvent) {
|
||||||
@ -8,7 +10,7 @@ export default class Revisions {
|
|||||||
case "documents.publish":
|
case "documents.publish":
|
||||||
case "documents.update.debounced": {
|
case "documents.update.debounced": {
|
||||||
const document = await Document.findByPk(event.documentId);
|
const document = await Document.findByPk(event.documentId);
|
||||||
if (!document) return;
|
invariant(document, "Document should exist");
|
||||||
|
|
||||||
const previous = await Revision.findLatest(document.id);
|
const previous = await Revision.findLatest(document.id);
|
||||||
|
|
||||||
@ -22,7 +24,10 @@ export default class Revisions {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Revision.createFromDocument(document);
|
const user = await User.findByPk(event.actorId);
|
||||||
|
invariant(user, "User should exist");
|
||||||
|
|
||||||
|
await revisionCreator({ user, document });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user