diff --git a/services/document-updater/app/coffee/ShareJsUpdateManager.coffee b/services/document-updater/app/coffee/ShareJsUpdateManager.coffee index a5cc6070cb..f4f3674c75 100644 --- a/services/document-updater/app/coffee/ShareJsUpdateManager.coffee +++ b/services/document-updater/app/coffee/ShareJsUpdateManager.coffee @@ -6,6 +6,7 @@ Keys = require "./UpdateKeys" {EventEmitter} = require "events" util = require "util" RealTimeRedisManager = require "./RealTimeRedisManager" +crypto = require "crypto" ShareJsModel:: = {} util.inherits ShareJsModel, EventEmitter @@ -22,7 +23,8 @@ module.exports = ShareJsUpdateManager = applyUpdate: (project_id, doc_id, update, lines, version, callback = (error, updatedDocLines) ->) -> logger.log project_id: project_id, doc_id: doc_id, update: update, "applying sharejs updates" jobs = [] - + # record the update version before it is modified + incomingUpdateVersion = update.version # We could use a global model for all docs, but we're hitting issues with the # internal state of ShareJS not being accessible for clearing caches, and # getting stuck due to queued callbacks (line 260 of sharejs/server/model.coffee) @@ -42,6 +44,10 @@ module.exports = ShareJsUpdateManager = logger.log project_id: project_id, doc_id: doc_id, error: error, "applied update" model.getSnapshot doc_key, (error, data) => return callback(error) if error? + # only check hash when present and no other updates have been applied + if update.hash? and incomingUpdateVersion == version + ourHash = ShareJsUpdateManager._computeHash(data.snapshot) + return callback(new Error("Invalid hash")) if ourHash != update.hash docLines = data.snapshot.split(/\r\n|\n|\r/) callback(null, docLines, data.v, model.db.appliedOps[doc_key] or []) @@ -53,3 +59,9 @@ module.exports = ShareJsUpdateManager = _sendOp: (project_id, doc_id, op) -> RealTimeRedisManager.sendData {project_id, doc_id, op} + _computeHash: (content) -> + return crypto.createHash('sha1') + .update("blob " + content.length + "\x00") + .update(content, 'utf8') + .digest('hex') +