From 0178f782490f7eebff70e9371ad00806f382996a Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Fri, 10 Nov 2017 15:47:12 +0000 Subject: [PATCH 01/27] handle file additions in DocumentUpdaterHandler.updateProjectStructure --- .../DocumentUpdaterHandler.coffee | 12 +++ .../DocumentUpdaterHandlerTests.coffee | 98 ++++++++++++++----- 2 files changed, 84 insertions(+), 26 deletions(-) diff --git a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee index d8613680a8..77cbe379b9 100644 --- a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee +++ b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee @@ -244,6 +244,18 @@ module.exports = DocumentUpdaterHandler = pathname: oldEntity.path newPathname: newEntity.path + for newEntity in newEntities + id = newEntity[entityType]._id + oldEntity = _.find oldEntities, (oldEntity) -> + oldEntity[entityType]._id.toString() == id.toString() + + if !oldEntity? + updates.push + id: id + pathname: newEntity.path + docLines: newEntity.docLines + url: newEntity.url + updates PENDINGUPDATESKEY = "PendingUpdates" diff --git a/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee b/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee index ec81ae1c2e..d0b9106ede 100644 --- a/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee +++ b/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee @@ -390,19 +390,6 @@ describe 'DocumentUpdaterHandler', -> describe "updateProjectStructure ", -> beforeEach -> @user_id = 1234 - @docIdA = new ObjectId() - @docIdB = new ObjectId() - @oldDocs = [ - { path: '/old_a', doc: _id: @docIdA } - { path: '/old_b', doc: _id: @docIdB } - ] - # create new instances of the same ObjectIds so that == doens't pass - @newDocs = [ - { path: '/old_a', doc: _id: new ObjectId(@docIdA.toString()) } - { path: '/new_b', doc: _id: new ObjectId(@docIdB.toString()) } - ] - @oldFiles = [] - @newFiles = [] describe "with project history disabled", -> beforeEach -> @@ -420,20 +407,79 @@ describe 'DocumentUpdaterHandler', -> describe "with project history enabled", -> beforeEach -> @settings.apis.project_history.enabled = true + @url = "#{@settings.apis.documentupdater.url}/project/#{@project_id}" @request.post = sinon.stub().callsArgWith(1, null, {statusCode: 204}, "") - @handler.updateProjectStructure @project_id, @user_id, @oldDocs, @newDocs, @oldFiles, @newFiles, @callback - it 'should send the structure update to the document updater', -> - docUpdates = [ - id: @docIdB, - pathname: "/old_b" - newPathname: "/new_b" - ] + describe "when an entity has changed name", -> + it 'should send the structure update to the document updater', (done) -> + @docIdA = new ObjectId() + @docIdB = new ObjectId() + @oldDocs = [ + { path: '/old_a', doc: _id: @docIdA } + { path: '/old_b', doc: _id: @docIdB } + ] + # create new instances of the same ObjectIds so that == doens't pass + @newDocs = [ + { path: '/old_a', doc: _id: new ObjectId(@docIdA.toString()) } + { path: '/new_b', doc: _id: new ObjectId(@docIdB.toString()) } + ] + @oldFiles = [] + @newFiles = [] - url = "#{@settings.apis.documentupdater.url}/project/#{@project_id}" - @request.post - .calledWith(url: url, json: {docUpdates, fileUpdates: [], userId: @user_id}) - .should.equal true + docUpdates = [ + id: @docIdB, + pathname: "/old_b" + newPathname: "/new_b" + ] - it "should call the callback with no error", -> - @callback.calledWith(null).should.equal true + @handler.updateProjectStructure @project_id, @user_id, @oldDocs, @newDocs, @oldFiles, @newFiles, () => + @request.post + .calledWith(url: @url, json: {docUpdates, fileUpdates: [], userId: @user_id}) + .should.equal true + done() + + describe "when a doc has been added", -> + it 'should send the structure update to the document updater', (done) -> + @docId = new ObjectId() + @oldDocs = [] + @newDocs = [ + { path: '/foo', docLines: 'a\nb', doc: _id: @docId } + ] + @oldFiles = [] + @newFiles = [] + + docUpdates = [ + id: @docId, + pathname: "/foo" + docLines: 'a\nb' + url: undefined + ] + + @handler.updateProjectStructure @project_id, @user_id, @oldDocs, @newDocs, @oldFiles, @newFiles, () => + @request.post + .calledWith(url: @url, json: {docUpdates, fileUpdates: [], userId: @user_id}) + .should.equal true + done() + + describe "when a file has been added", -> + it 'should send the structure update to the document updater', (done) -> + @fileId = new ObjectId() + @oldDocs = [] + @newDocs = [] + @oldFiles = [] + @newFiles = [ + { path: '/bar', url: 'filestore.example.com/file', file: _id: @fileId } + ] + + fileUpdates = [ + id: @fileId, + pathname: "/bar" + url: 'filestore.example.com/file' + docLines: undefined + ] + + @handler.updateProjectStructure @project_id, @user_id, @oldDocs, @newDocs, @oldFiles, @newFiles, () => + @request.post + .calledWith(url: @url, json: {docUpdates: [], fileUpdates, userId: @user_id}) + .should.equal true + done() From 6e84c635cf332e37dfbd17d54e1aea5c7bcfbb7e Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Fri, 10 Nov 2017 15:47:47 +0000 Subject: [PATCH 02/27] return url from FileStoreHandler.uploadFileFromDisk --- .../FileStore/FileStoreHandler.coffee | 9 ++++---- .../FileStore/FileStoreHandlerTests.coffee | 21 ++++++++++--------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/services/web/app/coffee/Features/FileStore/FileStoreHandler.coffee b/services/web/app/coffee/Features/FileStore/FileStoreHandler.coffee index 92efe7bfcb..88f55bc698 100644 --- a/services/web/app/coffee/Features/FileStore/FileStoreHandler.coffee +++ b/services/web/app/coffee/Features/FileStore/FileStoreHandler.coffee @@ -21,9 +21,9 @@ module.exports = FileStoreHandler = return callback(new Error("can not upload symlink")) _cb = callback - callback = (err) -> + callback = (err, url) -> callback = -> # avoid double callbacks - _cb(err) + _cb(err, url) logger.log project_id:project_id, file_id:file_id, fsPath:fsPath, "uploading file from disk" readStream = fs.createReadStream(fsPath) @@ -31,9 +31,10 @@ module.exports = FileStoreHandler = logger.err err:err, project_id:project_id, file_id:file_id, fsPath:fsPath, "something went wrong on the read stream of uploadFileFromDisk" callback err readStream.on "open", () -> + url = FileStoreHandler._buildUrl(project_id, file_id) opts = method: "post" - uri: FileStoreHandler._buildUrl(project_id, file_id) + uri: url timeout:fiveMinsInMs writeStream = request(opts) writeStream.on "error", (err)-> @@ -45,7 +46,7 @@ module.exports = FileStoreHandler = logger.err {err, statusCode: response.statusCode}, "error uploading to filestore" callback(err) else - callback(null) + callback(null, url) readStream.pipe writeStream getFileStream: (project_id, file_id, query, callback)-> diff --git a/services/web/test/unit/coffee/FileStore/FileStoreHandlerTests.coffee b/services/web/test/unit/coffee/FileStore/FileStoreHandlerTests.coffee index 73f32f3a60..ea7c7a4cbb 100644 --- a/services/web/test/unit/coffee/FileStore/FileStoreHandlerTests.coffee +++ b/services/web/test/unit/coffee/FileStore/FileStoreHandlerTests.coffee @@ -16,7 +16,7 @@ describe "FileStoreHandler", -> }) @writeStream = my:"writeStream" - on: (type, cb)-> + on: (type, cb)-> if type == "response" cb({statusCode: 200}) @readStream = {my:"readStream", on: sinon.stub()} @@ -38,7 +38,7 @@ describe "FileStoreHandler", -> @isSafeOnFileSystem = true it "should create read stream", (done)-> - @fs.createReadStream.returns + @fs.createReadStream.returns pipe:-> on: (type, cb)-> if type == "open" @@ -49,8 +49,8 @@ describe "FileStoreHandler", -> it "should pipe the read stream to request", (done)-> @request.returns(@writeStream) - @fs.createReadStream.returns - on: (type, cb)-> + @fs.createReadStream.returns + on: (type, cb)-> if type == "open" cb() pipe:(o)=> @@ -59,9 +59,9 @@ describe "FileStoreHandler", -> @handler.uploadFileFromDisk @project_id, @file_id, @fsPath, => it "should pass the correct options to request", (done)-> - @fs.createReadStream.returns + @fs.createReadStream.returns pipe:-> - on: (type, cb)-> + on: (type, cb)-> if type == "open" cb() @handler.uploadFileFromDisk @project_id, @file_id, @fsPath, => @@ -70,23 +70,24 @@ describe "FileStoreHandler", -> done() it "builds the correct url", (done)-> - @fs.createReadStream.returns + @fs.createReadStream.returns pipe:-> - on: (type, cb)-> + on: (type, cb)-> if type == "open" cb() @handler.uploadFileFromDisk @project_id, @file_id, @fsPath, => @handler._buildUrl.calledWith(@project_id, @file_id).should.equal true done() - it 'should callback with null', (done) -> + it 'should callback with the url', (done) -> @fs.createReadStream.returns pipe:-> on: (type, cb)-> if type == "open" cb() - @handler.uploadFileFromDisk @project_id, @file_id, @fsPath, (err) => + @handler.uploadFileFromDisk @project_id, @file_id, @fsPath, (err, url) => expect(err).to.not.exist + expect(url).to.equal(@handler._buildUrl()) done() describe "symlink", -> From c1481d596f362ad22fd8f2df0050c1f12cb3162c Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Fri, 10 Nov 2017 16:32:19 +0000 Subject: [PATCH 03/27] call DocumentUpdaterHandle.updateProjectStructure from ProjectEntityHandler.addDoc and addFile pass in user_id as null --- .../Project/ProjectEntityHandler.coffee | 24 +++++++++--- .../Project/ProjectEntityHandlerTests.coffee | 37 +++++++++++++++---- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index abd5c7f3d8..4bfbc0e30c 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -177,7 +177,14 @@ module.exports = ProjectEntityHandler = rev: 0 }, (err) -> return callback(err) if err? - callback(null, doc, folder_id) + newDoc = + doc: doc + path: result?.path?.fileSystem + docLines: docLines.join('\n') + documentUpdaterHandler = require('../../Features/DocumentUpdater/DocumentUpdaterHandler') + documentUpdaterHandler.updateProjectStructure project_id, null, [], [newDoc], [], [], (error) -> + return callback(error) if error? + callback null, doc, folder_id restoreDoc: (project_id, doc_id, name, callback = (error, doc, folder_id) ->) -> # getDoc will return the deleted doc's lines, but we don't actually remove @@ -191,15 +198,15 @@ module.exports = ProjectEntityHandler = if err? logger.err project_id:project_id, err:err, "error getting project for add file" return callback(err) - ProjectEntityHandler.addFileWithProject project, folder_id, fileName, path, callback + ProjectEntityHandler.addFileWithProject project, folder_id, fileName, path, null, callback - addFileWithProject: (project, folder_id, fileName, path, callback = (error, fileRef, folder_id) ->)-> + addFileWithProject: (project, folder_id, fileName, path, userId, callback = (error, fileRef, folder_id) ->)-> project_id = project._id logger.log project_id: project._id, folder_id: folder_id, file_name: fileName, path:path, "adding file" return callback(err) if err? confirmFolder project, folder_id, (folder_id)-> fileRef = new File name : fileName - FileStoreHandler.uploadFileFromDisk project._id, fileRef._id, path, (err)-> + FileStoreHandler.uploadFileFromDisk project._id, fileRef._id, path, (err, fileStoreUrl)-> if err? logger.err err:err, project_id: project._id, folder_id: folder_id, file_name: fileName, fileRef:fileRef, "error uploading image to s3" return callback(err) @@ -209,7 +216,14 @@ module.exports = ProjectEntityHandler = return callback(err) tpdsUpdateSender.addFile {project_id:project._id, file_id:fileRef._id, path:result?.path?.fileSystem, project_name:project.name, rev:fileRef.rev}, (err) -> return callback(err) if err? - callback(null, fileRef, folder_id) + newFile = + file: fileRef + path: result?.path?.fileSystem + url: fileStoreUrl + documentUpdaterHandler = require('../../Features/DocumentUpdater/DocumentUpdaterHandler') + documentUpdaterHandler.updateProjectStructure project_id, userId, [], [], [], [newFile], (error) -> + return callback(error) if error? + callback null, fileRef, folder_id replaceFile: (project_id, file_id, fsPath, callback)-> ProjectGetter.getProject project_id, {name:true}, (err, project) -> diff --git a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee index dc723bf8bd..ca968f10a0 100644 --- a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee @@ -17,8 +17,9 @@ describe 'ProjectEntityHandler', -> userId = 1234 beforeEach -> + @fileUrl = 'filestore.example.com/file' @FileStoreHandler = - uploadFileFromDisk:(project_id, fileRef, localImagePath, callback)->callback() + uploadFileFromDisk: sinon.stub().callsArgWith(3, null, @fileUrl) copyFile: sinon.stub().callsArgWith(4, null) @tpdsUpdateSender = addDoc:sinon.stub().callsArg(1) @@ -67,6 +68,9 @@ describe 'ProjectEntityHandler', -> findElement : sinon.stub() @settings = maxEntitiesPerProject:200 + @documentUpdaterHandler = + updateProjectStructure: sinon.stub().callsArg(6) + deleteDoc: sinon.stub().callsArg(2) @ProjectEntityHandler = SandboxedModule.require modulePath, requires: '../../models/Project': Project:@ProjectModel '../../models/Doc': Doc:@DocModel @@ -75,7 +79,7 @@ describe 'ProjectEntityHandler', -> '../FileStore/FileStoreHandler':@FileStoreHandler '../ThirdPartyDataStore/TpdsUpdateSender':@tpdsUpdateSender './ProjectLocator': @projectLocator - '../../Features/DocumentUpdater/DocumentUpdaterHandler':@documentUpdaterHandler = {} + '../../Features/DocumentUpdater/DocumentUpdaterHandler':@documentUpdaterHandler '../Docstore/DocstoreManager': @DocstoreManager = {} 'logger-sharelatex': @logger = {log:sinon.stub(), error: sinon.stub(), err:->} './ProjectUpdateHandler': @projectUpdater @@ -184,7 +188,6 @@ describe 'ProjectEntityHandler', -> describe "_cleanUpEntity", -> beforeEach -> @entity_id = "4eecaffcbffa66588e000009" - @documentUpdaterHandler.deleteDoc = sinon.stub().callsArg(2) @FileStoreHandler.deleteFile = sinon.stub().callsArg(2) @ProjectEntityHandler.unsetRootDoc = sinon.stub().callsArg(1) @@ -240,7 +243,6 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, path: @pathAfterMove) @ProjectGetter.getProject.callsArgWith(2, null, @project) @tpdsUpdateSender.moveEntity = sinon.stub() - @documentUpdaterHandler.updateProjectStructure = sinon.stub().callsArg(6) @ProjectEntityHandler.getAllEntitiesFromProject = sinon.stub() @ProjectEntityHandler.getAllEntitiesFromProject .onFirstCall() @@ -484,6 +486,15 @@ describe 'ProjectEntityHandler', -> .calledWith(project_id, @doc._id.toString(), @lines) .should.equal true + it "should should send the change in project structure to the doc updater", () -> + newDoc = + doc: @doc + path: @path + docLines: @lines.join('\n') + @documentUpdaterHandler.updateProjectStructure + .calledWith(project_id, null, [], [newDoc], [], []) + .should.equal true + describe "restoreDoc", -> beforeEach -> @name = "doc-name" @@ -512,7 +523,10 @@ describe 'ProjectEntityHandler', -> describe 'addFile', -> fileName = "something.jpg" beforeEach -> + @fileSystemPath = "somehintg" + @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, {path:{fileSystem: @fileSystemPath}}) @filePath = "somewhere" + it 'should upload it via the FileStoreHandler', (done)-> @FileStoreHandler.uploadFileFromDisk = (passedProject_id, file_id, filePath, callback)=> file_id.should.equal "file_id" @@ -533,7 +547,6 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, (err, fileRef, parentFolder)-> it 'should return doc and parent folder', (done)-> - @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, {path:{fileSystem:"somehintg"}}) @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, (err, fileRef, parentFolder)-> parentFolder.should.equal folder_id fileRef.name.should.equal fileName @@ -556,6 +569,18 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, (err, fileRef, parentFolder)-> + it "should should send the change in project structure to the doc updater", (done) -> + @documentUpdaterHandler.updateProjectStructure = (project_id, user_id, oldDocs, newDocs, oldFiles, newFiles) => + project_id.should.equal project_id + newFiles.length.should.equal 1 + newFile = newFiles[0] + newFile.file.name.should.equal fileName + newFile.path.should.equal @fileSystemPath + newFile.url.should.equal @fileUrl + done() + + @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, () -> + describe 'replacing a file', -> beforeEach -> @@ -575,12 +600,10 @@ describe 'ProjectEntityHandler', -> done() it 'should tell the file store handler to upload the file from disk', (done)-> - @FileStoreHandler.uploadFileFromDisk = sinon.stub().callsArgWith(3) @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, => @FileStoreHandler.uploadFileFromDisk.calledWith(project_id, @file_id, @fsPath).should.equal true done() - it 'should send the file to the tpds with an incremented rev', (done)-> @tpdsUpdateSender.addFile = (options)=> options.project_id.should.equal project_id From 42a1deaacad320a7b269236f539e334f78225d9c Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Mon, 13 Nov 2017 11:16:54 +0000 Subject: [PATCH 04/27] pass userId into ProjectEntityHandler.addFile --- .../coffee/Features/Editor/EditorController.coffee | 2 +- .../Features/Project/ProjectCreationHandler.coffee | 2 +- .../Features/Project/ProjectEntityHandler.coffee | 4 ++-- .../unit/coffee/Editor/EditorControllerTests.coffee | 6 +++--- .../coffee/Project/ProjectCreationHandlerTests.coffee | 5 +++-- .../coffee/Project/ProjectEntityHandlerTests.coffee | 11 ++++++----- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/services/web/app/coffee/Features/Editor/EditorController.coffee b/services/web/app/coffee/Features/Editor/EditorController.coffee index a43d6f0447..438711105e 100644 --- a/services/web/app/coffee/Features/Editor/EditorController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorController.coffee @@ -52,7 +52,7 @@ module.exports = EditorController = fileName = fileName.trim() logger.log {project_id, folder_id, fileName, path}, "sending new file to project" Metrics.inc "editor.add-file" - ProjectEntityHandler.addFile project_id, folder_id, fileName, path, (err, fileRef, folder_id)=> + ProjectEntityHandler.addFile project_id, folder_id, fileName, path, null, (err, fileRef, folder_id)=> if err? logger.err err:err, project_id:project_id, folder_id:folder_id, fileName:fileName, "error adding file without lock" return callback(err) diff --git a/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee b/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee index a38b214a9e..7fef1a8a54 100644 --- a/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee @@ -77,7 +77,7 @@ module.exports = ProjectCreationHandler = callback(error) (callback) -> universePath = Path.resolve(__dirname + "/../../../templates/project_files/universe.jpg") - ProjectEntityHandler.addFile project._id, project.rootFolder[0]._id, "universe.jpg", universePath, callback + ProjectEntityHandler.addFile project._id, project.rootFolder[0]._id, "universe.jpg", universePath, owner_id, callback ], (error) -> callback(error, project) diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index 4bfbc0e30c..db88b44ba4 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -193,12 +193,12 @@ module.exports = ProjectEntityHandler = return callback(error) if error? ProjectEntityHandler.addDoc project_id, null, name, lines, callback - addFile: (project_id, folder_id, fileName, path, callback = (error, fileRef, folder_id) ->)-> + addFile: (project_id, folder_id, fileName, path, userId, callback = (error, fileRef, folder_id) ->)-> ProjectGetter.getProjectWithOnlyFolders project_id, (err, project) -> if err? logger.err project_id:project_id, err:err, "error getting project for add file" return callback(err) - ProjectEntityHandler.addFileWithProject project, folder_id, fileName, path, null, callback + ProjectEntityHandler.addFileWithProject project, folder_id, fileName, path, userId, callback addFileWithProject: (project, folder_id, fileName, path, userId, callback = (error, fileRef, folder_id) ->)-> project_id = project._id diff --git a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee index ae5e8d79e3..f84dc04c10 100644 --- a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee +++ b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee @@ -196,13 +196,13 @@ describe "EditorController", -> @stream = new ArrayBuffer() it 'should add the folder using the project entity handler', (done)-> - @ProjectEntityHandler.addFile = sinon.stub().callsArgWith(4) + @ProjectEntityHandler.addFile = sinon.stub().callsArgWith(5) @EditorController.addFileWithoutLock @project_id, @folder_id, @fileName, @stream, @source, => @ProjectEntityHandler.addFile.calledWith(@project_id, @folder_id).should.equal true done() it 'should send the update of a new folder out to the users in the project', (done)-> - @ProjectEntityHandler.addFile = sinon.stub().callsArgWith(4, null, @file, @folder_id) + @ProjectEntityHandler.addFile = sinon.stub().callsArgWith(5, null, @file, @folder_id) @EditorController.addFileWithoutLock @project_id, @folder_id, @fileName, @stream, @source, => @EditorRealTimeController.emitToRoom @@ -211,7 +211,7 @@ describe "EditorController", -> done() it "should return the file in the callback", (done) -> - @ProjectEntityHandler.addFile = sinon.stub().callsArgWith(4, null, @file, @folder_id) + @ProjectEntityHandler.addFile = sinon.stub().callsArgWith(5, null, @file, @folder_id) @EditorController.addFileWithoutLock @project_id, @folder_id, @fileName, @stream, @source, (error, file) => file.should.equal @file done() diff --git a/services/web/test/unit/coffee/Project/ProjectCreationHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectCreationHandlerTests.coffee index 5c32db63d3..1b010a035c 100644 --- a/services/web/test/unit/coffee/Project/ProjectCreationHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectCreationHandlerTests.coffee @@ -34,7 +34,7 @@ describe 'ProjectCreationHandler', -> {@name} = options @ProjectEntityHandler = addDoc: sinon.stub().callsArgWith(4, null, {_id: docId}) - addFile: sinon.stub().callsArg(4) + addFile: sinon.stub().callsArg(5) setRootDoc: sinon.stub().callsArg(2) @ProjectDetailsHandler = validateProjectName: sinon.stub().yields() @@ -192,7 +192,8 @@ describe 'ProjectCreationHandler', -> @ProjectEntityHandler.addFile .calledWith( project_id, rootFolderId, "universe.jpg", - Path.resolve(__dirname + "/../../../../app/templates/project_files/universe.jpg") + Path.resolve(__dirname + "/../../../../app/templates/project_files/universe.jpg"), + ownerId ) .should.equal true diff --git a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee index ca968f10a0..22e2926934 100644 --- a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee @@ -534,7 +534,7 @@ describe 'ProjectEntityHandler', -> filePath.should.equal @filePath done() - @ProjectEntityHandler.addFile project_id, folder_id, fileName, @filePath, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.addFile project_id, folder_id, fileName, @filePath, userId, (err, fileRef, parentFolder)-> it 'should put file into folder by calling put element', (done)-> @ProjectEntityHandler._putElement = (passedProject, passedFolder_id, passedFileRef, passedType, callback)-> @@ -544,10 +544,10 @@ describe 'ProjectEntityHandler', -> passedType.should.equal 'file' done() - @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, userId, (err, fileRef, parentFolder)-> it 'should return doc and parent folder', (done)-> - @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, userId, (err, fileRef, parentFolder)-> parentFolder.should.equal folder_id fileRef.name.should.equal fileName done() @@ -567,11 +567,12 @@ describe 'ProjectEntityHandler', -> options.rev.should.equal 0 done() - @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, userId, (err, fileRef, parentFolder)-> it "should should send the change in project structure to the doc updater", (done) -> @documentUpdaterHandler.updateProjectStructure = (project_id, user_id, oldDocs, newDocs, oldFiles, newFiles) => project_id.should.equal project_id + user_id.should.equal user_id newFiles.length.should.equal 1 newFile = newFiles[0] newFile.file.name.should.equal fileName @@ -579,7 +580,7 @@ describe 'ProjectEntityHandler', -> newFile.url.should.equal @fileUrl done() - @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, () -> + @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, userId, () -> describe 'replacing a file', -> From 953dba0eded80ad0d6524e9e74df398974f6382b Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Mon, 13 Nov 2017 12:20:14 +0000 Subject: [PATCH 05/27] pass userId into Editorcontroller.addFile / addFileWithoutLock --- .../Features/Editor/EditorController.coffee | 8 +++---- .../ThirdPartyDataStore/UpdateMerger.coffee | 6 ++--- .../Uploads/FileSystemImportManager.coffee | 4 ++-- .../Editor/EditorControllerTests.coffee | 24 +++++++++---------- .../UpdateMergerTests.coffee | 12 +++++----- .../FileSystemImportManagerTests.coffee | 8 +++---- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/services/web/app/coffee/Features/Editor/EditorController.coffee b/services/web/app/coffee/Features/Editor/EditorController.coffee index 438711105e..d2fa43ad62 100644 --- a/services/web/app/coffee/Features/Editor/EditorController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorController.coffee @@ -39,20 +39,20 @@ module.exports = EditorController = EditorRealTimeController.emitToRoom(project_id, 'reciveNewDoc', folder_id, doc, source) callback(err, doc) - addFile: (project_id, folder_id, fileName, path, source, callback = (error, file)->)-> + addFile: (project_id, folder_id, fileName, path, source, user_id, callback = (error, file)->)-> LockManager.getLock project_id, (err)-> if err? logger.err err:err, project_id:project_id, source:source, "could not get lock to addFile" return callback(err) - EditorController.addFileWithoutLock project_id, folder_id, fileName, path, source, (error, file)-> + EditorController.addFileWithoutLock project_id, folder_id, fileName, path, source, user_id, (error, file)-> LockManager.releaseLock project_id, -> callback(error, file) - addFileWithoutLock: (project_id, folder_id, fileName, path, source, callback = (error, file)->)-> + addFileWithoutLock: (project_id, folder_id, fileName, path, source, user_id, callback = (error, file)->)-> fileName = fileName.trim() logger.log {project_id, folder_id, fileName, path}, "sending new file to project" Metrics.inc "editor.add-file" - ProjectEntityHandler.addFile project_id, folder_id, fileName, path, null, (err, fileRef, folder_id)=> + ProjectEntityHandler.addFile project_id, folder_id, fileName, path, user_id, (err, fileRef, folder_id)=> if err? logger.err err:err, project_id:project_id, folder_id:folder_id, fileName:fileName, "error adding file without lock" return callback(err) diff --git a/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee b/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee index bce0befe22..e78c1bd1e4 100644 --- a/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee +++ b/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee @@ -28,7 +28,7 @@ module.exports = FileTypeManager.isBinary path, fsPath, (err, isFile)-> return callback(err) if err? if isFile - self.p.processFile project_id, elementId, fsPath, path, source, callback + self.p.processFile project_id, elementId, fsPath, path, source, user_id, callback else self.p.processDoc project_id, elementId, user_id, fsPath, path, source, callback @@ -59,7 +59,7 @@ module.exports = return callback(err) editorController.addDoc project_id, folder._id, fileName, docLines, source, callback - processFile: (project_id, file_id, fsPath, path, source, callback)-> + processFile: (project_id, file_id, fsPath, path, source, user_id, callback)-> finish = (err)-> logger.log project_id:project_id, file_id:file_id, path:path, "completed processing file update from tpds" callback(err) @@ -71,7 +71,7 @@ module.exports = else if file_id? editorController.replaceFile project_id, file_id, fsPath, source, finish else - editorController.addFile project_id, folder?._id, fileName, fsPath, source, finish + editorController.addFile project_id, folder?._id, fileName, fsPath, source, user_id, finish writeStreamToDisk: (project_id, file_id, stream, callback = (err, fsPath)->)-> if !file_id? diff --git a/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee b/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee index f491807e9d..a1ddc2e59b 100644 --- a/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee +++ b/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee @@ -39,7 +39,7 @@ module.exports = FileSystemImportManager = return callback("path is symlink") if !replace - EditorController.addFileWithoutLock project_id, folder_id, name, path, "upload", callback + EditorController.addFileWithoutLock project_id, folder_id, name, path, "upload", user_id, callback else ProjectLocator.findElement project_id: project_id, element_id: folder_id, type: "folder", (error, folder) -> return callback(error) if error? @@ -52,7 +52,7 @@ module.exports = FileSystemImportManager = if existingFile? EditorController.replaceFile project_id, existingFile._id, path, "upload", callback else - EditorController.addFileWithoutLock project_id, folder_id, name, path, "upload", callback + EditorController.addFileWithoutLock project_id, folder_id, name, path, "upload", user_id, callback addFolder: (user_id, project_id, folder_id, name, path, replace, callback = (error)-> ) -> FileSystemImportManager._isSafeOnFileSystem path, (err, isSafe)-> diff --git a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee index f84dc04c10..7738d11b3b 100644 --- a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee +++ b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee @@ -197,14 +197,14 @@ describe "EditorController", -> it 'should add the folder using the project entity handler', (done)-> @ProjectEntityHandler.addFile = sinon.stub().callsArgWith(5) - @EditorController.addFileWithoutLock @project_id, @folder_id, @fileName, @stream, @source, => - @ProjectEntityHandler.addFile.calledWith(@project_id, @folder_id).should.equal true + @EditorController.addFileWithoutLock @project_id, @folder_id, @fileName, @stream, @source, @user_id, => + @ProjectEntityHandler.addFile.calledWith(@project_id, @folder_id, @fileName, @stream, @user_id).should.equal true done() it 'should send the update of a new folder out to the users in the project', (done)-> @ProjectEntityHandler.addFile = sinon.stub().callsArgWith(5, null, @file, @folder_id) - @EditorController.addFileWithoutLock @project_id, @folder_id, @fileName, @stream, @source, => + @EditorController.addFileWithoutLock @project_id, @folder_id, @fileName, @stream, @source, @user_id, => @EditorRealTimeController.emitToRoom .calledWith(@project_id, "reciveNewFile", @folder_id, @file, @source) .should.equal true @@ -212,7 +212,7 @@ describe "EditorController", -> it "should return the file in the callback", (done) -> @ProjectEntityHandler.addFile = sinon.stub().callsArgWith(5, null, @file, @folder_id) - @EditorController.addFileWithoutLock @project_id, @folder_id, @fileName, @stream, @source, (error, file) => + @EditorController.addFileWithoutLock @project_id, @folder_id, @fileName, @stream, @source, @user_id, (error, file) => file.should.equal @file done() @@ -222,28 +222,28 @@ describe "EditorController", -> beforeEach -> @LockManager.getLock.callsArgWith(1) @LockManager.releaseLock.callsArgWith(1) - @EditorController.addFileWithoutLock = sinon.stub().callsArgWith(5) + @EditorController.addFileWithoutLock = sinon.stub().callsArgWith(6) it "should call addFileWithoutLock", (done)-> - @EditorController.addFile @project_id, @folder_id, @fileName, @stream, @source, (error, file) => - @EditorController.addFileWithoutLock.calledWith(@project_id, @folder_id, @fileName, @stream, @source).should.equal true + @EditorController.addFile @project_id, @folder_id, @fileName, @stream, @source, @user_id, (error, file) => + @EditorController.addFileWithoutLock.calledWith(@project_id, @folder_id, @fileName, @stream, @source, @user_id).should.equal true done() it "should take the lock", (done)-> - @EditorController.addFile @project_id, @folder_id, @fileName, @stream, @source, (error, file) => + @EditorController.addFile @project_id, @folder_id, @fileName, @stream, @source, @user_id, (error, file) => @LockManager.getLock.calledWith(@project_id).should.equal true done() it "should release the lock", (done)-> - @EditorController.addFile @project_id, @folder_id, @fileName, @stream, @source, (error, file) => + @EditorController.addFile @project_id, @folder_id, @fileName, @stream, @source, @user_id, (error, file) => @LockManager.releaseLock.calledWith(@project_id).should.equal true done() it "should error if it can't cat the lock", (done)-> @LockManager.getLock = sinon.stub().callsArgWith(1, "timed out") - @EditorController.addFile @project_id, @folder_id, @fileName, @stream, @source, (err, file) => - expect(err).to.exist - err.should.equal "timed out" + @EditorController.addFile @project_id, @folder_id, @fileName, @stream, @source, @user_id, (error, file) => + expect(error).to.exist + error.should.equal "timed out" done() diff --git a/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee b/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee index 1b00f20bde..c2d3816a5c 100644 --- a/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee +++ b/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee @@ -63,11 +63,11 @@ describe 'UpdateMerger :', -> file_id = "1231" @projectLocator.findElementByPath = (_, __, cb)->cb(null, {_id:file_id}) @FileTypeManager.isBinary.callsArgWith(2, null, true) - @updateMerger.p.processFile = sinon.stub().callsArgWith(5) + @updateMerger.p.processFile = sinon.stub().callsArgWith(6) filePath = "/folder/file1.png" @updateMerger.mergeUpdate @user_id, @project_id, filePath, @update, @source, => - @updateMerger.p.processFile.calledWith(@project_id, file_id, @fsPath, filePath, @source).should.equal true + @updateMerger.p.processFile.calledWith(@project_id, file_id, @fsPath, filePath, @source, @user_id).should.equal true @FileTypeManager.isBinary.calledWith(filePath, @fsPath).should.equal true @fs.unlink.calledWith(@fsPath).should.equal true done() @@ -114,22 +114,22 @@ describe 'UpdateMerger :', -> @folder = _id: @folder_id @fileName = "file.png" @fsPath = "fs/path.tex" - @editorController.addFile = sinon.stub().callsArg(5) + @editorController.addFile = sinon.stub().callsArg(6) @editorController.replaceFile = sinon.stub().callsArg(4) @editorController.deleteEntity = sinon.stub() @editorController.mkdirp = sinon.stub().withArgs(@project_id).callsArgWith(2, null, [@folder], @folder) @updateMerger.p.writeStreamToDisk = sinon.stub().withArgs(@project_id, @file_id, @update).callsArgWith(3, null, @fsPath) it 'should replace file if the file already exists', (done)-> - @updateMerger.p.processFile @project_id, @file_id, @fsPath, @path, @source, => + @updateMerger.p.processFile @project_id, @file_id, @fsPath, @path, @source, @user_id, => @editorController.addFile.called.should.equal false @editorController.replaceFile.calledWith(@project_id, @file_id, @fsPath, @source).should.equal true done() it 'should call add file if the file does not exist', (done)-> - @updateMerger.p.processFile @project_id, undefined, @fsPath, @path, @source, => + @updateMerger.p.processFile @project_id, undefined, @fsPath, @path, @source, @user_id, => @editorController.mkdirp.calledWith(@project_id, "folder/").should.equal true - @editorController.addFile.calledWith(@project_id, @folder_id, @fileName, @fsPath, @source).should.equal true + @editorController.addFile.calledWith(@project_id, @folder_id, @fileName, @fsPath, @source, @user_id).should.equal true @editorController.replaceFile.called.should.equal false done() diff --git a/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee b/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee index a33775446f..032b60b261 100644 --- a/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee +++ b/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee @@ -114,12 +114,12 @@ describe "FileSystemImportManager", -> describe "addFile with replace set to false", -> beforeEach -> - @EditorController.addFileWithoutLock = sinon.stub().callsArg(5) + @EditorController.addFileWithoutLock = sinon.stub().callsArg(6) @FileSystemImportManager._isSafeOnFileSystem = sinon.stub().callsArgWith(1, null, true) @FileSystemImportManager.addFile @user_id, @project_id, @folder_id, @name, @path_on_disk, false, @callback it "should add the file", -> - @EditorController.addFileWithoutLock.calledWith(@project_id, @folder_id, @name, @path_on_disk, "upload") + @EditorController.addFileWithoutLock.calledWith(@project_id, @folder_id, @name, @path_on_disk, "upload", @user_id) .should.equal true describe "addFile with symlink", -> @@ -144,7 +144,7 @@ describe "FileSystemImportManager", -> } @FileSystemImportManager._isSafeOnFileSystem = sinon.stub().callsArgWith(1, null, true) @ProjectLocator.findElement = sinon.stub().callsArgWith(1, null, @folder) - @EditorController.addFileWithoutLock = sinon.stub().callsArg(5) + @EditorController.addFileWithoutLock = sinon.stub().callsArg(6) @FileSystemImportManager.addFile @user_id, @project_id, @folder_id, @name, @path_on_disk, true, @callback it "should look up the folder", -> @@ -153,7 +153,7 @@ describe "FileSystemImportManager", -> .should.equal true it "should add the file", -> - @EditorController.addFileWithoutLock.calledWith(@project_id, @folder_id, @name, @path_on_disk, "upload") + @EditorController.addFileWithoutLock.calledWith(@project_id, @folder_id, @name, @path_on_disk, "upload", @user_id) .should.equal true describe "when the file does exist", -> From ef68c6a5312f136087fa9914d03224c133776e00 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Tue, 14 Nov 2017 16:47:15 +0000 Subject: [PATCH 06/27] avoid N+1 lookups in DocumentUpdaterHandler --- .../DocumentUpdaterHandler.coffee | 17 +++++++++-------- .../DocumentUpdaterHandlerTests.coffee | 6 +++--- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee index 77cbe379b9..3f5972bdc7 100644 --- a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee +++ b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee @@ -233,22 +233,23 @@ module.exports = DocumentUpdaterHandler = _getRenameUpdates: (entityType, oldEntities, newEntities) -> updates = [] - for oldEntity in oldEntities - id = oldEntity[entityType]._id - newEntity = _.find newEntities, (newEntity) -> - newEntity[entityType]._id.toString() == id.toString() + oldEntitiesHash = _.indexBy oldEntities, (entity) -> entity[entityType]._id.toString() + newEntitiesHash = _.indexBy newEntities, (entity) -> entity[entityType]._id.toString() + for id, oldEntity of oldEntitiesHash + newEntity = newEntitiesHash[id] + + # renamed entities if newEntity.path != oldEntity.path updates.push id: id pathname: oldEntity.path newPathname: newEntity.path - for newEntity in newEntities - id = newEntity[entityType]._id - oldEntity = _.find oldEntities, (oldEntity) -> - oldEntity[entityType]._id.toString() == id.toString() + for id, newEntity of newEntitiesHash + oldEntity = oldEntitiesHash[id] + # removed entities if !oldEntity? updates.push id: id diff --git a/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee b/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee index d0b9106ede..9f1e292b2c 100644 --- a/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee +++ b/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee @@ -427,7 +427,7 @@ describe 'DocumentUpdaterHandler', -> @newFiles = [] docUpdates = [ - id: @docIdB, + id: @docIdB.toString(), pathname: "/old_b" newPathname: "/new_b" ] @@ -449,7 +449,7 @@ describe 'DocumentUpdaterHandler', -> @newFiles = [] docUpdates = [ - id: @docId, + id: @docId.toString(), pathname: "/foo" docLines: 'a\nb' url: undefined @@ -472,7 +472,7 @@ describe 'DocumentUpdaterHandler', -> ] fileUpdates = [ - id: @fileId, + id: @fileId.toString(), pathname: "/bar" url: 'filestore.example.com/file' docLines: undefined From acda4c2295fe922c63da47d6ee990f21ba170067 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Tue, 14 Nov 2017 16:52:53 +0000 Subject: [PATCH 07/27] remove inline requires from ProjectEntityHandler --- .../coffee/Features/Project/ProjectEntityHandler.coffee | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index db88b44ba4..09c64c7ca9 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -16,7 +16,7 @@ projectUpdateHandler = require('./ProjectUpdateHandler') DocstoreManager = require "../Docstore/DocstoreManager" ProjectGetter = require "./ProjectGetter" CooldownManager = require '../Cooldown/CooldownManager' - +documentUpdaterHandler = require('../../Features/DocumentUpdater/DocumentUpdaterHandler') module.exports = ProjectEntityHandler = getAllFolders: (project_id, callback) -> @@ -106,7 +106,6 @@ module.exports = ProjectEntityHandler = flushProjectToThirdPartyDataStore: (project_id, callback) -> self = @ logger.log project_id:project_id, "flushing project to tpds" - documentUpdaterHandler = require('../../Features/DocumentUpdater/DocumentUpdaterHandler') documentUpdaterHandler.flushProjectToMongo project_id, (error) -> return callback(error) if error? ProjectGetter.getProject project_id, {name:true}, (error, project) -> @@ -181,7 +180,6 @@ module.exports = ProjectEntityHandler = doc: doc path: result?.path?.fileSystem docLines: docLines.join('\n') - documentUpdaterHandler = require('../../Features/DocumentUpdater/DocumentUpdaterHandler') documentUpdaterHandler.updateProjectStructure project_id, null, [], [newDoc], [], [], (error) -> return callback(error) if error? callback null, doc, folder_id @@ -220,7 +218,6 @@ module.exports = ProjectEntityHandler = file: fileRef path: result?.path?.fileSystem url: fileStoreUrl - documentUpdaterHandler = require('../../Features/DocumentUpdater/DocumentUpdaterHandler') documentUpdaterHandler.updateProjectStructure project_id, userId, [], [], [], [newFile], (error) -> return callback(error) if error? callback null, fileRef, folder_id @@ -398,7 +395,6 @@ module.exports = ProjectEntityHandler = self.getAllEntitiesFromProject newProject, (error, newDocs, newFiles ) => return callback(error) if error? - documentUpdaterHandler = require('../../Features/DocumentUpdater/DocumentUpdaterHandler') documentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback _checkValidMove: (project, entityType, entityPath, destFolderId, callback = (error) ->) -> @@ -456,7 +452,6 @@ module.exports = ProjectEntityHandler = return callback(error) if error? ProjectEntityHandler.getAllEntitiesFromProject newProject, (error, newDocs, newFiles) => return callback(error) if error? - documentUpdaterHandler = require('../../Features/DocumentUpdater/DocumentUpdaterHandler') documentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback _cleanUpEntity: (project, entity, entityType, callback = (error) ->) -> @@ -480,7 +475,7 @@ module.exports = ProjectEntityHandler = unsetRootDocIfRequired (error) -> return callback(error) if error? - require('../../Features/DocumentUpdater/DocumentUpdaterHandler').deleteDoc project_id, doc_id, (error) -> + documentUpdaterHandler.deleteDoc project_id, doc_id, (error) -> return callback(error) if error? ProjectEntityHandler._insertDeletedDocReference project._id, doc, (error) -> return callback(error) if error? From 62f88402e86b5d85d0a8d2b0ce324c245924acb3 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Wed, 15 Nov 2017 15:07:55 +0000 Subject: [PATCH 08/27] fix DocumentUpdaterHandler casing --- .../Features/Project/ProjectEntityHandler.coffee | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index 09c64c7ca9..ee55252761 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -16,7 +16,7 @@ projectUpdateHandler = require('./ProjectUpdateHandler') DocstoreManager = require "../Docstore/DocstoreManager" ProjectGetter = require "./ProjectGetter" CooldownManager = require '../Cooldown/CooldownManager' -documentUpdaterHandler = require('../../Features/DocumentUpdater/DocumentUpdaterHandler') +DocumentUpdaterHandler = require('../../Features/DocumentUpdater/DocumentUpdaterHandler') module.exports = ProjectEntityHandler = getAllFolders: (project_id, callback) -> @@ -106,7 +106,7 @@ module.exports = ProjectEntityHandler = flushProjectToThirdPartyDataStore: (project_id, callback) -> self = @ logger.log project_id:project_id, "flushing project to tpds" - documentUpdaterHandler.flushProjectToMongo project_id, (error) -> + DocumentUpdaterHandler.flushProjectToMongo project_id, (error) -> return callback(error) if error? ProjectGetter.getProject project_id, {name:true}, (error, project) -> return callback(error) if error? @@ -180,7 +180,7 @@ module.exports = ProjectEntityHandler = doc: doc path: result?.path?.fileSystem docLines: docLines.join('\n') - documentUpdaterHandler.updateProjectStructure project_id, null, [], [newDoc], [], [], (error) -> + DocumentUpdaterHandler.updateProjectStructure project_id, null, [], [newDoc], [], [], (error) -> return callback(error) if error? callback null, doc, folder_id @@ -218,7 +218,7 @@ module.exports = ProjectEntityHandler = file: fileRef path: result?.path?.fileSystem url: fileStoreUrl - documentUpdaterHandler.updateProjectStructure project_id, userId, [], [], [], [newFile], (error) -> + DocumentUpdaterHandler.updateProjectStructure project_id, userId, [], [], [], [newFile], (error) -> return callback(error) if error? callback null, fileRef, folder_id @@ -395,7 +395,7 @@ module.exports = ProjectEntityHandler = self.getAllEntitiesFromProject newProject, (error, newDocs, newFiles ) => return callback(error) if error? - documentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback + DocumentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback _checkValidMove: (project, entityType, entityPath, destFolderId, callback = (error) ->) -> return callback() if !entityType.match(/folder/) @@ -452,7 +452,7 @@ module.exports = ProjectEntityHandler = return callback(error) if error? ProjectEntityHandler.getAllEntitiesFromProject newProject, (error, newDocs, newFiles) => return callback(error) if error? - documentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback + DocumentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback _cleanUpEntity: (project, entity, entityType, callback = (error) ->) -> if(entityType.indexOf("file") != -1) @@ -475,7 +475,7 @@ module.exports = ProjectEntityHandler = unsetRootDocIfRequired (error) -> return callback(error) if error? - documentUpdaterHandler.deleteDoc project_id, doc_id, (error) -> + DocumentUpdaterHandler.deleteDoc project_id, doc_id, (error) -> return callback(error) if error? ProjectEntityHandler._insertDeletedDocReference project._id, doc, (error) -> return callback(error) if error? From bfd22899a02d6db1e370dec70408ae263dd31a0b Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Wed, 15 Nov 2017 15:12:59 +0000 Subject: [PATCH 09/27] fix DocumentUpdaterHandler.updateProjectStructure --- .../DocumentUpdaterHandler.coffee | 18 +++++++----------- .../DocumentUpdaterHandlerTests.coffee | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee index 3f5972bdc7..fc4b5c452b 100644 --- a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee +++ b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee @@ -236,26 +236,22 @@ module.exports = DocumentUpdaterHandler = oldEntitiesHash = _.indexBy oldEntities, (entity) -> entity[entityType]._id.toString() newEntitiesHash = _.indexBy newEntities, (entity) -> entity[entityType]._id.toString() - for id, oldEntity of oldEntitiesHash - newEntity = newEntitiesHash[id] - - # renamed entities - if newEntity.path != oldEntity.path - updates.push - id: id - pathname: oldEntity.path - newPathname: newEntity.path - for id, newEntity of newEntitiesHash oldEntity = oldEntitiesHash[id] - # removed entities if !oldEntity? + # entity added updates.push id: id pathname: newEntity.path docLines: newEntity.docLines url: newEntity.url + else if newEntity.path != oldEntity.path + # entity renamed + updates.push + id: id + pathname: oldEntity.path + newPathname: newEntity.path updates diff --git a/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee b/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee index 9f1e292b2c..99214749d6 100644 --- a/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee +++ b/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee @@ -483,3 +483,18 @@ describe 'DocumentUpdaterHandler', -> .calledWith(url: @url, json: {docUpdates: [], fileUpdates, userId: @user_id}) .should.equal true done() + + describe "when a doc has been deleted", -> + it 'should do nothing', (done) -> + @docId = new ObjectId() + @oldDocs = [ + { path: '/foo', docLines: 'a\nb', doc: _id: @docId } + ] + @newDocs = [] + @oldFiles = [] + @newFiles = [] + + @handler.updateProjectStructure @project_id, @user_id, @oldDocs, @newDocs, @oldFiles, @newFiles, () => + @request.post.called.should.equal false + done() + From 300f76bc5c12a720b021018fd3265f6948b04499 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Thu, 23 Nov 2017 15:18:43 +0000 Subject: [PATCH 10/27] pass user_id into ProjectEntityHandler.addDoc / addDocWithProject --- .../app/coffee/Features/Editor/EditorController.coffee | 2 +- .../coffee/Features/Project/ProjectCreationHandler.coffee | 6 +++--- .../app/coffee/Features/Project/ProjectDuplicator.coffee | 2 +- .../coffee/Features/Project/ProjectEntityHandler.coffee | 8 ++++---- .../test/unit/coffee/Editor/EditorControllerTests.coffee | 6 +++--- .../coffee/Project/ProjectCreationHandlerTests.coffee | 8 ++++---- .../unit/coffee/Project/ProjectDuplicatorTests.coffee | 6 +++--- .../unit/coffee/Project/ProjectEntityHandlerTests.coffee | 4 ++-- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/services/web/app/coffee/Features/Editor/EditorController.coffee b/services/web/app/coffee/Features/Editor/EditorController.coffee index d2fa43ad62..6bafac08da 100644 --- a/services/web/app/coffee/Features/Editor/EditorController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorController.coffee @@ -32,7 +32,7 @@ module.exports = EditorController = docName = docName.trim() logger.log {project_id, folder_id, docName, source}, "sending new doc to project" Metrics.inc "editor.add-doc" - ProjectEntityHandler.addDoc project_id, folder_id, docName, docLines, (err, doc, folder_id)=> + ProjectEntityHandler.addDoc project_id, folder_id, docName, docLines, null, (err, doc, folder_id)=> if err? logger.err err:err, project_id:project_id, docName:docName, "error adding doc without lock" return callback(err) diff --git a/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee b/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee index 7fef1a8a54..cd78cddc09 100644 --- a/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectCreationHandler.coffee @@ -52,7 +52,7 @@ module.exports = ProjectCreationHandler = return callback(error) if error? self._buildTemplate "mainbasic.tex", owner_id, projectName, (error, docLines)-> return callback(error) if error? - ProjectEntityHandler.addDoc project._id, project.rootFolder[0]._id, "main.tex", docLines, (error, doc)-> + ProjectEntityHandler.addDoc project._id, project.rootFolder[0]._id, "main.tex", docLines, owner_id, (error, doc)-> if error? logger.err err:error, "error adding doc when creating basic project" return callback(error) @@ -67,13 +67,13 @@ module.exports = ProjectCreationHandler = (callback) -> self._buildTemplate "main.tex", owner_id, projectName, (error, docLines)-> return callback(error) if error? - ProjectEntityHandler.addDoc project._id, project.rootFolder[0]._id, "main.tex", docLines, (error, doc)-> + ProjectEntityHandler.addDoc project._id, project.rootFolder[0]._id, "main.tex", docLines, owner_id, (error, doc)-> return callback(error) if error? ProjectEntityHandler.setRootDoc project._id, doc._id, callback (callback) -> self._buildTemplate "references.bib", owner_id, projectName, (error, docLines)-> return callback(error) if error? - ProjectEntityHandler.addDoc project._id, project.rootFolder[0]._id, "references.bib", docLines, (error, doc)-> + ProjectEntityHandler.addDoc project._id, project.rootFolder[0]._id, "references.bib", docLines, owner_id, (error, doc)-> callback(error) (callback) -> universePath = Path.resolve(__dirname + "/../../../templates/project_files/universe.jpg") diff --git a/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee b/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee index d945326395..6f7f551bc6 100644 --- a/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee +++ b/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee @@ -21,7 +21,7 @@ module.exports = ProjectDuplicator = if !doc?._id? return callback() content = docContents[doc._id.toString()] - projectEntityHandler.addDocWithProject newProject, desFolder._id, doc.name, content.lines, (err, newDoc)-> + projectEntityHandler.addDocWithProject newProject, desFolder._id, doc.name, content.lines, null, (err, newDoc)-> if err? logger.err err:err, "error copying doc" return callback(err) diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index ee55252761..d004ad0cce 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -149,14 +149,14 @@ module.exports = ProjectEntityHandler = else DocstoreManager.getDoc project_id, doc_id, options, callback - addDoc: (project_id, folder_id, docName, docLines, callback = (error, doc, folder_id) ->)=> + addDoc: (project_id, folder_id, docName, docLines, userId, callback = (error, doc, folder_id) ->)=> ProjectGetter.getProjectWithOnlyFolders project_id, (err, project) -> if err? logger.err project_id:project_id, err:err, "error getting project for add doc" return callback(err) - ProjectEntityHandler.addDocWithProject project, folder_id, docName, docLines, callback + ProjectEntityHandler.addDocWithProject project, folder_id, docName, docLines, userId, callback - addDocWithProject: (project, folder_id, docName, docLines, callback = (error, doc, folder_id) ->)=> + addDocWithProject: (project, folder_id, docName, docLines, userId, callback = (error, doc, folder_id) ->)=> project_id = project._id logger.log project_id: project_id, folder_id: folder_id, doc_name: docName, "adding doc to project with project" confirmFolder project, folder_id, (folder_id)=> @@ -180,7 +180,7 @@ module.exports = ProjectEntityHandler = doc: doc path: result?.path?.fileSystem docLines: docLines.join('\n') - DocumentUpdaterHandler.updateProjectStructure project_id, null, [], [newDoc], [], [], (error) -> + DocumentUpdaterHandler.updateProjectStructure project_id, userId, [], [newDoc], [], [], (error) -> return callback(error) if error? callback null, doc, folder_id diff --git a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee index 7738d11b3b..cc2d1e9c69 100644 --- a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee +++ b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee @@ -131,14 +131,14 @@ describe "EditorController", -> @docLines = ["1234","dskl"] it 'should add the doc using the project entity handler', (done)-> - mock = sinon.mock(@ProjectEntityHandler).expects("addDoc").withArgs(@project_id, @folder_id, @docName, @docLines).callsArg(4) + mock = sinon.mock(@ProjectEntityHandler).expects("addDoc").withArgs(@project_id, @folder_id, @docName, @docLines).callsArg(5) @EditorController.addDocWithoutLock @project_id, @folder_id, @docName, @docLines, @source, -> mock.verify() done() it 'should send the update out to the users in the project', (done)-> - @ProjectEntityHandler.addDoc = sinon.stub().callsArgWith(4, null, @doc, @folder_id) + @ProjectEntityHandler.addDoc = sinon.stub().callsArgWith(5, null, @doc, @folder_id) @EditorController.addDocWithoutLock @project_id, @folder_id, @docName, @docLines, @source, => @EditorRealTimeController.emitToRoom @@ -147,7 +147,7 @@ describe "EditorController", -> done() it 'should return the doc to the callback', (done) -> - @ProjectEntityHandler.addDoc = sinon.stub().callsArgWith(4, null, @doc, @folder_id) + @ProjectEntityHandler.addDoc = sinon.stub().callsArgWith(5, null, @doc, @folder_id) @EditorController.addDocWithoutLock @project_id, @folder_id, @docName, @docLines, @source, (error, doc) => doc.should.equal @doc done() diff --git a/services/web/test/unit/coffee/Project/ProjectCreationHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectCreationHandlerTests.coffee index 1b010a035c..470b538bd9 100644 --- a/services/web/test/unit/coffee/Project/ProjectCreationHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectCreationHandlerTests.coffee @@ -33,7 +33,7 @@ describe 'ProjectCreationHandler', -> constructor:(options)-> {@name} = options @ProjectEntityHandler = - addDoc: sinon.stub().callsArgWith(4, null, {_id: docId}) + addDoc: sinon.stub().callsArgWith(5, null, {_id: docId}) addFile: sinon.stub().callsArg(5) setRootDoc: sinon.stub().callsArg(2) @ProjectDetailsHandler = @@ -149,7 +149,7 @@ describe 'ProjectCreationHandler', -> .should.equal true it 'should insert main.tex', -> - @ProjectEntityHandler.addDoc.calledWith(project_id, rootFolderId, "main.tex", ["mainbasic.tex", "lines"]) + @ProjectEntityHandler.addDoc.calledWith(project_id, rootFolderId, "main.tex", ["mainbasic.tex", "lines"], ownerId) .should.equal true it 'should set the main doc id', -> @@ -180,12 +180,12 @@ describe 'ProjectCreationHandler', -> it 'should insert main.tex', -> @ProjectEntityHandler.addDoc - .calledWith(project_id, rootFolderId, "main.tex", ["main.tex", "lines"]) + .calledWith(project_id, rootFolderId, "main.tex", ["main.tex", "lines"], ownerId) .should.equal true it 'should insert references.bib', -> @ProjectEntityHandler.addDoc - .calledWith(project_id, rootFolderId, "references.bib", ["references.bib", "lines"]) + .calledWith(project_id, rootFolderId, "references.bib", ["references.bib", "lines"], ownerId) .should.equal true it 'should insert universe.jpg', -> diff --git a/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee b/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee index a1101cfbe0..ce6b8b42e3 100644 --- a/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee @@ -64,7 +64,7 @@ describe 'ProjectDuplicator', -> @projectOptionsHandler = setCompiler : sinon.stub() @entityHandler = - addDocWithProject: sinon.stub().callsArgWith(4, null, {name:"somDoc"}) + addDocWithProject: sinon.stub().callsArgWith(5, null, {name:"somDoc"}) copyFileFromExistingProjectWithProject: sinon.stub().callsArgWith(4) setRootDoc: sinon.stub() addFolderWithProject: sinon.stub().callsArgWith(3, null, @newFolder) @@ -112,13 +112,13 @@ describe 'ProjectDuplicator', -> done() it 'should use the same compiler', (done)-> - @entityHandler.addDocWithProject.callsArgWith(4, null, @rootFolder.docs[0]) + @entityHandler.addDocWithProject.callsArgWith(5, null, @rootFolder.docs[0]) @duplicator.duplicate @owner, @old_project_id, "", (err, newProject)=> @projectOptionsHandler.setCompiler.calledWith(@stubbedNewProject._id, @project.compiler).should.equal true done() it 'should use the same root doc', (done)-> - @entityHandler.addDocWithProject.callsArgWith(4, null, @rootFolder.docs[0]) + @entityHandler.addDocWithProject.callsArgWith(5, null, @rootFolder.docs[0]) @duplicator.duplicate @owner, @old_project_id, "", (err, newProject)=> @entityHandler.setRootDoc.calledWith(@stubbedNewProject._id, @rootFolder.docs[0]._id).should.equal true done() diff --git a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee index 22e2926934..506ff0cdb2 100644 --- a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee @@ -457,7 +457,7 @@ describe 'ProjectEntityHandler', -> @tpdsUpdateSender.addDoc = sinon.stub().callsArg(1) @DocstoreManager.updateDoc = sinon.stub().yields(null, true, 0) - @ProjectEntityHandler.addDoc project_id, folder_id, @name, @lines, @callback + @ProjectEntityHandler.addDoc project_id, folder_id, @name, @lines, userId, @callback # Created doc @doc = @ProjectEntityHandler._putElement.args[0][2] @@ -492,7 +492,7 @@ describe 'ProjectEntityHandler', -> path: @path docLines: @lines.join('\n') @documentUpdaterHandler.updateProjectStructure - .calledWith(project_id, null, [], [newDoc], [], []) + .calledWith(project_id, userId, [], [newDoc], [], []) .should.equal true describe "restoreDoc", -> From 7d63939f79a2b48546cc4de0cda5056e3ef45e49 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Thu, 23 Nov 2017 15:23:29 +0000 Subject: [PATCH 11/27] pass owner_id to ProjectEntityHandler.addDoc from ProjectDuplicator --- .../Features/Project/ProjectDuplicator.coffee | 12 ++++++------ .../coffee/Project/ProjectDuplicatorTests.coffee | 16 +++++++++++----- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee b/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee index 6f7f551bc6..730e1e2a1a 100644 --- a/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee +++ b/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee @@ -12,7 +12,7 @@ logger = require("logger-sharelatex") module.exports = ProjectDuplicator = - _copyDocs: (newProject, originalRootDoc, originalFolder, desFolder, docContents, callback)-> + _copyDocs: (owner_id, newProject, originalRootDoc, originalFolder, desFolder, docContents, callback)-> setRootDoc = _.once (doc_id)-> projectEntityHandler.setRootDoc newProject._id, doc_id docs = originalFolder.docs or [] @@ -21,7 +21,7 @@ module.exports = ProjectDuplicator = if !doc?._id? return callback() content = docContents[doc._id.toString()] - projectEntityHandler.addDocWithProject newProject, desFolder._id, doc.name, content.lines, null, (err, newDoc)-> + projectEntityHandler.addDocWithProject newProject, desFolder._id, doc.name, content.lines, owner_id, (err, newDoc)-> if err? logger.err err:err, "error copying doc" return callback(err) @@ -39,7 +39,7 @@ module.exports = ProjectDuplicator = async.parallelLimit jobs, 5, callback - _copyFolderRecursivly: (newProject_id, originalProject_id, originalRootDoc, originalFolder, desFolder, docContents, callback)-> + _copyFolderRecursivly: (owner_id, newProject_id, originalProject_id, originalRootDoc, originalFolder, desFolder, docContents, callback)-> ProjectGetter.getProject newProject_id, {rootFolder:true, name:true}, (err, newProject)-> if err? logger.err project_id:newProject_id, "could not get project" @@ -53,12 +53,12 @@ module.exports = ProjectDuplicator = return cb() projectEntityHandler.addFolderWithProject newProject, desFolder?._id, childFolder.name, (err, newFolder)-> return cb(err) if err? - ProjectDuplicator._copyFolderRecursivly newProject_id, originalProject_id, originalRootDoc, childFolder, newFolder, docContents, cb + ProjectDuplicator._copyFolderRecursivly owner_id, newProject_id, originalProject_id, originalRootDoc, childFolder, newFolder, docContents, cb jobs.push (cb)-> ProjectDuplicator._copyFiles newProject, originalProject_id, originalFolder, desFolder, cb jobs.push (cb)-> - ProjectDuplicator._copyDocs newProject, originalRootDoc, originalFolder, desFolder, docContents, cb + ProjectDuplicator._copyDocs owner_id, newProject, originalRootDoc, originalFolder, desFolder, docContents, cb async.series jobs, callback @@ -90,7 +90,7 @@ module.exports = ProjectDuplicator = projectOptionsHandler.setCompiler newProject._id, originalProject.compiler, -> - ProjectDuplicator._copyFolderRecursivly newProject._id, originalProject_id, originalRootDoc, originalProject.rootFolder[0], newProject.rootFolder[0], docContents, -> + ProjectDuplicator._copyFolderRecursivly owner._id, newProject._id, originalProject_id, originalRootDoc, originalProject.rootFolder[0], newProject.rootFolder[0], docContents, -> if err? logger.err err:err, originalProject_id:originalProject_id, newProjectName:newProjectName, "error cloning project" callback(err, newProject) diff --git a/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee b/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee index ce6b8b42e3..c4be897f9a 100644 --- a/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee @@ -112,13 +112,13 @@ describe 'ProjectDuplicator', -> done() it 'should use the same compiler', (done)-> - @entityHandler.addDocWithProject.callsArgWith(5, null, @rootFolder.docs[0]) + @entityHandler.addDocWithProject.callsArgWith(5, null, @rootFolder.docs[0], @owner._id) @duplicator.duplicate @owner, @old_project_id, "", (err, newProject)=> @projectOptionsHandler.setCompiler.calledWith(@stubbedNewProject._id, @project.compiler).should.equal true done() it 'should use the same root doc', (done)-> - @entityHandler.addDocWithProject.callsArgWith(5, null, @rootFolder.docs[0]) + @entityHandler.addDocWithProject.callsArgWith(5, null, @rootFolder.docs[0], @owner._id) @duplicator.duplicate @owner, @old_project_id, "", (err, newProject)=> @entityHandler.setRootDoc.calledWith(@stubbedNewProject._id, @rootFolder.docs[0]._id).should.equal true done() @@ -139,9 +139,15 @@ describe 'ProjectDuplicator', -> it 'should copy all the docs', (done)-> @duplicator.duplicate @owner, @old_project_id, "", (err, newProject)=> @DocstoreManager.getAllDocs.calledWith(@old_project_id).should.equal true - @entityHandler.addDocWithProject.calledWith(@stubbedNewProject, @stubbedNewProject.rootFolder[0]._id, @doc0.name, @doc0_lines).should.equal true - @entityHandler.addDocWithProject.calledWith(@stubbedNewProject, @newFolder._id, @doc1.name, @doc1_lines).should.equal true - @entityHandler.addDocWithProject.calledWith(@stubbedNewProject, @newFolder._id, @doc2.name, @doc2_lines).should.equal true + @entityHandler.addDocWithProject + .calledWith(@stubbedNewProject, @stubbedNewProject.rootFolder[0]._id, @doc0.name, @doc0_lines, @owner._id) + .should.equal true + @entityHandler.addDocWithProject + .calledWith(@stubbedNewProject, @newFolder._id, @doc1.name, @doc1_lines, @owner._id) + .should.equal true + @entityHandler.addDocWithProject + .calledWith(@stubbedNewProject, @newFolder._id, @doc2.name, @doc2_lines, @owner._id) + .should.equal true done() it 'should copy all the files', (done)-> From e4ca3bc5ad6d50b1baa6f5d15d316b6205cacbee Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Thu, 23 Nov 2017 15:34:24 +0000 Subject: [PATCH 12/27] pass user_id into EditorController.addDocWithoutLock --- .../coffee/Features/Editor/EditorController.coffee | 6 +++--- .../Features/Uploads/FileSystemImportManager.coffee | 4 ++-- .../unit/coffee/Editor/EditorControllerTests.coffee | 8 ++++---- .../Uploads/FileSystemImportManagerTests.coffee | 12 ++++++------ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/services/web/app/coffee/Features/Editor/EditorController.coffee b/services/web/app/coffee/Features/Editor/EditorController.coffee index 6bafac08da..0cc1b8fa11 100644 --- a/services/web/app/coffee/Features/Editor/EditorController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorController.coffee @@ -24,15 +24,15 @@ module.exports = EditorController = if err? logger.err err:err, project_id:project_id, source:source, "could not get lock to addDoc" return callback(err) - EditorController.addDocWithoutLock project_id, folder_id, docName, docLines, source, (error, doc)-> + EditorController.addDocWithoutLock project_id, folder_id, docName, docLines, source, null, (error, doc)-> LockManager.releaseLock project_id, -> callback(error, doc) - addDocWithoutLock: (project_id, folder_id, docName, docLines, source, callback = (error, doc)->)-> + addDocWithoutLock: (project_id, folder_id, docName, docLines, source, user_id, callback = (error, doc)->)-> docName = docName.trim() logger.log {project_id, folder_id, docName, source}, "sending new doc to project" Metrics.inc "editor.add-doc" - ProjectEntityHandler.addDoc project_id, folder_id, docName, docLines, null, (err, doc, folder_id)=> + ProjectEntityHandler.addDoc project_id, folder_id, docName, docLines, user_id, (err, doc, folder_id)=> if err? logger.err err:err, project_id:project_id, docName:docName, "error adding doc without lock" return callback(err) diff --git a/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee b/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee index a1ddc2e59b..cc52b50dc4 100644 --- a/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee +++ b/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee @@ -28,9 +28,9 @@ module.exports = FileSystemImportManager = if existingDoc? EditorController.setDoc project_id, existingDoc._id, user_id, lines, "upload", callback else - EditorController.addDocWithoutLock project_id, folder_id, name, lines, "upload", callback + EditorController.addDocWithoutLock project_id, folder_id, name, lines, "upload", user_id, callback else - EditorController.addDocWithoutLock project_id, folder_id, name, lines, "upload", callback + EditorController.addDocWithoutLock project_id, folder_id, name, lines, "upload", user_id, callback addFile: (user_id, project_id, folder_id, name, path, replace, callback = (error, file)-> )-> FileSystemImportManager._isSafeOnFileSystem path, (err, isSafe)-> diff --git a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee index cc2d1e9c69..3f34c84b1f 100644 --- a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee +++ b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee @@ -133,14 +133,14 @@ describe "EditorController", -> it 'should add the doc using the project entity handler', (done)-> mock = sinon.mock(@ProjectEntityHandler).expects("addDoc").withArgs(@project_id, @folder_id, @docName, @docLines).callsArg(5) - @EditorController.addDocWithoutLock @project_id, @folder_id, @docName, @docLines, @source, -> + @EditorController.addDocWithoutLock @project_id, @folder_id, @docName, @docLines, @source, @user_id, -> mock.verify() done() it 'should send the update out to the users in the project', (done)-> @ProjectEntityHandler.addDoc = sinon.stub().callsArgWith(5, null, @doc, @folder_id) - @EditorController.addDocWithoutLock @project_id, @folder_id, @docName, @docLines, @source, => + @EditorController.addDocWithoutLock @project_id, @folder_id, @docName, @docLines, @source, @user_id, => @EditorRealTimeController.emitToRoom .calledWith(@project_id, "reciveNewDoc", @folder_id, @doc, @source) .should.equal true @@ -148,7 +148,7 @@ describe "EditorController", -> it 'should return the doc to the callback', (done) -> @ProjectEntityHandler.addDoc = sinon.stub().callsArgWith(5, null, @doc, @folder_id) - @EditorController.addDocWithoutLock @project_id, @folder_id, @docName, @docLines, @source, (error, doc) => + @EditorController.addDocWithoutLock @project_id, @folder_id, @docName, @docLines, @source, @user_id, (error, doc) => doc.should.equal @doc done() @@ -157,7 +157,7 @@ describe "EditorController", -> beforeEach -> @LockManager.getLock.callsArgWith(1) @LockManager.releaseLock.callsArgWith(1) - @EditorController.addDocWithoutLock = sinon.stub().callsArgWith(5) + @EditorController.addDocWithoutLock = sinon.stub().callsArgWith(6) it "should call addDocWithoutLock", (done)-> @EditorController.addDoc @project_id, @folder_id, @docName, @docLines, @source, => diff --git a/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee b/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee index 032b60b261..cbb4fbfa92 100644 --- a/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee +++ b/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee @@ -44,14 +44,14 @@ describe "FileSystemImportManager", -> describe "with replace set to false", -> beforeEach -> - @EditorController.addDocWithoutLock = sinon.stub().callsArg(5) + @EditorController.addDocWithoutLock = sinon.stub().callsArg(6) @FileSystemImportManager.addDoc @user_id, @project_id, @folder_id, @name, @path_on_disk, false, @callback it "should read the file from disk", -> @fs.readFile.calledWith(@path_on_disk, "utf8").should.equal true it "should insert the doc", -> - @EditorController.addDocWithoutLock.calledWith(@project_id, @folder_id, @name, @docLines, "upload") + @EditorController.addDocWithoutLock.calledWith(@project_id, @folder_id, @name, @docLines, "upload", @user_id) .should.equal true describe "with windows line ending", -> @@ -59,11 +59,11 @@ describe "FileSystemImportManager", -> @docContent = "one\r\ntwo\r\nthree" @docLines = ["one", "two", "three"] @fs.readFile = sinon.stub().callsArgWith(2, null, @docContent) - @EditorController.addDocWithoutLock = sinon.stub().callsArg(5) + @EditorController.addDocWithoutLock = sinon.stub().callsArg(6) @FileSystemImportManager.addDoc @user_id, @project_id, @folder_id, @name, @path_on_disk, false, @callback it "should strip the \\r characters before adding", -> - @EditorController.addDocWithoutLock.calledWith(@project_id, @folder_id, @name, @docLines, "upload") + @EditorController.addDocWithoutLock.calledWith(@project_id, @folder_id, @name, @docLines, "upload", @user_id) .should.equal true describe "with replace set to true", -> @@ -76,7 +76,7 @@ describe "FileSystemImportManager", -> }] } @ProjectLocator.findElement = sinon.stub().callsArgWith(1, null, @folder) - @EditorController.addDocWithoutLock = sinon.stub().callsArg(5) + @EditorController.addDocWithoutLock = sinon.stub().callsArg(6) @FileSystemImportManager.addDoc @user_id, @project_id, @folder_id, @name, @path_on_disk, true, @callback it "should look up the folder", -> @@ -85,7 +85,7 @@ describe "FileSystemImportManager", -> .should.equal true it "should insert the doc", -> - @EditorController.addDocWithoutLock.calledWith(@project_id, @folder_id, @name, @docLines, "upload") + @EditorController.addDocWithoutLock.calledWith(@project_id, @folder_id, @name, @docLines, "upload", @user_id) .should.equal true describe "when the doc does exist", -> From 980e43e47804b51cfce4a3110f6ce99226c56e8c Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Thu, 23 Nov 2017 15:40:14 +0000 Subject: [PATCH 13/27] pass user_id into EditorController.addDoc --- .../Features/Editor/EditorController.coffee | 4 ++-- .../Features/Editor/EditorHttpController.coffee | 5 +++-- .../coffee/Editor/EditorControllerTests.coffee | 15 ++++++--------- .../Editor/EditorHttpControllerTests.coffee | 4 ++-- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/services/web/app/coffee/Features/Editor/EditorController.coffee b/services/web/app/coffee/Features/Editor/EditorController.coffee index 0cc1b8fa11..79191cd91e 100644 --- a/services/web/app/coffee/Features/Editor/EditorController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorController.coffee @@ -19,12 +19,12 @@ module.exports = EditorController = DocumentUpdaterHandler.flushDocToMongo project_id, doc_id, callback - addDoc: (project_id, folder_id, docName, docLines, source, callback = (error, doc)->)-> + addDoc: (project_id, folder_id, docName, docLines, source, user_id, callback = (error, doc)->)-> LockManager.getLock project_id, (err)-> if err? logger.err err:err, project_id:project_id, source:source, "could not get lock to addDoc" return callback(err) - EditorController.addDocWithoutLock project_id, folder_id, docName, docLines, source, null, (error, doc)-> + EditorController.addDocWithoutLock project_id, folder_id, docName, docLines, source, user_id, (error, doc)-> LockManager.releaseLock project_id, -> callback(error, doc) diff --git a/services/web/app/coffee/Features/Editor/EditorHttpController.coffee b/services/web/app/coffee/Features/Editor/EditorHttpController.coffee index e9bac7300d..cbc296b69f 100644 --- a/services/web/app/coffee/Features/Editor/EditorHttpController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorHttpController.coffee @@ -81,10 +81,11 @@ module.exports = EditorHttpController = project_id = req.params.Project_id name = req.body.name parent_folder_id = req.body.parent_folder_id + user_id = AuthenticationController.getLoggedInUserId(req) logger.log project_id:project_id, name:name, parent_folder_id:parent_folder_id, "getting request to add doc to project" if !EditorHttpController._nameIsAcceptableLength(name) return res.sendStatus 400 - EditorController.addDoc project_id, parent_folder_id, name, [], "editor", (error, doc) -> + EditorController.addDoc project_id, parent_folder_id, name, [], "editor", user_id, (error, doc) -> if error == "project_has_to_many_files" res.status(400).json(req.i18n.translate("project_has_to_many_files")) else if error? @@ -113,9 +114,9 @@ module.exports = EditorHttpController = entity_id = req.params.entity_id entity_type = req.params.entity_type name = req.body.name - user_id = AuthenticationController.getLoggedInUserId(req) if !EditorHttpController._nameIsAcceptableLength(name) return res.sendStatus 400 + user_id = AuthenticationController.getLoggedInUserId(req) EditorController.renameEntity project_id, entity_id, entity_type, name, user_id, (error) -> return next(error) if error? res.sendStatus 204 diff --git a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee index 3f34c84b1f..3b702f2b78 100644 --- a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee +++ b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee @@ -160,29 +160,26 @@ describe "EditorController", -> @EditorController.addDocWithoutLock = sinon.stub().callsArgWith(6) it "should call addDocWithoutLock", (done)-> - @EditorController.addDoc @project_id, @folder_id, @docName, @docLines, @source, => - @EditorController.addDocWithoutLock.calledWith(@project_id, @folder_id, @docName, @docLines, @source).should.equal true + @EditorController.addDoc @project_id, @folder_id, @docName, @docLines, @source, @user_id, => + @EditorController.addDocWithoutLock.calledWith(@project_id, @folder_id, @docName, @docLines, @source, @user_id).should.equal true done() it "should take the lock", (done)-> - @EditorController.addDoc @project_id, @folder_id, @docName, @docLines, @source, => + @EditorController.addDoc @project_id, @folder_id, @docName, @docLines, @source, @user_id, => @LockManager.getLock.calledWith(@project_id).should.equal true done() it "should release the lock", (done)-> - @EditorController.addDoc @project_id, @folder_id, @docName, @docLines, @source, => + @EditorController.addDoc @project_id, @folder_id, @docName, @docLines, @source, @user_id, => @LockManager.releaseLock.calledWith(@project_id).should.equal true done() it "should error if it can't cat the lock", (done)-> @LockManager.getLock = sinon.stub().callsArgWith(1, "timed out") - @EditorController.addDoc @project_id, @folder_id, @docName, @docLines, @source, (err)=> + @EditorController.addDoc @project_id, @folder_id, @docName, @docLines, @source, @user_id, (err)=> expect(err).to.exist err.should.equal "timed out" - done() - - - + done() describe 'addFileWithoutLock:', -> beforeEach -> diff --git a/services/web/test/unit/coffee/Editor/EditorHttpControllerTests.coffee b/services/web/test/unit/coffee/Editor/EditorHttpControllerTests.coffee index 2df4af72ec..e05846c5d5 100644 --- a/services/web/test/unit/coffee/Editor/EditorHttpControllerTests.coffee +++ b/services/web/test/unit/coffee/Editor/EditorHttpControllerTests.coffee @@ -201,7 +201,7 @@ describe "EditorHttpController", -> @req.body = name: @name = "doc-name" parent_folder_id: @parent_folder_id - @EditorController.addDoc = sinon.stub().callsArgWith(5, null, @doc) + @EditorController.addDoc = sinon.stub().callsArgWith(6, null, @doc) describe "successfully", -> beforeEach -> @@ -209,7 +209,7 @@ describe "EditorHttpController", -> it "should call EditorController.addDoc", -> @EditorController.addDoc - .calledWith(@project_id, @parent_folder_id, @name, [], "editor") + .calledWith(@project_id, @parent_folder_id, @name, [], "editor", @userId) .should.equal true it "should send the doc back as JSON", -> From 90e3b71c1c458852ddef4509aa2909bd247b1cb2 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Thu, 23 Nov 2017 16:40:15 +0000 Subject: [PATCH 14/27] version replacing files --- .../Project/ProjectEntityHandler.coffee | 37 ++++++++++--------- .../Project/ProjectEntityHandlerTests.coffee | 27 +++++++++++--- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index d004ad0cce..57e319afcc 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -223,12 +223,9 @@ module.exports = ProjectEntityHandler = callback null, fileRef, folder_id replaceFile: (project_id, file_id, fsPath, callback)-> + self = ProjectEntityHandler ProjectGetter.getProject project_id, {name:true}, (err, project) -> return callback(err) if err? - findOpts = - project_id:project._id - element_id:file_id - type:"file" FileStoreHandler.uploadFileFromDisk project._id, file_id, fsPath, (err)-> return callback(err) if err? # Note there is a potential race condition here (and elsewhere) @@ -236,20 +233,25 @@ module.exports = ProjectEntityHandler = # then the path to the file element will be out of date. In practice # this is not a problem so long as we do not do anything longer running # between them (like waiting for the file to upload.) - projectLocator.findElement findOpts, (err, fileRef, path)=> + self.getAllEntitiesFromProject project, (err, oldDocs, oldFiles) => return callback(err) if err? - tpdsUpdateSender.addFile {project_id:project._id, file_id:fileRef._id, path:path.fileSystem, rev:fileRef.rev+1, project_name:project.name}, (error) -> + projectLocator.findElement {project:project, element_id: file_id, type: 'file'}, (err, fileRef, path)=> return callback(err) if err? - conditons = _id:project._id - inc = {} - inc["#{path.mongo}.rev"] = 1 - set = {} - set["#{path.mongo}.created"] = new Date() - update = - "$inc": inc - "$set": set - Project.update conditons, update, {}, (err, second)-> - callback() + tpdsUpdateSender.addFile {project_id:project._id, file_id:fileRef._id, path:path.fileSystem, rev:fileRef.rev+1, project_name:project.name}, (err) -> + return callback(err) if err? + conditions = _id:project._id + inc = {} + inc["#{path.mongo}.rev"] = 1 + set = {} + set["#{path.mongo}.created"] = new Date() + update = + "$inc": inc + "$set": set + Project.findOneAndUpdate conditions, update, { "new": true}, (err, newProject) -> + return callback(err) if err? + self.getAllEntitiesFromProject newProject, (err, newDocs, newFiles) => + return callback(err) if err? + DocumentUpdaterHandler.updateProjectStructure project_id, null, oldDocs, newDocs, oldFiles, newFiles, callback copyFileFromExistingProject: (project_id, folder_id, originalProject_id, origonalFileRef, callback = (error, fileRef, folder_id) ->)-> logger.log project_id:project_id, folder_id:folder_id, originalProject_id:originalProject_id, origonalFileRef:origonalFileRef, "copying file in s3" @@ -392,8 +394,7 @@ module.exports = ProjectEntityHandler = endPath: result.path.fileSystem, rev: entity.rev tpdsUpdateSender.moveEntity opts - self.getAllEntitiesFromProject newProject, (error, newDocs, newFiles - ) => + self.getAllEntitiesFromProject newProject, (error, newDocs, newFiles) => return callback(error) if error? DocumentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback diff --git a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee index 506ff0cdb2..1b629f2257 100644 --- a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee @@ -583,7 +583,6 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, userId, () -> describe 'replacing a file', -> - beforeEach -> @projectLocator @file_id = "file_id_here" @@ -591,13 +590,23 @@ describe 'ProjectEntityHandler', -> @fileRef = {rev:3, _id:@file_id} @filePaths = {fileSystem:"/folder1/file.png", mongo:"folder.1.files.somewhere"} @projectLocator.findElement = sinon.stub().callsArgWith(1, null, @fileRef, @filePaths) - @ProjectModel.update = (_, __, ___, cb)-> cb() + + @ProjectEntityHandler.getAllEntitiesFromProject = sinon.stub() + @ProjectEntityHandler.getAllEntitiesFromProject + .onFirstCall() + .callsArgWith(1, null, [], @oldFiles = ['old-file']) + @ProjectEntityHandler.getAllEntitiesFromProject + .onSecondCall() + .callsArgWith(1, null, [], @newFiles = ['new-file']) + @ProjectModel.findOneAndUpdate = sinon.stub().callsArgWith(3, null, @project) + @ProjectGetter.getProject = sinon.stub().callsArgWith(2, null, @project) it 'should find the file', (done)-> - @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, => - @projectLocator.findElement.calledWith({element_id:@file_id, type:"file", project_id:project_id}).should.equal true + @projectLocator.findElement + .calledWith({element_id:@file_id, type:"file", project: @project}) + .should.equal true done() it 'should tell the file store handler to upload the file from disk', (done)-> @@ -617,7 +626,7 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, => it 'should inc the rev id', (done)-> - @ProjectModel.update = (conditions, update, options, callback)=> + @ProjectModel.findOneAndUpdate = (conditions, update, options, callback)=> conditions._id.should.equal project_id update.$inc["#{@filePaths.mongo}.rev"].should.equal 1 done() @@ -626,7 +635,7 @@ describe 'ProjectEntityHandler', -> it 'should update the created at date', (done)-> d = new Date() - @ProjectModel.update = (conditions, update, options, callback)=> + @ProjectModel.findOneAndUpdate = (conditions, update, options, callback)=> conditions._id.should.equal project_id differenceInMs = update.$set["#{@filePaths.mongo}.created"].getTime() - d.getTime() differenceInMs.should.be.below(20) @@ -634,6 +643,12 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, => + it "should should send the old and new project structure to the doc updater", (done) -> + @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, => + @documentUpdaterHandler.updateProjectStructure + .calledWith(project_id, null, [], [], @oldFiles, @newFiles) + .should.equal true + done() describe 'addFolder', -> folderName = "folder1234" From 4ec0d07aae17abe7b1800fb0bdae4e04459c54db Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Fri, 24 Nov 2017 10:39:06 +0000 Subject: [PATCH 15/27] remove unused ProjectEntityHandler.copyFileFromExistingProject --- .../Features/Project/ProjectEntityHandler.coffee | 9 --------- .../Project/ProjectEntityHandlerTests.coffee | 16 +++++++--------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index 57e319afcc..d06ca0714a 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -253,15 +253,6 @@ module.exports = ProjectEntityHandler = return callback(err) if err? DocumentUpdaterHandler.updateProjectStructure project_id, null, oldDocs, newDocs, oldFiles, newFiles, callback - copyFileFromExistingProject: (project_id, folder_id, originalProject_id, origonalFileRef, callback = (error, fileRef, folder_id) ->)-> - logger.log project_id:project_id, folder_id:folder_id, originalProject_id:originalProject_id, origonalFileRef:origonalFileRef, "copying file in s3" - ProjectGetter.getProject project_id, {name:true}, (err, project) -> - if err? - logger.err project_id:project_id, err:err, "error getting project for copy file from existing project" - return callback(err) - ProjectEntityHandler.copyFileFromExistingProjectWithProject project, folder_id, originalProject_id, origonalFileRef, callback - - copyFileFromExistingProjectWithProject: (project, folder_id, originalProject_id, origonalFileRef, callback = (error, fileRef, folder_id) ->)-> project_id = project._id logger.log project_id:project_id, folder_id:folder_id, originalProject_id:originalProject_id, origonalFileRef:origonalFileRef, "copying file in s3 with project" diff --git a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee index 1b629f2257..73a2b83090 100644 --- a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee @@ -982,19 +982,18 @@ describe 'ProjectEntityHandler', -> @ProjectModel.update.calledWith({_id : @project_id}, {$unset : {rootDoc_id: true}}) .should.equal true - describe 'copyFileFromExistingProject', -> + describe 'copyFileFromExistingProjectWithProject', -> fileName = "something.jpg" filePath = "dumpFolder/somewhere/image.jpeg" oldProject_id = "123kljadas" oldFileRef = {name:fileName, _id:"oldFileRef"} - beforeEach -> - @ProjectGetter.getProject = (project_id, fields, callback)=> callback(null, {name:@project.name, _id:@project._id}) - @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, {path:{fileSystem:"somehintg"}}) + beforeEach -> + @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, {path:{fileSystem:"somehintg"}}) it 'should copy the file in FileStoreHandler', (done)-> @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, {path:{fileSystem:"somehintg"}}) - @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)=> + @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)=> @FileStoreHandler.copyFile.calledWith(oldProject_id, oldFileRef._id, project_id, fileRef._id).should.equal true done() @@ -1006,10 +1005,10 @@ describe 'ProjectEntityHandler', -> passedType.should.equal 'file' done() - @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> it 'should return doc and parent folder', (done)-> - @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> parentFolder.should.equal folder_id fileRef.name.should.equal fileName done() @@ -1029,8 +1028,7 @@ describe 'ProjectEntityHandler', -> options.rev.should.equal 0 done() - @ProjectEntityHandler.copyFileFromExistingProject project_id, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> - + @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> describe "renameEntity", -> beforeEach -> From 60ee78704a0f60e29e4ea2efd1e62188895eda62 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Fri, 24 Nov 2017 11:13:44 +0000 Subject: [PATCH 16/27] return url from FileStoreHandler.copyFile --- .../app/coffee/Features/FileStore/FileStoreHandler.coffee | 2 +- .../test/unit/coffee/FileStore/FileStoreHandlerTests.coffee | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/services/web/app/coffee/Features/FileStore/FileStoreHandler.coffee b/services/web/app/coffee/Features/FileStore/FileStoreHandler.coffee index 88f55bc698..ef363fbbc7 100644 --- a/services/web/app/coffee/Features/FileStore/FileStoreHandler.coffee +++ b/services/web/app/coffee/Features/FileStore/FileStoreHandler.coffee @@ -92,7 +92,7 @@ module.exports = FileStoreHandler = request opts, (err)-> if err? logger.err err:err, oldProject_id:oldProject_id, oldFile_id:oldFile_id, newProject_id:newProject_id, newFile_id:newFile_id, "something went wrong telling filestore api to copy file" - callback(err) + callback(err, opts.uri) _buildUrl: (project_id, file_id)-> return "#{settings.apis.filestore.url}/project/#{project_id}/file/#{file_id}" diff --git a/services/web/test/unit/coffee/FileStore/FileStoreHandlerTests.coffee b/services/web/test/unit/coffee/FileStore/FileStoreHandlerTests.coffee index ea7c7a4cbb..90a3e870d1 100644 --- a/services/web/test/unit/coffee/FileStore/FileStoreHandlerTests.coffee +++ b/services/web/test/unit/coffee/FileStore/FileStoreHandlerTests.coffee @@ -219,6 +219,11 @@ describe "FileStoreHandler", -> @handler._buildUrl.calledWith(@newProject_id, @newFile_id).should.equal true done() + it "returns the url", (done)-> + @request.callsArgWith(1, null) + @handler.copyFile @project_id, @file_id, @newProject_id, @newFile_id, (err, url) => + url.should.equal "http://filestore.stubbedBuilder.com" + done() it "should return the err", (done)-> error = "errrror" From 088ce33cbc4cebbb6f276a0745fb12e23b9fa2fa Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Fri, 24 Nov 2017 11:14:15 +0000 Subject: [PATCH 17/27] version ProjectEntityHandler.copyFileFromExistingProjectWithProject --- .../Project/ProjectEntityHandler.coffee | 22 ++++++++++------- .../Project/ProjectEntityHandlerTests.coffee | 24 +++++++++++++++---- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index d06ca0714a..2e3f67b760 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -255,25 +255,31 @@ module.exports = ProjectEntityHandler = copyFileFromExistingProjectWithProject: (project, folder_id, originalProject_id, origonalFileRef, callback = (error, fileRef, folder_id) ->)-> project_id = project._id - logger.log project_id:project_id, folder_id:folder_id, originalProject_id:originalProject_id, origonalFileRef:origonalFileRef, "copying file in s3 with project" + logger.log { project_id, folder_id, originalProject_id, origonalFileRef }, "copying file in s3 with project" return callback(err) if err? confirmFolder project, folder_id, (folder_id)=> if !origonalFileRef? - logger.err project_id:project._id, folder_id:folder_id, originalProject_id:originalProject_id, origonalFileRef:origonalFileRef, "file trying to copy is null" + logger.err { project_id, folder_id, originalProject_id, origonalFileRef }, "file trying to copy is null" return callback() fileRef = new File name : origonalFileRef.name - FileStoreHandler.copyFile originalProject_id, origonalFileRef._id, project._id, fileRef._id, (err)-> + FileStoreHandler.copyFile originalProject_id, origonalFileRef._id, project._id, fileRef._id, (err, fileStoreUrl)-> if err? - logger.err err:err, project_id:project._id, folder_id:folder_id, originalProject_id:originalProject_id, origonalFileRef:origonalFileRef, "error coping file in s3" + logger.err { err, project_id, folder_id, originalProject_id, origonalFileRef }, "error coping file in s3" return callback(err) ProjectEntityHandler._putElement project, folder_id, fileRef, "file", (err, result)=> if err? - logger.err err:err, project_id:project._id, folder_id:folder_id, "error putting element as part of copy" + logger.err { err, project_id, folder_id }, "error putting element as part of copy" return callback(err) - tpdsUpdateSender.addFile {project_id:project._id, file_id:fileRef._id, path:result?.path?.fileSystem, rev:fileRef.rev, project_name:project.name}, (err) -> + tpdsUpdateSender.addFile { project_id, file_id:fileRef._id, path:result?.path?.fileSystem, rev:fileRef.rev, project_name:project.name}, (err) -> if err? - logger.err err:err, project_id:project._id, folder_id:folder_id, originalProject_id:originalProject_id, origonalFileRef:origonalFileRef, "error sending file to tpds worker" - callback(null, fileRef, folder_id) + logger.err { err, project_id, folder_id, originalProject_id, origonalFileRef }, "error sending file to tpds worker" + newFile = + file: fileRef + path: result?.path?.fileSystem + url: fileStoreUrl + DocumentUpdaterHandler.updateProjectStructure project_id, null, [], [], [], [newFile], (error) -> + return callback(error) if error? + callback null, fileRef, folder_id mkdirp: (project_id, path, callback = (err, newlyCreatedFolders, lastFolderInPath)->)-> self = @ diff --git a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee index 73a2b83090..ff953b676c 100644 --- a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee @@ -20,7 +20,7 @@ describe 'ProjectEntityHandler', -> @fileUrl = 'filestore.example.com/file' @FileStoreHandler = uploadFileFromDisk: sinon.stub().callsArgWith(3, null, @fileUrl) - copyFile: sinon.stub().callsArgWith(4, null) + copyFile: sinon.stub().callsArgWith(4, null, @fileUrl) @tpdsUpdateSender = addDoc:sinon.stub().callsArg(1) addFile:sinon.stub().callsArg(1) @@ -570,9 +570,9 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, userId, (err, fileRef, parentFolder)-> it "should should send the change in project structure to the doc updater", (done) -> - @documentUpdaterHandler.updateProjectStructure = (project_id, user_id, oldDocs, newDocs, oldFiles, newFiles) => - project_id.should.equal project_id - user_id.should.equal user_id + @documentUpdaterHandler.updateProjectStructure = (passed_project_id, passed_user_id, oldDocs, newDocs, oldFiles, newFiles) => + passed_project_id.should.equal project_id + passed_user_id.should.equal userId newFiles.length.should.equal 1 newFile = newFiles[0] newFile.file.name.should.equal fileName @@ -989,7 +989,8 @@ describe 'ProjectEntityHandler', -> oldFileRef = {name:fileName, _id:"oldFileRef"} beforeEach -> - @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, {path:{fileSystem:"somehintg"}}) + @fileSystemPath = "somehintg" + @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, {path:{fileSystem: @fileSystemPath}}) it 'should copy the file in FileStoreHandler', (done)-> @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, {path:{fileSystem:"somehintg"}}) @@ -1030,6 +1031,19 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> + it "should should send the change in project structure to the doc updater", (done) -> + @documentUpdaterHandler.updateProjectStructure = (passed_project_id, passed_user_id, oldDocs, newDocs, oldFiles, newFiles) => + passed_project_id.should.equal project_id + #passed_user_id.should.equal userId + newFiles.length.should.equal 1 + newFile = newFiles[0] + newFile.file.name.should.equal fileName + newFile.path.should.equal @fileSystemPath + newFile.url.should.equal @fileUrl + done() + + @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> + describe "renameEntity", -> beforeEach -> @entity_id = "4eecaffcbffa66588e000009" From 08891c7a7f534b70918b8265db28400318a32b6d Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Fri, 24 Nov 2017 11:26:43 +0000 Subject: [PATCH 18/27] pass userId into ProjectEntityHandler.replaceFile --- .../coffee/Features/Editor/EditorController.coffee | 2 +- .../Features/Project/ProjectEntityHandler.coffee | 4 ++-- .../coffee/Editor/EditorControllerTests.coffee | 2 +- .../Project/ProjectEntityHandlerTests.coffee | 14 +++++++------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/services/web/app/coffee/Features/Editor/EditorController.coffee b/services/web/app/coffee/Features/Editor/EditorController.coffee index 79191cd91e..f0530edd7f 100644 --- a/services/web/app/coffee/Features/Editor/EditorController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorController.coffee @@ -60,7 +60,7 @@ module.exports = EditorController = callback(err, fileRef) replaceFile: (project_id, file_id, fsPath, source, callback = (error) ->)-> - ProjectEntityHandler.replaceFile project_id, file_id, fsPath, callback + ProjectEntityHandler.replaceFile project_id, file_id, fsPath, null, callback addFolder : (project_id, folder_id, folderName, source, callback = (error, folder)->)-> LockManager.getLock project_id, (err)-> diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index 2e3f67b760..42f70b0a7f 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -222,7 +222,7 @@ module.exports = ProjectEntityHandler = return callback(error) if error? callback null, fileRef, folder_id - replaceFile: (project_id, file_id, fsPath, callback)-> + replaceFile: (project_id, file_id, fsPath, userId, callback)-> self = ProjectEntityHandler ProjectGetter.getProject project_id, {name:true}, (err, project) -> return callback(err) if err? @@ -251,7 +251,7 @@ module.exports = ProjectEntityHandler = return callback(err) if err? self.getAllEntitiesFromProject newProject, (err, newDocs, newFiles) => return callback(err) if err? - DocumentUpdaterHandler.updateProjectStructure project_id, null, oldDocs, newDocs, oldFiles, newFiles, callback + DocumentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback copyFileFromExistingProjectWithProject: (project, folder_id, originalProject_id, origonalFileRef, callback = (error, fileRef, folder_id) ->)-> project_id = project._id diff --git a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee index 3b702f2b78..63d44a8c20 100644 --- a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee +++ b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee @@ -253,7 +253,7 @@ describe "EditorController", -> @fsPath = "/folder/file.png" it 'should send the replace file message to the editor controller', (done)-> - @ProjectEntityHandler.replaceFile = sinon.stub().callsArgWith(3) + @ProjectEntityHandler.replaceFile = sinon.stub().callsArgWith(4) @EditorController.replaceFile @project_id, @file_id, @fsPath, @source, => @ProjectEntityHandler.replaceFile.calledWith(@project_id, @file_id, @fsPath).should.equal true done() diff --git a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee index ff953b676c..1eef82cbc5 100644 --- a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee @@ -603,14 +603,14 @@ describe 'ProjectEntityHandler', -> @ProjectGetter.getProject = sinon.stub().callsArgWith(2, null, @project) it 'should find the file', (done)-> - @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, => + @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, userId, => @projectLocator.findElement .calledWith({element_id:@file_id, type:"file", project: @project}) .should.equal true done() it 'should tell the file store handler to upload the file from disk', (done)-> - @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, => + @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, userId, => @FileStoreHandler.uploadFileFromDisk.calledWith(project_id, @file_id, @fsPath).should.equal true done() @@ -623,7 +623,7 @@ describe 'ProjectEntityHandler', -> options.rev.should.equal @fileRef.rev + 1 done() - @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, => + @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, userId, => it 'should inc the rev id', (done)-> @ProjectModel.findOneAndUpdate = (conditions, update, options, callback)=> @@ -631,7 +631,7 @@ describe 'ProjectEntityHandler', -> update.$inc["#{@filePaths.mongo}.rev"].should.equal 1 done() - @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, => + @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, userId, => it 'should update the created at date', (done)-> d = new Date() @@ -641,12 +641,12 @@ describe 'ProjectEntityHandler', -> differenceInMs.should.be.below(20) done() - @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, => + @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, userId, => it "should should send the old and new project structure to the doc updater", (done) -> - @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, => + @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, userId, => @documentUpdaterHandler.updateProjectStructure - .calledWith(project_id, null, [], [], @oldFiles, @newFiles) + .calledWith(project_id, userId, [], [], @oldFiles, @newFiles) .should.equal true done() From feee5823689a8d5fe10bbeb4dcfca88d0b277a04 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Fri, 24 Nov 2017 11:32:34 +0000 Subject: [PATCH 19/27] pass user_id into EditorController.replaceFile --- .../web/app/coffee/Features/Editor/EditorController.coffee | 4 ++-- .../coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee | 2 +- .../coffee/Features/Uploads/FileSystemImportManager.coffee | 2 +- .../web/test/unit/coffee/Editor/EditorControllerTests.coffee | 4 ++-- .../unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee | 4 ++-- .../unit/coffee/Uploads/FileSystemImportManagerTests.coffee | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/services/web/app/coffee/Features/Editor/EditorController.coffee b/services/web/app/coffee/Features/Editor/EditorController.coffee index f0530edd7f..f66094f9e8 100644 --- a/services/web/app/coffee/Features/Editor/EditorController.coffee +++ b/services/web/app/coffee/Features/Editor/EditorController.coffee @@ -59,8 +59,8 @@ module.exports = EditorController = EditorRealTimeController.emitToRoom(project_id, 'reciveNewFile', folder_id, fileRef, source) callback(err, fileRef) - replaceFile: (project_id, file_id, fsPath, source, callback = (error) ->)-> - ProjectEntityHandler.replaceFile project_id, file_id, fsPath, null, callback + replaceFile: (project_id, file_id, fsPath, source, user_id, callback = (error) ->)-> + ProjectEntityHandler.replaceFile project_id, file_id, fsPath, user_id, callback addFolder : (project_id, folder_id, folderName, source, callback = (error, folder)->)-> LockManager.getLock project_id, (err)-> diff --git a/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee b/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee index e78c1bd1e4..9671524f67 100644 --- a/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee +++ b/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee @@ -69,7 +69,7 @@ module.exports = logger.err err:err, project_id:project_id, file_id:file_id, path:path, "error processing file" return callback(err) else if file_id? - editorController.replaceFile project_id, file_id, fsPath, source, finish + editorController.replaceFile project_id, file_id, fsPath, source, user_id, finish else editorController.addFile project_id, folder?._id, fileName, fsPath, source, user_id, finish diff --git a/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee b/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee index cc52b50dc4..0cec7cfc9d 100644 --- a/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee +++ b/services/web/app/coffee/Features/Uploads/FileSystemImportManager.coffee @@ -50,7 +50,7 @@ module.exports = FileSystemImportManager = existingFile = fileRef break if existingFile? - EditorController.replaceFile project_id, existingFile._id, path, "upload", callback + EditorController.replaceFile project_id, existingFile._id, path, "upload", user_id, callback else EditorController.addFileWithoutLock project_id, folder_id, name, path, "upload", user_id, callback diff --git a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee index 63d44a8c20..4e1af79b46 100644 --- a/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee +++ b/services/web/test/unit/coffee/Editor/EditorControllerTests.coffee @@ -254,8 +254,8 @@ describe "EditorController", -> it 'should send the replace file message to the editor controller', (done)-> @ProjectEntityHandler.replaceFile = sinon.stub().callsArgWith(4) - @EditorController.replaceFile @project_id, @file_id, @fsPath, @source, => - @ProjectEntityHandler.replaceFile.calledWith(@project_id, @file_id, @fsPath).should.equal true + @EditorController.replaceFile @project_id, @file_id, @fsPath, @source, @user_id, => + @ProjectEntityHandler.replaceFile.calledWith(@project_id, @file_id, @fsPath, @user_id).should.equal true done() describe 'addFolderWithoutLock :', -> diff --git a/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee b/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee index c2d3816a5c..196c502dbf 100644 --- a/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee +++ b/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee @@ -115,7 +115,7 @@ describe 'UpdateMerger :', -> @fileName = "file.png" @fsPath = "fs/path.tex" @editorController.addFile = sinon.stub().callsArg(6) - @editorController.replaceFile = sinon.stub().callsArg(4) + @editorController.replaceFile = sinon.stub().callsArg(5) @editorController.deleteEntity = sinon.stub() @editorController.mkdirp = sinon.stub().withArgs(@project_id).callsArgWith(2, null, [@folder], @folder) @updateMerger.p.writeStreamToDisk = sinon.stub().withArgs(@project_id, @file_id, @update).callsArgWith(3, null, @fsPath) @@ -123,7 +123,7 @@ describe 'UpdateMerger :', -> it 'should replace file if the file already exists', (done)-> @updateMerger.p.processFile @project_id, @file_id, @fsPath, @path, @source, @user_id, => @editorController.addFile.called.should.equal false - @editorController.replaceFile.calledWith(@project_id, @file_id, @fsPath, @source).should.equal true + @editorController.replaceFile.calledWith(@project_id, @file_id, @fsPath, @source, @user_id).should.equal true done() it 'should call add file if the file does not exist', (done)-> diff --git a/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee b/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee index cbb4fbfa92..0eb17c0d02 100644 --- a/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee +++ b/services/web/test/unit/coffee/Uploads/FileSystemImportManagerTests.coffee @@ -169,7 +169,7 @@ describe "FileSystemImportManager", -> } @FileSystemImportManager._isSafeOnFileSystem = sinon.stub().callsArgWith(1, null, true) @ProjectLocator.findElement = sinon.stub().callsArgWith(1, null, @folder) - @EditorController.replaceFile = sinon.stub().callsArg(4) + @EditorController.replaceFile = sinon.stub().callsArg(5) @FileSystemImportManager.addFile @user_id, @project_id, @folder_id, @name, @path_on_disk, true, @callback it "should look up the folder", -> @@ -178,7 +178,7 @@ describe "FileSystemImportManager", -> .should.equal true it "should replace the file", -> - @EditorController.replaceFile.calledWith(@project_id, @file_id, @path_on_disk, "upload") + @EditorController.replaceFile.calledWith(@project_id, @file_id, @path_on_disk, "upload", @user_id) .should.equal true describe "addFolder", -> From 61a1336ec60af80789edf48b679781b0161566eb Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Fri, 24 Nov 2017 11:37:19 +0000 Subject: [PATCH 20/27] pass userId into ProjectEntiyHandler.copyFileFromExistingProjectWithProject --- .../Features/Project/ProjectDuplicator.coffee | 6 +++--- .../Features/Project/ProjectEntityHandler.coffee | 4 ++-- .../coffee/Project/ProjectDuplicatorTests.coffee | 14 ++++++++++---- .../Project/ProjectEntityHandlerTests.coffee | 12 ++++++------ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee b/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee index 730e1e2a1a..815e31eb27 100644 --- a/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee +++ b/services/web/app/coffee/Features/Project/ProjectDuplicator.coffee @@ -31,11 +31,11 @@ module.exports = ProjectDuplicator = async.series jobs, callback - _copyFiles: (newProject, originalProject_id, originalFolder, desFolder, callback)-> + _copyFiles: (owner_id, newProject, originalProject_id, originalFolder, desFolder, callback)-> fileRefs = originalFolder.fileRefs or [] jobs = fileRefs.map (file)-> return (cb)-> - projectEntityHandler.copyFileFromExistingProjectWithProject newProject, desFolder._id, originalProject_id, file, cb + projectEntityHandler.copyFileFromExistingProjectWithProject newProject, desFolder._id, originalProject_id, file, owner_id, cb async.parallelLimit jobs, 5, callback @@ -56,7 +56,7 @@ module.exports = ProjectDuplicator = ProjectDuplicator._copyFolderRecursivly owner_id, newProject_id, originalProject_id, originalRootDoc, childFolder, newFolder, docContents, cb jobs.push (cb)-> - ProjectDuplicator._copyFiles newProject, originalProject_id, originalFolder, desFolder, cb + ProjectDuplicator._copyFiles owner_id, newProject, originalProject_id, originalFolder, desFolder, cb jobs.push (cb)-> ProjectDuplicator._copyDocs owner_id, newProject, originalRootDoc, originalFolder, desFolder, docContents, cb diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index 42f70b0a7f..5e19e4afa5 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -253,7 +253,7 @@ module.exports = ProjectEntityHandler = return callback(err) if err? DocumentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback - copyFileFromExistingProjectWithProject: (project, folder_id, originalProject_id, origonalFileRef, callback = (error, fileRef, folder_id) ->)-> + copyFileFromExistingProjectWithProject: (project, folder_id, originalProject_id, origonalFileRef, userId, callback = (error, fileRef, folder_id) ->)-> project_id = project._id logger.log { project_id, folder_id, originalProject_id, origonalFileRef }, "copying file in s3 with project" return callback(err) if err? @@ -277,7 +277,7 @@ module.exports = ProjectEntityHandler = file: fileRef path: result?.path?.fileSystem url: fileStoreUrl - DocumentUpdaterHandler.updateProjectStructure project_id, null, [], [], [], [newFile], (error) -> + DocumentUpdaterHandler.updateProjectStructure project_id, userId, [], [], [], [newFile], (error) -> return callback(error) if error? callback null, fileRef, folder_id diff --git a/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee b/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee index c4be897f9a..b489014e7e 100644 --- a/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectDuplicatorTests.coffee @@ -65,7 +65,7 @@ describe 'ProjectDuplicator', -> setCompiler : sinon.stub() @entityHandler = addDocWithProject: sinon.stub().callsArgWith(5, null, {name:"somDoc"}) - copyFileFromExistingProjectWithProject: sinon.stub().callsArgWith(4) + copyFileFromExistingProjectWithProject: sinon.stub().callsArgWith(5) setRootDoc: sinon.stub() addFolderWithProject: sinon.stub().callsArgWith(3, null, @newFolder) @@ -152,7 +152,13 @@ describe 'ProjectDuplicator', -> it 'should copy all the files', (done)-> @duplicator.duplicate @owner, @old_project_id, "", (err, newProject)=> - @entityHandler.copyFileFromExistingProjectWithProject.calledWith(@stubbedNewProject, @stubbedNewProject.rootFolder[0]._id, @project._id, @rootFolder.fileRefs[0]).should.equal true - @entityHandler.copyFileFromExistingProjectWithProject.calledWith(@stubbedNewProject, @newFolder._id, @project._id, @level1folder.fileRefs[0]).should.equal true - @entityHandler.copyFileFromExistingProjectWithProject.calledWith(@stubbedNewProject, @newFolder._id, @project._id, @level2folder.fileRefs[0]).should.equal true + @entityHandler.copyFileFromExistingProjectWithProject + .calledWith(@stubbedNewProject, @stubbedNewProject.rootFolder[0]._id, @project._id, @rootFolder.fileRefs[0], @owner._id) + .should.equal true + @entityHandler.copyFileFromExistingProjectWithProject + .calledWith(@stubbedNewProject, @newFolder._id, @project._id, @level1folder.fileRefs[0], @owner._id) + .should.equal true + @entityHandler.copyFileFromExistingProjectWithProject + .calledWith(@stubbedNewProject, @newFolder._id, @project._id, @level2folder.fileRefs[0], @owner._id) + .should.equal true done() diff --git a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee index 1eef82cbc5..881b579150 100644 --- a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee @@ -994,7 +994,7 @@ describe 'ProjectEntityHandler', -> it 'should copy the file in FileStoreHandler', (done)-> @ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, {path:{fileSystem:"somehintg"}}) - @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)=> + @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, userId, (err, fileRef, parentFolder)=> @FileStoreHandler.copyFile.calledWith(oldProject_id, oldFileRef._id, project_id, fileRef._id).should.equal true done() @@ -1006,10 +1006,10 @@ describe 'ProjectEntityHandler', -> passedType.should.equal 'file' done() - @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, userId, (err, fileRef, parentFolder)-> it 'should return doc and parent folder', (done)-> - @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, userId, (err, fileRef, parentFolder)-> parentFolder.should.equal folder_id fileRef.name.should.equal fileName done() @@ -1029,12 +1029,12 @@ describe 'ProjectEntityHandler', -> options.rev.should.equal 0 done() - @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, userId, (err, fileRef, parentFolder)-> it "should should send the change in project structure to the doc updater", (done) -> @documentUpdaterHandler.updateProjectStructure = (passed_project_id, passed_user_id, oldDocs, newDocs, oldFiles, newFiles) => passed_project_id.should.equal project_id - #passed_user_id.should.equal userId + passed_user_id.should.equal userId newFiles.length.should.equal 1 newFile = newFiles[0] newFile.file.name.should.equal fileName @@ -1042,7 +1042,7 @@ describe 'ProjectEntityHandler', -> newFile.url.should.equal @fileUrl done() - @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, (err, fileRef, parentFolder)-> + @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, userId, (err, fileRef, parentFolder)-> describe "renameEntity", -> beforeEach -> From 3466db0aae8aba8d4410ef7cf6aa6e0c1b8c2c83 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Mon, 27 Nov 2017 17:09:51 +0000 Subject: [PATCH 21/27] add acceptance tests --- services/web/config/settings.defaults.coffee | 2 +- .../coffee/ProjectStructureTests.coffee | 200 ++++++++++++++++++ .../coffee/helpers/MockDocUpdaterApi.coffee | 29 +++ .../coffee/helpers/MockDocstoreApi.coffee | 1 + .../coffee/helpers/MockFileStoreApi.coffee | 20 ++ .../helpers/MockProjectHistoryApi.coffee | 18 ++ .../acceptance/coffee/helpers/User.coffee | 9 +- services/web/test/acceptance/files/1pixel.png | Bin 0 -> 3690 bytes services/web/test/acceptance/files/2pixel.png | Bin 0 -> 3694 bytes .../test/acceptance/files/test_project.zip | Bin 0 -> 3820 bytes .../web/test/acceptance/scripts/full-test.sh | 2 +- 11 files changed, 276 insertions(+), 5 deletions(-) create mode 100644 services/web/test/acceptance/coffee/ProjectStructureTests.coffee create mode 100644 services/web/test/acceptance/coffee/helpers/MockFileStoreApi.coffee create mode 100644 services/web/test/acceptance/coffee/helpers/MockProjectHistoryApi.coffee create mode 100644 services/web/test/acceptance/files/1pixel.png create mode 100644 services/web/test/acceptance/files/2pixel.png create mode 100644 services/web/test/acceptance/files/test_project.zip diff --git a/services/web/config/settings.defaults.coffee b/services/web/config/settings.defaults.coffee index 98d1c9e031..65a8bf1e91 100644 --- a/services/web/config/settings.defaults.coffee +++ b/services/web/config/settings.defaults.coffee @@ -111,7 +111,7 @@ module.exports = settings = trackchanges: url : "http://localhost:3015" project_history: - enabled: false + enabled: process.env.PROJECT_HISTORY_ENABLED == 'true' or false url : "http://localhost:3054" docstore: url : "http://#{process.env['DOCSTORE_HOST'] or 'localhost'}:3016" diff --git a/services/web/test/acceptance/coffee/ProjectStructureTests.coffee b/services/web/test/acceptance/coffee/ProjectStructureTests.coffee new file mode 100644 index 0000000000..c7f429ac40 --- /dev/null +++ b/services/web/test/acceptance/coffee/ProjectStructureTests.coffee @@ -0,0 +1,200 @@ +async = require("async") +expect = require("chai").expect +Path = require "path" +fs = require "fs" +_ = require "underscore" + +ProjectGetter = require "../../../app/js/Features/Project/ProjectGetter.js" + +MockDocUpdaterApi = require './helpers/MockDocUpdaterApi' +MockFileStoreApi = require './helpers/MockFileStoreApi' +MockProjectHistoryApi = require './helpers/MockProjectHistoryApi' +request = require "./helpers/request" +User = require "./helpers/User" + +describe "ProjectStructureChanges", -> + before (done) -> + @owner = new User() + @owner.login done + + describe "creating a project from the example template", -> + before (done) -> + MockDocUpdaterApi.clearProjectStructureUpdates() + @owner.createProject "project", {template: "example"}, (error, project_id) => + throw error if error? + @example_project_id = project_id + done() + + it "should version creating a doc", -> + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).docUpdates + expect(updates.length).to.equal(2) + _.each updates, (update) => + expect(update.userId).to.equal(@owner._id) + expect(update.docLines).to.be.a('string') + expect(_.where(updates, pathname: "/main.tex").length).to.equal 1 + expect(_.where(updates, pathname: "/references.bib").length).to.equal 1 + + it "should version creating a file", -> + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/universe.jpg") + expect(update.url).to.be.a('string'); + + describe "duplicating a project", -> + before (done) -> + MockDocUpdaterApi.clearProjectStructureUpdates() + @owner.request.post { + uri: "/Project/#{@example_project_id}/clone", + json: + projectName: 'new.tex' + }, (error, res, body) => + throw error if error? + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to add doc #{res.statusCode}") + @dup_project_id = body.project_id + done() + + it "should version the dosc created", -> + updates = MockDocUpdaterApi.getProjectStructureUpdates(@dup_project_id).docUpdates + expect(updates.length).to.equal(2) + _.each updates, (update) => + expect(update.userId).to.equal(@owner._id) + expect(update.docLines).to.be.a('string') + expect(_.where(updates, pathname: "/main.tex").length).to.equal(1) + expect(_.where(updates, pathname: "/references.bib").length).to.equal(1) + + it "should version the files created", -> + updates = MockDocUpdaterApi.getProjectStructureUpdates(@dup_project_id).fileUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/universe.jpg") + expect(update.url).to.be.a('string'); + + describe "adding a doc", -> + before (done) -> + MockDocUpdaterApi.clearProjectStructureUpdates() + + ProjectGetter.getProject @example_project_id, (error, projects) => + throw error if error? + @owner.request.post { + uri: "project/#{@example_project_id}/doc", + json: + name: 'new.tex' + parent_folder_id: projects[0].rootFolder[0]._id + }, (error, res, body) => + throw error if error? + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to add doc #{res.statusCode}") + done() + + it "should version the doc added", -> + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).docUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/new.tex") + expect(update.docLines).to.be.a('string'); + + describe "uploading a project", -> + before (done) -> + MockDocUpdaterApi.clearProjectStructureUpdates() + + zip_file = fs.createReadStream(Path.resolve(__dirname + '/../files/test_project.zip')) + + req = @owner.request.post { + uri: "project/new/upload", + formData: + qqfile: zip_file + }, (error, res, body) => + throw error if error? + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to upload project #{res.statusCode}") + @uploaded_project_id = JSON.parse(body).project_id + done() + + it "should version the dosc created", -> + updates = MockDocUpdaterApi.getProjectStructureUpdates(@uploaded_project_id).docUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/main.tex") + expect(update.docLines).to.equal("Test") + + it "should version the files created", -> + updates = MockDocUpdaterApi.getProjectStructureUpdates(@uploaded_project_id).fileUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/1pixel.png") + expect(update.url).to.be.a('string'); + + describe "uploading a file", -> + before (done) -> + MockDocUpdaterApi.clearProjectStructureUpdates() + ProjectGetter.getProject @example_project_id, (error, projects) => + throw error if error? + @root_folder_id = projects[0].rootFolder[0]._id.toString() + done() + + it "should version a newly uploaded file", (done) -> + image_file = fs.createReadStream(Path.resolve(__dirname + '/../files/1pixel.png')) + + req = @owner.request.post { + uri: "project/#{@example_project_id}/upload", + qs: + folder_id: @root_folder_id + formData: + qqfile: + value: image_file + options: + filename: '1pixel.png', + contentType: 'image/png' + }, (error, res, body) => + throw error if error? + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to upload file #{res.statusCode}") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/1pixel.png") + expect(update.url).to.be.a('string'); + @original_file_url = update.url + + done() + + it "should version a replacement file", (done) -> + image_file = fs.createReadStream(Path.resolve(__dirname + '/../files/2pixel.png')) + + req = @owner.request.post { + uri: "project/#{@example_project_id}/upload", + qs: + folder_id: @root_folder_id + formData: + qqfile: + value: image_file + options: + filename: '1pixel.png', + contentType: 'image/png' + }, (error, res, body) => + throw error if error? + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to upload file #{res.statusCode}") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@example_project_id).fileUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/1pixel.png") + expect(update.url).to.be.a('string'); + + done() + + describe "tpds", -> + it "should version add a doc" + it "should version add a new file" + it "should version replacing a file" diff --git a/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee b/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee index aefcd4513a..2147ac2691 100644 --- a/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee +++ b/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee @@ -1,11 +1,40 @@ express = require("express") app = express() +bodyParser = require "body-parser" +jsonParser = bodyParser.json() module.exports = MockDocUpdaterApi = + project_structures_updates: {} + + clearProjectStructureUpdates: () -> + @project_structures_updates = {} + + getProjectStructureUpdates: (project_id) -> + @project_structures_updates[project_id] + + addProjectStructureUpdates: (project_id, userId, docUpdates, fileUpdates) -> + @project_structures_updates[project_id] ||= { + docUpdates: [] + fileUpdates: [] + } + for update in docUpdates + update.userId = userId + @project_structures_updates[project_id].docUpdates.push(update) + + for update in fileUpdates + update.userId = userId + @project_structures_updates[project_id].fileUpdates.push(update) + run: () -> app.post "/project/:project_id/flush", (req, res, next) => res.sendStatus 200 + app.post "/project/:project_id", jsonParser, (req, res, next) => + project_id = req.params.project_id + {userId, docUpdates, fileUpdates} = req.body + @addProjectStructureUpdates(project_id, userId, docUpdates, fileUpdates) + res.sendStatus 200 + app.listen 3003, (error) -> throw error if error? .on "error", (error) -> diff --git a/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee b/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee index 2133d40b9f..c5b003ac75 100644 --- a/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee +++ b/services/web/test/acceptance/coffee/helpers/MockDocstoreApi.coffee @@ -13,6 +13,7 @@ module.exports = MockDocStoreApi = @docs[project_id][doc_id] = {lines, version, ranges} @docs[project_id][doc_id].rev ?= 0 @docs[project_id][doc_id].rev += 1 + @docs[project_id][doc_id]._id = doc_id res.json { modified: true rev: @docs[project_id][doc_id].rev diff --git a/services/web/test/acceptance/coffee/helpers/MockFileStoreApi.coffee b/services/web/test/acceptance/coffee/helpers/MockFileStoreApi.coffee new file mode 100644 index 0000000000..f3022302f4 --- /dev/null +++ b/services/web/test/acceptance/coffee/helpers/MockFileStoreApi.coffee @@ -0,0 +1,20 @@ +express = require("express") +app = express() + +module.exports = MockFileStoreApi = + files: {} + + run: () -> + app.post "/project/:project_id/file/:file_id", (req, res, next) => + req.on 'data', -> + + req.on 'end', -> + res.send 200 + + app.listen 3009, (error) -> + throw error if error? + .on "error", (error) -> + console.error "error starting MockFileStoreApi:", error.message + process.exit(1) + +MockFileStoreApi.run() diff --git a/services/web/test/acceptance/coffee/helpers/MockProjectHistoryApi.coffee b/services/web/test/acceptance/coffee/helpers/MockProjectHistoryApi.coffee new file mode 100644 index 0000000000..9027e22468 --- /dev/null +++ b/services/web/test/acceptance/coffee/helpers/MockProjectHistoryApi.coffee @@ -0,0 +1,18 @@ +express = require("express") +app = express() + +module.exports = MockProjectHistoryApi = + docs: {} + + run: () -> + app.post "/project", (req, res, next) => + res.json project: id: 1 + + app.listen 3054, (error) -> + throw error if error? + .on "error", (error) -> + console.error "error starting MockProjectHistoryApi:", error.message + process.exit(1) + + +MockProjectHistoryApi.run() diff --git a/services/web/test/acceptance/coffee/helpers/User.coffee b/services/web/test/acceptance/coffee/helpers/User.coffee index 6cd7edd7d4..ad728fb263 100644 --- a/services/web/test/acceptance/coffee/helpers/User.coffee +++ b/services/web/test/acceptance/coffee/helpers/User.coffee @@ -99,11 +99,14 @@ class User getProject: (project_id, callback = (error, project)->) -> db.projects.findOne {_id: ObjectId(project_id.toString())}, callback - createProject: (name, callback = (error, project_id) ->) -> + createProject: (name, options, callback = (error, oroject_id) ->) -> + if typeof options == "function" + callback = options + options = {} + @request.post { url: "/project/new", - json: - projectName: name + json: Object.assign({projectName: name}, options) }, (error, response, body) -> return callback(error) if error? if !body?.project_id? diff --git a/services/web/test/acceptance/files/1pixel.png b/services/web/test/acceptance/files/1pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..a97e79570bd0b360a61a563aa899ef747c985654 GIT binary patch literal 3690 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 literal 0 HcmV?d00001 diff --git a/services/web/test/acceptance/files/2pixel.png b/services/web/test/acceptance/files/2pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..dea591ec2490b22ecfce64453f367f8bf7e5ea07 GIT binary patch literal 3694 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 literal 0 HcmV?d00001 diff --git a/services/web/test/acceptance/scripts/full-test.sh b/services/web/test/acceptance/scripts/full-test.sh index ca10c32a0a..9351df81e3 100755 --- a/services/web/test/acceptance/scripts/full-test.sh +++ b/services/web/test/acceptance/scripts/full-test.sh @@ -3,7 +3,7 @@ # If you're running on OS X, you probably need to rebuild # some dependencies in the docker container, before it will start. # -# npm rebuild --update-binary +#npm rebuild --update-binary echo ">> Starting server..." From 9736513f59b38865af3243fac08c4a0a66a9d6e2 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Mon, 27 Nov 2017 17:10:20 +0000 Subject: [PATCH 22/27] fix ProjectEntityHandler.replaceFile --- .../app/coffee/Features/Project/ProjectEntityHandler.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index 5e19e4afa5..372e7e3469 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -224,9 +224,9 @@ module.exports = ProjectEntityHandler = replaceFile: (project_id, file_id, fsPath, userId, callback)-> self = ProjectEntityHandler - ProjectGetter.getProject project_id, {name:true}, (err, project) -> + FileStoreHandler.uploadFileFromDisk project_id, file_id, fsPath, (err)-> return callback(err) if err? - FileStoreHandler.uploadFileFromDisk project._id, file_id, fsPath, (err)-> + ProjectGetter.getProject project_id, {rootFolder: true, name:true}, (err, project) -> return callback(err) if err? # Note there is a potential race condition here (and elsewhere) # If the file tree changes between findElement and the Project.update From 77eac423c7e80a70a355a72fee1af9a2667d3b1b Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Wed, 29 Nov 2017 11:07:49 +0000 Subject: [PATCH 23/27] add tpds project structure acceptance tests --- .../coffee/ProjectStructureTests.coffee | 119 +++++++++++++++++- .../coffee/helpers/MockDocUpdaterApi.coffee | 16 ++- services/web/test/acceptance/files/test.tex | 1 + 3 files changed, 121 insertions(+), 15 deletions(-) create mode 100644 services/web/test/acceptance/files/test.tex diff --git a/services/web/test/acceptance/coffee/ProjectStructureTests.coffee b/services/web/test/acceptance/coffee/ProjectStructureTests.coffee index c7f429ac40..e54d4fac9d 100644 --- a/services/web/test/acceptance/coffee/ProjectStructureTests.coffee +++ b/services/web/test/acceptance/coffee/ProjectStructureTests.coffee @@ -1,7 +1,10 @@ -async = require("async") +async = require "async" expect = require("chai").expect +mkdirp = require "mkdirp" +ObjectId = require("mongojs").ObjectId Path = require "path" fs = require "fs" +Settings = require "settings-sharelatex" _ = require "underscore" ProjectGetter = require "../../../app/js/Features/Project/ProjectGetter.js" @@ -20,7 +23,7 @@ describe "ProjectStructureChanges", -> describe "creating a project from the example template", -> before (done) -> MockDocUpdaterApi.clearProjectStructureUpdates() - @owner.createProject "project", {template: "example"}, (error, project_id) => + @owner.createProject "example-project", {template: "example"}, (error, project_id) => throw error if error? @example_project_id = project_id done() @@ -133,12 +136,14 @@ describe "ProjectStructureChanges", -> describe "uploading a file", -> before (done) -> - MockDocUpdaterApi.clearProjectStructureUpdates() ProjectGetter.getProject @example_project_id, (error, projects) => throw error if error? @root_folder_id = projects[0].rootFolder[0]._id.toString() done() + beforeEach () -> + MockDocUpdaterApi.clearProjectStructureUpdates() + it "should version a newly uploaded file", (done) -> image_file = fs.createReadStream(Path.resolve(__dirname + '/../files/1pixel.png')) @@ -195,6 +200,108 @@ describe "ProjectStructureChanges", -> done() describe "tpds", -> - it "should version add a doc" - it "should version add a new file" - it "should version replacing a file" + before (done) -> + @tpds_project_name = "tpds-project-#{new ObjectId().toString()}" + @owner.createProject @tpds_project_name, (error, project_id) => + throw error if error? + @tpds_project_id = project_id + mkdirp Settings.path.dumpFolder, done + + beforeEach () -> + MockDocUpdaterApi.clearProjectStructureUpdates() + + it "should version adding a doc", (done) -> + tex_file = fs.createReadStream(Path.resolve(__dirname + '/../files/test.tex')) + + req = @owner.request.post { + uri: "/user/#{@owner._id}/update/#{@tpds_project_name}/test.tex", + auth: + user: _.keys(Settings.httpAuthUsers)[0] + pass: _.values(Settings.httpAuthUsers)[0] + sendImmediately: true + } + + tex_file.on "error", (err) -> + throw err + + req.on "error", (err) -> + throw err + + req.on "response", (res) => + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to upload file #{res.statusCode}") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@tpds_project_id).docUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/test.tex") + expect(update.docLines).to.equal("Test") + + done() + + tex_file.pipe(req) + + it "should version adding a new file", (done) -> + image_file = fs.createReadStream(Path.resolve(__dirname + '/../files/1pixel.png')) + + req = @owner.request.post { + uri: "/user/#{@owner._id}/update/#{@tpds_project_name}/1pixel.png", + auth: + user: _.keys(Settings.httpAuthUsers)[0] + pass: _.values(Settings.httpAuthUsers)[0] + sendImmediately: true + } + + image_file.on "error", (err) -> + throw err + + req.on "error", (err) -> + throw err + + req.on "response", (res) => + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to upload file #{res.statusCode}") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@tpds_project_id).fileUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/1pixel.png") + expect(update.url).to.be.a('string'); + + done() + + image_file.pipe(req) + + it "should version replacing a file", (done) -> + image_file = fs.createReadStream(Path.resolve(__dirname + '/../files/2pixel.png')) + + req = @owner.request.post { + uri: "/user/#{@owner._id}/update/#{@tpds_project_name}/1pixel.png", + auth: + user: _.keys(Settings.httpAuthUsers)[0] + pass: _.values(Settings.httpAuthUsers)[0] + sendImmediately: true + } + + image_file.on "error", (err) -> + throw err + + req.on "error", (err) -> + throw err + + req.on "response", (res) => + if res.statusCode < 200 || res.statusCode >= 300 + throw new Error("failed to upload file #{res.statusCode}") + + updates = MockDocUpdaterApi.getProjectStructureUpdates(@tpds_project_id).fileUpdates + expect(updates.length).to.equal(1) + update = updates[0] + expect(update.userId).to.equal(@owner._id) + expect(update.pathname).to.equal("/1pixel.png") + expect(update.url).to.be.a('string'); + + done() + + image_file.pipe(req) diff --git a/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee b/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee index 2147ac2691..b00cd6b173 100644 --- a/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee +++ b/services/web/test/acceptance/coffee/helpers/MockDocUpdaterApi.coffee @@ -4,26 +4,24 @@ bodyParser = require "body-parser" jsonParser = bodyParser.json() module.exports = MockDocUpdaterApi = - project_structures_updates: {} + updates: {} clearProjectStructureUpdates: () -> - @project_structures_updates = {} + @updates = {} getProjectStructureUpdates: (project_id) -> - @project_structures_updates[project_id] + @updates[project_id] || { docUpdates: [], fileUpdates: [] } addProjectStructureUpdates: (project_id, userId, docUpdates, fileUpdates) -> - @project_structures_updates[project_id] ||= { - docUpdates: [] - fileUpdates: [] - } + @updates[project_id] ||= { docUpdates: [], fileUpdates: [] } + for update in docUpdates update.userId = userId - @project_structures_updates[project_id].docUpdates.push(update) + @updates[project_id].docUpdates.push(update) for update in fileUpdates update.userId = userId - @project_structures_updates[project_id].fileUpdates.push(update) + @updates[project_id].fileUpdates.push(update) run: () -> app.post "/project/:project_id/flush", (req, res, next) => diff --git a/services/web/test/acceptance/files/test.tex b/services/web/test/acceptance/files/test.tex new file mode 100644 index 0000000000..8318c86b35 --- /dev/null +++ b/services/web/test/acceptance/files/test.tex @@ -0,0 +1 @@ +Test \ No newline at end of file From 497c6facd50456eff5513e127ab8baa0a0c8a196 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Wed, 29 Nov 2017 11:37:47 +0000 Subject: [PATCH 24/27] fix ProjectEntityHandler.replaceFile --- .../Project/ProjectEntityHandler.coffee | 34 +++++++++---------- .../Project/ProjectEntityHandlerTests.coffee | 31 ++++++++--------- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index 372e7e3469..9549417403 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -224,7 +224,7 @@ module.exports = ProjectEntityHandler = replaceFile: (project_id, file_id, fsPath, userId, callback)-> self = ProjectEntityHandler - FileStoreHandler.uploadFileFromDisk project_id, file_id, fsPath, (err)-> + FileStoreHandler.uploadFileFromDisk project_id, file_id, fsPath, (err, fileStoreUrl)-> return callback(err) if err? ProjectGetter.getProject project_id, {rootFolder: true, name:true}, (err, project) -> return callback(err) if err? @@ -233,25 +233,25 @@ module.exports = ProjectEntityHandler = # then the path to the file element will be out of date. In practice # this is not a problem so long as we do not do anything longer running # between them (like waiting for the file to upload.) - self.getAllEntitiesFromProject project, (err, oldDocs, oldFiles) => + projectLocator.findElement {project:project, element_id: file_id, type: 'file'}, (err, fileRef, path)=> return callback(err) if err? - projectLocator.findElement {project:project, element_id: file_id, type: 'file'}, (err, fileRef, path)=> + tpdsUpdateSender.addFile {project_id:project._id, file_id:fileRef._id, path:path.fileSystem, rev:fileRef.rev+1, project_name:project.name}, (err) -> return callback(err) if err? - tpdsUpdateSender.addFile {project_id:project._id, file_id:fileRef._id, path:path.fileSystem, rev:fileRef.rev+1, project_name:project.name}, (err) -> + conditions = _id:project._id + inc = {} + inc["#{path.mongo}.rev"] = 1 + set = {} + set["#{path.mongo}.created"] = new Date() + update = + "$inc": inc + "$set": set + Project.findOneAndUpdate conditions, update, { "new": true}, (err) -> return callback(err) if err? - conditions = _id:project._id - inc = {} - inc["#{path.mongo}.rev"] = 1 - set = {} - set["#{path.mongo}.created"] = new Date() - update = - "$inc": inc - "$set": set - Project.findOneAndUpdate conditions, update, { "new": true}, (err, newProject) -> - return callback(err) if err? - self.getAllEntitiesFromProject newProject, (err, newDocs, newFiles) => - return callback(err) if err? - DocumentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback + newFile = + file: fileRef + path: path.fileSystem + url: fileStoreUrl + DocumentUpdaterHandler.updateProjectStructure project_id, userId, [], [], [], [newFile], callback copyFileFromExistingProjectWithProject: (project, folder_id, originalProject_id, origonalFileRef, userId, callback = (error, fileRef, folder_id) ->)-> project_id = project._id diff --git a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee index 881b579150..18e44f46a6 100644 --- a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee @@ -582,24 +582,15 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, userId, () -> - describe 'replacing a file', -> + describe 'replaceFile', -> beforeEach -> @projectLocator @file_id = "file_id_here" @fsPath = "fs_path_here.png" - @fileRef = {rev:3, _id:@file_id} - @filePaths = {fileSystem:"/folder1/file.png", mongo:"folder.1.files.somewhere"} + @fileRef = {rev:3, _id: @file_id, name: @fileName = "fileName"} + @filePaths = {fileSystem: @fileSystemPath="/folder1/file.png", mongo:"folder.1.files.somewhere"} @projectLocator.findElement = sinon.stub().callsArgWith(1, null, @fileRef, @filePaths) - - @ProjectEntityHandler.getAllEntitiesFromProject = sinon.stub() - @ProjectEntityHandler.getAllEntitiesFromProject - .onFirstCall() - .callsArgWith(1, null, [], @oldFiles = ['old-file']) - @ProjectEntityHandler.getAllEntitiesFromProject - .onSecondCall() - .callsArgWith(1, null, [], @newFiles = ['new-file']) - @ProjectModel.findOneAndUpdate = sinon.stub().callsArgWith(3, null, @project) - + @ProjectModel.findOneAndUpdate = sinon.stub().callsArgWith(3) @ProjectGetter.getProject = sinon.stub().callsArgWith(2, null, @project) it 'should find the file', (done)-> @@ -644,12 +635,18 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, userId, => it "should should send the old and new project structure to the doc updater", (done) -> - @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, userId, => - @documentUpdaterHandler.updateProjectStructure - .calledWith(project_id, userId, [], [], @oldFiles, @newFiles) - .should.equal true + @documentUpdaterHandler.updateProjectStructure = (passed_project_id, passed_user_id, oldDocs, newDocs, oldFiles, newFiles) => + passed_project_id.should.equal project_id + passed_user_id.should.equal userId + newFiles.length.should.equal 1 + newFile = newFiles[0] + newFile.file.name.should.equal @fileName + newFile.path.should.equal @fileSystemPath + newFile.url.should.equal @fileUrl done() + @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, userId, => + describe 'addFolder', -> folderName = "folder1234" beforeEach -> From 19643f4bb549b30810052c54a71a37c74c5b0861 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Wed, 29 Nov 2017 11:41:52 +0000 Subject: [PATCH 25/27] pass user_id into editorController.addDoc in ThirdPartyDataStore/UpdateMerger --- .../app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee | 2 +- .../unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee b/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee index 9671524f67..010594d16a 100644 --- a/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee +++ b/services/web/app/coffee/Features/ThirdPartyDataStore/UpdateMerger.coffee @@ -57,7 +57,7 @@ module.exports = if err? logger.err err:err, project_id:project_id, doc_id:doc_id, path:path, "error processing file" return callback(err) - editorController.addDoc project_id, folder._id, fileName, docLines, source, callback + editorController.addDoc project_id, folder._id, fileName, docLines, source, user_id, callback processFile: (project_id, file_id, fsPath, path, source, user_id, callback)-> finish = (err)-> diff --git a/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee b/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee index 196c502dbf..e20419765f 100644 --- a/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee +++ b/services/web/test/unit/coffee/ThirdPartyDataStore/UpdateMergerTests.coffee @@ -97,7 +97,7 @@ describe 'UpdateMerger :', -> path = "folder1/folder2/#{docName}" @editorController.mkdirp = sinon.stub().withArgs(@project_id).callsArgWith(2, null, [folder], folder) @editorController.addDoc = -> - mock = sinon.mock(@editorController).expects("addDoc").withArgs(@project_id, folder._id, docName, @splitDocLines, @source).callsArg(5) + mock = sinon.mock(@editorController).expects("addDoc").withArgs(@project_id, folder._id, docName, @splitDocLines, @source, @user_id).callsArg(6) @update.write(@docLines) @update.end() From 1405b645f33506d2584bb3832918f3d75ba300f4 Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Thu, 30 Nov 2017 13:49:08 +0000 Subject: [PATCH 26/27] fix acceptance tests after rebase --- services/web/docker-compose.yml | 1 + services/web/docker-shared.template.yml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/services/web/docker-compose.yml b/services/web/docker-compose.yml index aaa8666a16..ed12abf0be 100644 --- a/services/web/docker-compose.yml +++ b/services/web/docker-compose.yml @@ -24,6 +24,7 @@ services: REDIS_HOST: redis MONGO_URL: "mongodb://mongo/sharelatex" SHARELATEX_ALLOW_PUBLIC_ACCESS: 'true' + PROJECT_HISTORY_ENABLED: 'true' depends_on: - redis - mongo diff --git a/services/web/docker-shared.template.yml b/services/web/docker-shared.template.yml index 48adb7a036..d697e59e96 100644 --- a/services/web/docker-shared.template.yml +++ b/services/web/docker-shared.template.yml @@ -25,6 +25,7 @@ services: - ./config:/app/config - ./test/unit/coffee:/app/test/unit/coffee:ro - ./test/acceptance/coffee:/app/test/acceptance/coffee:ro + - ./test/acceptance/files:/app/test/acceptance/files:ro - ./test/smoke/coffee:/app/test/smoke/coffee:ro MODULE_VOLUMES - working_dir: /app \ No newline at end of file + working_dir: /app From 4094801f187fbaa1fdb920e4e6667107e9820e2e Mon Sep 17 00:00:00 2001 From: Hayden Faulds Date: Thu, 30 Nov 2017 15:46:37 +0000 Subject: [PATCH 27/27] pass object to DocumentUpdater.updateProjectStructure instead of separate arrays --- .../DocumentUpdaterHandler.coffee | 8 ++-- .../Project/ProjectEntityHandler.coffee | 24 ++++++---- .../DocumentUpdaterHandlerTests.coffee | 47 ++++++++----------- .../Project/ProjectEntityHandlerTests.coffee | 24 ++++++---- 4 files changed, 52 insertions(+), 51 deletions(-) diff --git a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee index fc4b5c452b..f7dd9f3e17 100644 --- a/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee +++ b/services/web/app/coffee/Features/DocumentUpdater/DocumentUpdaterHandler.coffee @@ -204,11 +204,11 @@ module.exports = DocumentUpdaterHandler = logger.error {project_id, doc_id, thread_id}, "doc updater returned a non-success status code: #{res.statusCode}" callback new Error("doc updater returned a non-success status code: #{res.statusCode}") - updateProjectStructure : (project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback = (error) ->)-> + updateProjectStructure : (project_id, userId, changes, callback = (error) ->)-> return callback() if !settings.apis.project_history?.enabled - docUpdates = DocumentUpdaterHandler._getRenameUpdates('doc', oldDocs, newDocs) - fileUpdates = DocumentUpdaterHandler._getRenameUpdates('file', oldFiles, newFiles) + docUpdates = DocumentUpdaterHandler._getRenameUpdates('doc', changes.oldDocs, changes.newDocs) + fileUpdates = DocumentUpdaterHandler._getRenameUpdates('file', changes.oldFiles, changes.newFiles) timer = new metrics.Timer("set-document") url = "#{settings.apis.documentupdater.url}/project/#{project_id}" @@ -231,6 +231,8 @@ module.exports = DocumentUpdaterHandler = callback new Error("doc updater returned a non-success status code: #{res.statusCode}") _getRenameUpdates: (entityType, oldEntities, newEntities) -> + oldEntities ||= [] + newEntities ||= [] updates = [] oldEntitiesHash = _.indexBy oldEntities, (entity) -> entity[entityType]._id.toString() diff --git a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee index 9549417403..446786fa57 100644 --- a/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee +++ b/services/web/app/coffee/Features/Project/ProjectEntityHandler.coffee @@ -176,11 +176,12 @@ module.exports = ProjectEntityHandler = rev: 0 }, (err) -> return callback(err) if err? - newDoc = + newDocs = [ doc: doc path: result?.path?.fileSystem docLines: docLines.join('\n') - DocumentUpdaterHandler.updateProjectStructure project_id, userId, [], [newDoc], [], [], (error) -> + ] + DocumentUpdaterHandler.updateProjectStructure project_id, userId, {newDocs}, (error) -> return callback(error) if error? callback null, doc, folder_id @@ -214,11 +215,12 @@ module.exports = ProjectEntityHandler = return callback(err) tpdsUpdateSender.addFile {project_id:project._id, file_id:fileRef._id, path:result?.path?.fileSystem, project_name:project.name, rev:fileRef.rev}, (err) -> return callback(err) if err? - newFile = + newFiles = [ file: fileRef path: result?.path?.fileSystem url: fileStoreUrl - DocumentUpdaterHandler.updateProjectStructure project_id, userId, [], [], [], [newFile], (error) -> + ] + DocumentUpdaterHandler.updateProjectStructure project_id, userId, {newFiles}, (error) -> return callback(error) if error? callback null, fileRef, folder_id @@ -247,11 +249,12 @@ module.exports = ProjectEntityHandler = "$set": set Project.findOneAndUpdate conditions, update, { "new": true}, (err) -> return callback(err) if err? - newFile = + newFiles = [ file: fileRef path: path.fileSystem url: fileStoreUrl - DocumentUpdaterHandler.updateProjectStructure project_id, userId, [], [], [], [newFile], callback + ] + DocumentUpdaterHandler.updateProjectStructure project_id, userId, {newFiles}, callback copyFileFromExistingProjectWithProject: (project, folder_id, originalProject_id, origonalFileRef, userId, callback = (error, fileRef, folder_id) ->)-> project_id = project._id @@ -273,11 +276,12 @@ module.exports = ProjectEntityHandler = tpdsUpdateSender.addFile { project_id, file_id:fileRef._id, path:result?.path?.fileSystem, rev:fileRef.rev, project_name:project.name}, (err) -> if err? logger.err { err, project_id, folder_id, originalProject_id, origonalFileRef }, "error sending file to tpds worker" - newFile = + newFiles = [ file: fileRef path: result?.path?.fileSystem url: fileStoreUrl - DocumentUpdaterHandler.updateProjectStructure project_id, userId, [], [], [], [newFile], (error) -> + ] + DocumentUpdaterHandler.updateProjectStructure project_id, userId, {newFiles}, (error) -> return callback(error) if error? callback null, fileRef, folder_id @@ -393,7 +397,7 @@ module.exports = ProjectEntityHandler = tpdsUpdateSender.moveEntity opts self.getAllEntitiesFromProject newProject, (error, newDocs, newFiles) => return callback(error) if error? - DocumentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback + DocumentUpdaterHandler.updateProjectStructure project_id, userId, {oldDocs, newDocs, oldFiles, newFiles}, callback _checkValidMove: (project, entityType, entityPath, destFolderId, callback = (error) ->) -> return callback() if !entityType.match(/folder/) @@ -450,7 +454,7 @@ module.exports = ProjectEntityHandler = return callback(error) if error? ProjectEntityHandler.getAllEntitiesFromProject newProject, (error, newDocs, newFiles) => return callback(error) if error? - DocumentUpdaterHandler.updateProjectStructure project_id, userId, oldDocs, newDocs, oldFiles, newFiles, callback + DocumentUpdaterHandler.updateProjectStructure project_id, userId, {oldDocs, newDocs, oldFiles, newFiles}, callback _cleanUpEntity: (project, entity, entityType, callback = (error) ->) -> if(entityType.indexOf("file") != -1) diff --git a/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee b/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee index 99214749d6..14ccaa3a33 100644 --- a/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee +++ b/services/web/test/unit/coffee/DocumentUpdater/DocumentUpdaterHandlerTests.coffee @@ -396,7 +396,7 @@ describe 'DocumentUpdaterHandler', -> @settings.apis.project_history.enabled = false @request.post = sinon.stub() - @handler.updateProjectStructure @project_id, @user_id, @oldDocs, @newDocs, @oldFiles, @newFiles, @callback + @handler.updateProjectStructure @project_id, @user_id, {}, @callback it 'does not make a web request', -> @request.post.called.should.equal false @@ -414,17 +414,17 @@ describe 'DocumentUpdaterHandler', -> it 'should send the structure update to the document updater', (done) -> @docIdA = new ObjectId() @docIdB = new ObjectId() - @oldDocs = [ - { path: '/old_a', doc: _id: @docIdA } - { path: '/old_b', doc: _id: @docIdB } - ] - # create new instances of the same ObjectIds so that == doens't pass - @newDocs = [ - { path: '/old_a', doc: _id: new ObjectId(@docIdA.toString()) } - { path: '/new_b', doc: _id: new ObjectId(@docIdB.toString()) } - ] - @oldFiles = [] - @newFiles = [] + @changes = { + oldDocs: [ + { path: '/old_a', doc: _id: @docIdA } + { path: '/old_b', doc: _id: @docIdB } + ] + # create new instances of the same ObjectIds so that == doesn't pass + newDocs: [ + { path: '/old_a', doc: _id: new ObjectId(@docIdA.toString()) } + { path: '/new_b', doc: _id: new ObjectId(@docIdB.toString()) } + ] + } docUpdates = [ id: @docIdB.toString(), @@ -432,7 +432,7 @@ describe 'DocumentUpdaterHandler', -> newPathname: "/new_b" ] - @handler.updateProjectStructure @project_id, @user_id, @oldDocs, @newDocs, @oldFiles, @newFiles, () => + @handler.updateProjectStructure @project_id, @user_id, @changes, () => @request.post .calledWith(url: @url, json: {docUpdates, fileUpdates: [], userId: @user_id}) .should.equal true @@ -441,12 +441,9 @@ describe 'DocumentUpdaterHandler', -> describe "when a doc has been added", -> it 'should send the structure update to the document updater', (done) -> @docId = new ObjectId() - @oldDocs = [] - @newDocs = [ + @changes = newDocs: [ { path: '/foo', docLines: 'a\nb', doc: _id: @docId } ] - @oldFiles = [] - @newFiles = [] docUpdates = [ id: @docId.toString(), @@ -455,7 +452,7 @@ describe 'DocumentUpdaterHandler', -> url: undefined ] - @handler.updateProjectStructure @project_id, @user_id, @oldDocs, @newDocs, @oldFiles, @newFiles, () => + @handler.updateProjectStructure @project_id, @user_id, @changes, () => @request.post .calledWith(url: @url, json: {docUpdates, fileUpdates: [], userId: @user_id}) .should.equal true @@ -464,10 +461,7 @@ describe 'DocumentUpdaterHandler', -> describe "when a file has been added", -> it 'should send the structure update to the document updater', (done) -> @fileId = new ObjectId() - @oldDocs = [] - @newDocs = [] - @oldFiles = [] - @newFiles = [ + @changes = newFiles: [ { path: '/bar', url: 'filestore.example.com/file', file: _id: @fileId } ] @@ -478,7 +472,7 @@ describe 'DocumentUpdaterHandler', -> docLines: undefined ] - @handler.updateProjectStructure @project_id, @user_id, @oldDocs, @newDocs, @oldFiles, @newFiles, () => + @handler.updateProjectStructure @project_id, @user_id, @changes, () => @request.post .calledWith(url: @url, json: {docUpdates: [], fileUpdates, userId: @user_id}) .should.equal true @@ -487,14 +481,11 @@ describe 'DocumentUpdaterHandler', -> describe "when a doc has been deleted", -> it 'should do nothing', (done) -> @docId = new ObjectId() - @oldDocs = [ + @changes = oldDocs: [ { path: '/foo', docLines: 'a\nb', doc: _id: @docId } ] - @newDocs = [] - @oldFiles = [] - @newFiles = [] - @handler.updateProjectStructure @project_id, @user_id, @oldDocs, @newDocs, @oldFiles, @newFiles, () => + @handler.updateProjectStructure @project_id, @user_id, @changes, () => @request.post.called.should.equal false done() diff --git a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee index 18e44f46a6..f62690e226 100644 --- a/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee +++ b/services/web/test/unit/coffee/Project/ProjectEntityHandlerTests.coffee @@ -69,7 +69,7 @@ describe 'ProjectEntityHandler', -> @settings = maxEntitiesPerProject:200 @documentUpdaterHandler = - updateProjectStructure: sinon.stub().callsArg(6) + updateProjectStructure: sinon.stub().yields() deleteDoc: sinon.stub().callsArg(2) @ProjectEntityHandler = SandboxedModule.require modulePath, requires: '../../models/Project': Project:@ProjectModel @@ -274,7 +274,7 @@ describe 'ProjectEntityHandler', -> it "should should send the update to the doc updater", -> @documentUpdaterHandler.updateProjectStructure - .calledWith(project_id, userId, @oldDocs, @newDocs, @oldFiles, @newFiles) + .calledWith(project_id, userId, {@oldDocs, @newDocs, @oldFiles, @newFiles}) .should.equal true it 'should remove the element from its current position', -> @@ -326,7 +326,7 @@ describe 'ProjectEntityHandler', -> it "should should send the update to the doc updater", -> @documentUpdaterHandler.updateProjectStructure - .calledWith(project_id, userId, @oldDocs, @newDocs, @oldFiles, @newFiles) + .calledWith(project_id, userId, {@oldDocs, @newDocs, @oldFiles, @newFiles}) .should.equal true it 'should remove the element from its current position', -> @@ -487,12 +487,13 @@ describe 'ProjectEntityHandler', -> .should.equal true it "should should send the change in project structure to the doc updater", () -> - newDoc = + newDocs = [ doc: @doc path: @path docLines: @lines.join('\n') + ] @documentUpdaterHandler.updateProjectStructure - .calledWith(project_id, userId, [], [newDoc], [], []) + .calledWith(project_id, userId, {newDocs}) .should.equal true describe "restoreDoc", -> @@ -570,9 +571,10 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.addFile project_id, folder_id, fileName, {}, userId, (err, fileRef, parentFolder)-> it "should should send the change in project structure to the doc updater", (done) -> - @documentUpdaterHandler.updateProjectStructure = (passed_project_id, passed_user_id, oldDocs, newDocs, oldFiles, newFiles) => + @documentUpdaterHandler.updateProjectStructure = (passed_project_id, passed_user_id, changes) => passed_project_id.should.equal project_id passed_user_id.should.equal userId + { newFiles } = changes newFiles.length.should.equal 1 newFile = newFiles[0] newFile.file.name.should.equal fileName @@ -635,9 +637,10 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.replaceFile project_id, @file_id, @fsPath, userId, => it "should should send the old and new project structure to the doc updater", (done) -> - @documentUpdaterHandler.updateProjectStructure = (passed_project_id, passed_user_id, oldDocs, newDocs, oldFiles, newFiles) => + @documentUpdaterHandler.updateProjectStructure = (passed_project_id, passed_user_id, changes) => passed_project_id.should.equal project_id passed_user_id.should.equal userId + { newFiles } = changes newFiles.length.should.equal 1 newFile = newFiles[0] newFile.file.name.should.equal @fileName @@ -1029,9 +1032,10 @@ describe 'ProjectEntityHandler', -> @ProjectEntityHandler.copyFileFromExistingProjectWithProject @project, folder_id, oldProject_id, oldFileRef, userId, (err, fileRef, parentFolder)-> it "should should send the change in project structure to the doc updater", (done) -> - @documentUpdaterHandler.updateProjectStructure = (passed_project_id, passed_user_id, oldDocs, newDocs, oldFiles, newFiles) => + @documentUpdaterHandler.updateProjectStructure = (passed_project_id, passed_user_id, changes) => passed_project_id.should.equal project_id passed_user_id.should.equal userId + { newFiles } = changes newFiles.length.should.equal 1 newFile = newFiles[0] newFile.file.name.should.equal fileName @@ -1060,12 +1064,12 @@ describe 'ProjectEntityHandler', -> @projectLocator.findElement = sinon.stub().callsArgWith(1, null, @entity = { _id: @entity_id, name:"old.tex", rev:4 }, @path) @tpdsUpdateSender.moveEntity = sinon.stub() @ProjectModel.findOneAndUpdate = sinon.stub().callsArgWith(3, null, @project) - @documentUpdaterHandler.updateProjectStructure = sinon.stub().callsArg(6) + @documentUpdaterHandler.updateProjectStructure = sinon.stub().yields() it "should should send the old and new project structure to the doc updater", (done) -> @ProjectEntityHandler.renameEntity project_id, @entity_id, @entityType, @newName, userId, => @documentUpdaterHandler.updateProjectStructure - .calledWith(project_id, userId, @oldDocs, @newDocs, @oldFiles, @newFiles) + .calledWith(project_id, userId, {@oldDocs, @newDocs, @oldFiles, @newFiles}) .should.equal true done()