Compare commits

...

3 Commits

Author SHA1 Message Date
Tom Moor b680a3e152 avoid overriding restore 2021-10-27 22:52:30 -07:00
Tom Moor 9306a0390e fix: protect against restore of collab revision 2021-10-25 23:39:50 -07:00
Tom Moor 4d5eed4860 Store snapshot on revision 2021-10-25 22:46:20 -07:00
6 changed files with 56 additions and 11 deletions
@@ -0,0 +1,13 @@
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.addColumn("revisions", "state", {
type: Sequelize.BLOB,
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.removeColumn("revisions", "state");
},
};
+16
View File
@@ -674,6 +674,22 @@ Document.prototype.unarchive = async function (userId: string) {
return this;
};
Document.prototype.restoreFromRevision = async function (
revision: Revision,
userId: string
) {
if (revision.state) {
throw new Error("cannot restore document with snapshot");
}
this.text = revision.text;
this.title = revision.title;
this.lastModifiedById = userId;
await this.save();
return this;
};
// Delete a document, archived or otherwise.
Document.prototype.delete = function (userId: string) {
return sequelize.transaction(
+11
View File
@@ -1,5 +1,6 @@
// @flow
import MarkdownSerializer from "slate-md-serializer";
import * as Y from "yjs";
import { DataTypes, sequelize } from "../sequelize";
const serializer = new MarkdownSerializer();
@@ -12,6 +13,7 @@ const Revision = sequelize.define("revision", {
},
version: DataTypes.SMALLINT,
editorVersion: DataTypes.STRING,
state: DataTypes.BLOB,
title: DataTypes.STRING,
text: DataTypes.TEXT,
});
@@ -45,8 +47,17 @@ Revision.findLatest = function (documentId) {
};
Revision.createFromDocument = function (document, options) {
let snapshot;
if (document.state) {
const ydoc = new Y.Doc();
Y.applyUpdate(ydoc, document.state);
snapshot = Buffer.from(Y.encodeSnapshot(Y.snapshot(ydoc)));
}
return Revision.create(
{
state: snapshot,
title: document.title,
text: document.text,
userId: document.lastModifiedById,
+4 -1
View File
@@ -3,6 +3,9 @@ import { Document } from "../../models";
import { globalEventQueue } from "../../queues";
import type { Event } from "../../types";
const delay =
process.env.NODE_ENV === "development" ? 1 * 60 * 1000 : 5 * 60 * 1000;
export default class DebounceProcessor {
async on(event: Event) {
switch (event.name) {
@@ -13,7 +16,7 @@ export default class DebounceProcessor {
name: "documents.update.delayed",
},
{
delay: 5 * 60 * 1000,
delay,
}
);
break;
+1 -3
View File
@@ -713,9 +713,7 @@ router.post("documents.restore", auth(), async (ctx) => {
const revision = await Revision.findByPk(revisionId);
authorize(document, "restore", revision);
document.text = revision.text;
document.title = revision.title;
await document.save();
await document.restoreFromRevision(revision, user.id);
await Event.create({
name: "documents.restore",
+11 -7
View File
@@ -8,7 +8,18 @@
"Development": "Development",
"Open document": "Open document",
"New document": "New document",
"Star": "Star",
"Unstar": "Unstar",
"Download": "Download",
"Download document": "Download document",
"Duplicate": "Duplicate",
"Duplicate document": "Duplicate document",
"Document duplicated": "Document duplicated",
"Print": "Print",
"Print document": "Print document",
"Import document": "Import document",
"Templatize": "Templatize",
"Create template": "Create template",
"Home": "Home",
"Search": "Search",
"Drafts": "Drafts",
@@ -198,8 +209,6 @@
"Export": "Export",
"Integrations": "Integrations",
"Installation": "Installation",
"Unstar": "Unstar",
"Star": "Star",
"Previous page": "Previous page",
"Next page": "Next page",
"Could not import file": "Could not import file",
@@ -218,7 +227,6 @@
"Sort in sidebar": "Sort in sidebar",
"Alphabetical sort": "Alphabetical sort",
"Manual sort": "Manual sort",
"Document duplicated": "Document duplicated",
"Document restored": "Document restored",
"Document unpublished": "Document unpublished",
"Document options": "Document options",
@@ -227,15 +235,11 @@
"Unpin": "Unpin",
"Pin to collection": "Pin to collection",
"New nested document": "New nested document",
"Create template": "Create template",
"Duplicate": "Duplicate",
"Unpublish": "Unpublish",
"Permanently delete": "Permanently delete",
"Move": "Move",
"Enable embeds": "Enable embeds",
"Disable embeds": "Disable embeds",
"Download": "Download",
"Print": "Print",
"Move {{ documentName }}": "Move {{ documentName }}",
"Permanently delete {{ documentName }}": "Permanently delete {{ documentName }}",
"Export options": "Export options",