mirror of
https://github.com/overleaf/overleaf.git
synced 2025-03-03 11:31:45 +00:00
Merge branch 'master' of github.com:sharelatex/web-sharelatex-internal
This commit is contained in:
commit
a0c7295b36
8 changed files with 291 additions and 170 deletions
|
@ -204,6 +204,48 @@ 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) ->)->
|
||||
return callback() if !settings.apis.project_history?.enabled
|
||||
|
||||
docUpdates = DocumentUpdaterHandler._getRenameUpdates('doc', oldDocs, newDocs)
|
||||
fileUpdates = DocumentUpdaterHandler._getRenameUpdates('file', oldFiles, newFiles)
|
||||
|
||||
timer = new metrics.Timer("set-document")
|
||||
url = "#{settings.apis.documentupdater.url}/project/#{project_id}"
|
||||
body =
|
||||
url: url
|
||||
json: { docUpdates, fileUpdates, userId }
|
||||
|
||||
return callback() if (docUpdates.length + fileUpdates.length) < 1
|
||||
|
||||
request.post body, (error, res, body)->
|
||||
timer.done()
|
||||
if error?
|
||||
logger.error {error, url, project_id}, "error update project structure in doc updater"
|
||||
callback(error)
|
||||
else if res.statusCode >= 200 and res.statusCode < 300
|
||||
logger.error {project_id}, "updated project structure in doc updater"
|
||||
callback(null)
|
||||
else
|
||||
logger.error {project_id, url}, "doc updater returned a non-success status code: #{res.statusCode}"
|
||||
callback new Error("doc updater returned a non-success status code: #{res.statusCode}")
|
||||
|
||||
_getRenameUpdates: (entityType, oldEntities, newEntities) ->
|
||||
updates = []
|
||||
|
||||
for oldEntity in oldEntities
|
||||
id = oldEntity[entityType]._id
|
||||
newEntity = _.find newEntities, (newEntity) ->
|
||||
newEntity[entityType]._id.toString() == id.toString()
|
||||
|
||||
if newEntity.path != oldEntity.path
|
||||
updates.push
|
||||
id: id
|
||||
pathname: oldEntity.path
|
||||
newPathname: newEntity.path
|
||||
|
||||
updates
|
||||
|
||||
PENDINGUPDATESKEY = "PendingUpdates"
|
||||
DOCLINESKEY = "doclines"
|
||||
DOCIDSWITHPENDINGUPDATES = "DocsWithPendingUpdates"
|
||||
|
|
|
@ -150,11 +150,11 @@ module.exports = EditorController =
|
|||
logger.log project_id:project_id, "recived message to delete project"
|
||||
ProjectDeleter.deleteProject project_id, callback
|
||||
|
||||
renameEntity: (project_id, entity_id, entityType, newName, callback)->
|
||||
renameEntity: (project_id, entity_id, entityType, newName, userId, callback)->
|
||||
newName = sanitize.escape(newName)
|
||||
Metrics.inc "editor.rename-entity"
|
||||
logger.log entity_id:entity_id, entity_id:entity_id, entity_id:entity_id, "reciving new name for entity for project"
|
||||
ProjectEntityHandler.renameEntity project_id, entity_id, entityType, newName, ->
|
||||
ProjectEntityHandler.renameEntity project_id, entity_id, entityType, newName, userId, (err) ->
|
||||
if err?
|
||||
logger.err err:err, project_id:project_id, entity_id:entity_id, entityType:entityType, newName:newName, "error renaming entity"
|
||||
return callback(err)
|
||||
|
@ -162,13 +162,13 @@ module.exports = EditorController =
|
|||
EditorRealTimeController.emitToRoom project_id, 'reciveEntityRename', entity_id, newName
|
||||
callback?()
|
||||
|
||||
moveEntity: (project_id, entity_id, folder_id, entityType, callback)->
|
||||
moveEntity: (project_id, entity_id, folder_id, entityType, userId, callback)->
|
||||
Metrics.inc "editor.move-entity"
|
||||
LockManager.getLock project_id, (err)->
|
||||
if err?
|
||||
logger.err err:err, project_id:project_id, "could not get lock for move entity"
|
||||
return callback(err)
|
||||
ProjectEntityHandler.moveEntity project_id, entity_id, folder_id, entityType, =>
|
||||
ProjectEntityHandler.moveEntity project_id, entity_id, folder_id, entityType, userId, =>
|
||||
if err?
|
||||
logger.err err:err, project_id:project_id, entity_id:entity_id, folder_id:folder_id, "error moving entity"
|
||||
return callback(err)
|
||||
|
|
|
@ -12,6 +12,7 @@ CollaboratorsHandler = require("../Collaborators/CollaboratorsHandler")
|
|||
CollaboratorsInviteHandler = require("../Collaborators/CollaboratorsInviteHandler")
|
||||
PrivilegeLevels = require "../Authorization/PrivilegeLevels"
|
||||
TokenAccessHandler = require '../TokenAccess/TokenAccessHandler'
|
||||
AuthenticationController = require "../Authentication/AuthenticationController"
|
||||
|
||||
module.exports = EditorHttpController =
|
||||
joinProject: (req, res, next) ->
|
||||
|
@ -112,9 +113,10 @@ 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
|
||||
EditorController.renameEntity project_id, entity_id, entity_type, name, (error) ->
|
||||
EditorController.renameEntity project_id, entity_id, entity_type, name, user_id, (error) ->
|
||||
return next(error) if error?
|
||||
res.sendStatus 204
|
||||
|
||||
|
@ -123,7 +125,8 @@ module.exports = EditorHttpController =
|
|||
entity_id = req.params.entity_id
|
||||
entity_type = req.params.entity_type
|
||||
folder_id = req.body.folder_id
|
||||
EditorController.moveEntity project_id, entity_id, folder_id, entity_type, (error) ->
|
||||
user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
EditorController.moveEntity project_id, entity_id, folder_id, entity_type, user_id, (error) ->
|
||||
return next(error) if error?
|
||||
res.sendStatus 204
|
||||
|
||||
|
|
|
@ -355,47 +355,50 @@ module.exports = ProjectEntityHandler =
|
|||
else
|
||||
callback()
|
||||
|
||||
moveEntity: (project_id, entity_id, folder_id, entityType, callback = (error) ->)->
|
||||
moveEntity: (project_id, entity_id, destFolderId, entityType, userId, callback = (error) ->)->
|
||||
self = @
|
||||
destinationFolder_id = folder_id
|
||||
logger.log entityType:entityType, entity_id:entity_id, project_id:project_id, folder_id:folder_id, "moving entity"
|
||||
logger.log {entityType, entity_id, project_id, destFolderId}, "moving entity"
|
||||
if !entityType?
|
||||
logger.err err: "No entityType set", project_id: project_id, entity_id: entity_id
|
||||
logger.err {err: "No entityType set", project_id, entity_id}
|
||||
return callback("No entityType set")
|
||||
entityType = entityType.toLowerCase()
|
||||
ProjectGetter.getProject project_id, {rootFolder:true, name:true}, (err, project)=>
|
||||
return callback(err) if err?
|
||||
projectLocator.findElement {project:project, element_id:entity_id, type:entityType}, (err, entity, path)->
|
||||
projectLocator.findElement {project, element_id: entity_id, type: entityType}, (err, entity, entityPath)->
|
||||
return callback(err) if err?
|
||||
|
||||
if entityType.match(/folder/)
|
||||
ensureFolderIsNotMovedIntoChild = (callback = (error) ->) ->
|
||||
projectLocator.findElement {project: project, element_id: folder_id, type:"folder"}, (err, destEntity, destPath) ->
|
||||
logger.log destPath: destPath.fileSystem, folderPath: path.fileSystem, "checking folder is not moving into child folder"
|
||||
if (destPath.fileSystem.slice(0, path.fileSystem.length) == path.fileSystem)
|
||||
logger.log "destination is a child folder, aborting"
|
||||
callback(new Error("destination folder is a child folder of me"))
|
||||
else
|
||||
callback()
|
||||
else
|
||||
ensureFolderIsNotMovedIntoChild = (callback = () ->) -> callback()
|
||||
|
||||
ensureFolderIsNotMovedIntoChild (error) ->
|
||||
self._checkValidMove project, entityType, entityPath, destFolderId, (error) ->
|
||||
return callback(error) if error?
|
||||
self._removeElementFromMongoArray Project, project_id, path.mongo, (err)->
|
||||
return callback(err) if err?
|
||||
# We've updated the project structure by removing the element, so must refresh it.
|
||||
ProjectGetter.getProject project_id, {rootFolder:true, name:true}, (err, project)=>
|
||||
self.getAllEntitiesFromProject project, (error, oldDocs, oldFiles) =>
|
||||
return callback(error) if error?
|
||||
self._removeElementFromMongoArray Project, project_id, entityPath.mongo, (err, newProject)->
|
||||
return callback(err) if err?
|
||||
ProjectEntityHandler._putElement project, destinationFolder_id, entity, entityType, (err, result)->
|
||||
self._putElement newProject, destFolderId, entity, entityType, (err, result, newProject)->
|
||||
return callback(err) if err?
|
||||
opts =
|
||||
project_id:project_id
|
||||
project_name:project.name
|
||||
startPath:path.fileSystem
|
||||
endPath:result.path.fileSystem,
|
||||
rev:entity.rev
|
||||
tpdsUpdateSender.moveEntity opts, callback
|
||||
project_id: project_id
|
||||
project_name: project.name
|
||||
startPath: entityPath.fileSystem
|
||||
endPath: result.path.fileSystem,
|
||||
rev: entity.rev
|
||||
tpdsUpdateSender.moveEntity opts
|
||||
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) ->) ->
|
||||
return callback() if !entityType.match(/folder/)
|
||||
|
||||
projectLocator.findElement { project, element_id: destFolderId, type:"folder"}, (err, destEntity, destFolderPath) ->
|
||||
return callback(err) if err?
|
||||
logger.log destFolderPath: destFolderPath.fileSystem, folderPath: entityPath.fileSystem, "checking folder is not moving into child folder"
|
||||
isNestedFolder = destFolderPath.fileSystem.slice(0, entityPath.fileSystem.length) == entityPath.fileSystem
|
||||
if isNestedFolder
|
||||
callback(new Error("destination folder is a child folder of me"))
|
||||
else
|
||||
callback()
|
||||
|
||||
|
||||
deleteEntity: (project_id, entity_id, entityType, callback = (error) ->)->
|
||||
self = @
|
||||
|
@ -417,25 +420,30 @@ module.exports = ProjectEntityHandler =
|
|||
callback null
|
||||
|
||||
|
||||
renameEntity: (project_id, entity_id, entityType, newName, callback)->
|
||||
renameEntity: (project_id, entity_id, entityType, newName, userId, callback)->
|
||||
logger.log(entity_id: entity_id, project_id: project_id, ('renaming '+entityType))
|
||||
if !entityType?
|
||||
logger.err err: "No entityType set", project_id: project_id, entity_id: entity_id
|
||||
return callback("No entityType set")
|
||||
entityType = entityType.toLowerCase()
|
||||
ProjectGetter.getProject project_id, {rootFolder:true, name:true}, (err, project)=>
|
||||
projectLocator.findElement {project:project, element_id:entity_id, type:entityType}, (err, entity, path, folder)=>
|
||||
if err?
|
||||
return callback err
|
||||
conditons = {_id:project_id}
|
||||
update = "$set":{}
|
||||
namePath = path.mongo+".name"
|
||||
update["$set"][namePath] = newName
|
||||
endPath = path.fileSystem.replace(entity.name, newName)
|
||||
tpdsUpdateSender.moveEntity({project_id:project_id, startPath:path.fileSystem, endPath:endPath, project_name:project.name, rev:entity.rev})
|
||||
Project.update conditons, update, {}, (err)->
|
||||
if callback?
|
||||
callback err
|
||||
ProjectGetter.getProject project_id, {rootFolder:true, name:true}, (error, project)=>
|
||||
return callback(error) if error?
|
||||
ProjectEntityHandler.getAllEntitiesFromProject project, (error, oldDocs, oldFiles) =>
|
||||
return callback(error) if error?
|
||||
projectLocator.findElement {project:project, element_id:entity_id, type:entityType}, (error, entity, path)=>
|
||||
return callback(error) if error?
|
||||
endPath = path.fileSystem.replace(entity.name, newName)
|
||||
conditions = {_id:project_id}
|
||||
update = "$set":{}
|
||||
namePath = path.mongo+".name"
|
||||
update["$set"][namePath] = newName
|
||||
tpdsUpdateSender.moveEntity({project_id:project_id, startPath:path.fileSystem, endPath:endPath, project_name:project.name, rev:entity.rev})
|
||||
Project.findOneAndUpdate conditions, update, { "new": true}, (error, newProject) ->
|
||||
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) ->) ->
|
||||
if(entityType.indexOf("file") != -1)
|
||||
|
@ -487,17 +495,15 @@ module.exports = ProjectEntityHandler =
|
|||
|
||||
async.series jobs, callback
|
||||
|
||||
_removeElementFromMongoArray : (model, model_id, path, callback)->
|
||||
conditons = {_id:model_id}
|
||||
_removeElementFromMongoArray : (model, model_id, path, callback = (err, project) ->)->
|
||||
conditions = {_id:model_id}
|
||||
update = {"$unset":{}}
|
||||
update["$unset"][path] = 1
|
||||
model.update conditons, update, {}, (err)->
|
||||
model.update conditions, update, {}, (err)->
|
||||
pullUpdate = {"$pull":{}}
|
||||
nonArrayPath = path.slice(0, path.lastIndexOf("."))
|
||||
pullUpdate["$pull"][nonArrayPath] = null
|
||||
model.update conditons, pullUpdate, {}, (err)->
|
||||
if callback?
|
||||
callback(err)
|
||||
model.findOneAndUpdate conditions, pullUpdate, {"new": true}, callback
|
||||
|
||||
_insertDeletedDocReference: (project_id, doc, callback = (error) ->) ->
|
||||
Project.update {
|
||||
|
@ -534,8 +540,7 @@ module.exports = ProjectEntityHandler =
|
|||
|
||||
countFolder project.rootFolder[0], callback
|
||||
|
||||
_putElement: (project, folder_id, element, type, callback = (err, path)->)->
|
||||
|
||||
_putElement: (project, folder_id, element, type, callback = (err, path, project)->)->
|
||||
sanitizeTypeOfElement = (elementType)->
|
||||
lastChar = elementType.slice -1
|
||||
if lastChar != "s"
|
||||
|
@ -576,11 +581,11 @@ module.exports = ProjectEntityHandler =
|
|||
update = "$push":{}
|
||||
update["$push"][mongopath] = element
|
||||
logger.log project_id: project._id, element_id: element._id, fileType: type, folder_id: folder_id, mongopath:mongopath, "adding element to project"
|
||||
Project.update conditions, update, {}, (err)->
|
||||
Project.findOneAndUpdate conditions, update, {"new": true}, (err, project)->
|
||||
if err?
|
||||
logger.err err: err, project_id: project._id, 'error saving in putElement project'
|
||||
return callback(err)
|
||||
callback(err, {path:newPath})
|
||||
callback(err, {path:newPath}, project)
|
||||
|
||||
|
||||
confirmFolder = (project, folder_id, callback)->
|
||||
|
|
|
@ -6,6 +6,7 @@ SandboxedModule = require('sandboxed-module')
|
|||
assert = require('chai').assert
|
||||
path = require 'path'
|
||||
_ = require 'underscore'
|
||||
ObjectId = require("mongojs").ObjectId;
|
||||
modulePath = path.join __dirname, '../../../../app/js/Features/DocumentUpdater/DocumentUpdaterHandler'
|
||||
|
||||
describe 'DocumentUpdaterHandler', ->
|
||||
|
@ -20,8 +21,14 @@ describe 'DocumentUpdaterHandler', ->
|
|||
|
||||
@request = {}
|
||||
@projectEntityHandler = {}
|
||||
@settings =
|
||||
apis : documentupdater: url : "http://something.com"
|
||||
@settings =
|
||||
apis:
|
||||
documentupdater:
|
||||
url : "http://document_updater.example.com"
|
||||
project_history:
|
||||
url: "http://project_history.example.com"
|
||||
|
||||
@callback = sinon.stub()
|
||||
@handler = SandboxedModule.require modulePath, requires:
|
||||
'request': defaults:=> return @request
|
||||
'settings-sharelatex':@settings
|
||||
|
@ -29,14 +36,11 @@ describe 'DocumentUpdaterHandler', ->
|
|||
'../Project/ProjectEntityHandler':@projectEntityHandler
|
||||
"../../models/Project": Project: @Project={}
|
||||
'../../Features/Project/ProjectLocator':{}
|
||||
"metrics-sharelatex":
|
||||
"metrics-sharelatex":
|
||||
Timer:->
|
||||
done:->
|
||||
|
||||
describe 'flushProjectToMongo', ->
|
||||
beforeEach ->
|
||||
@callback = sinon.stub()
|
||||
|
||||
describe "successfully", ->
|
||||
beforeEach ->
|
||||
@request.post = sinon.stub().callsArgWith(1, null, {statusCode: 204}, "")
|
||||
|
@ -68,9 +72,6 @@ describe 'DocumentUpdaterHandler', ->
|
|||
.should.equal true
|
||||
|
||||
describe 'flushProjectToMongoAndDelete', ->
|
||||
beforeEach ->
|
||||
@callback = sinon.stub()
|
||||
|
||||
describe "successfully", ->
|
||||
beforeEach ->
|
||||
@request.del = sinon.stub().callsArgWith(1, null, {statusCode: 204}, "")
|
||||
|
@ -102,9 +103,6 @@ describe 'DocumentUpdaterHandler', ->
|
|||
.should.equal true
|
||||
|
||||
describe 'flushDocToMongo', ->
|
||||
beforeEach ->
|
||||
@callback = sinon.stub()
|
||||
|
||||
describe "successfully", ->
|
||||
beforeEach ->
|
||||
@request.post = sinon.stub().callsArgWith(1, null, {statusCode: 204}, "")
|
||||
|
@ -136,9 +134,6 @@ describe 'DocumentUpdaterHandler', ->
|
|||
.should.equal true
|
||||
|
||||
describe "deleteDoc", ->
|
||||
beforeEach ->
|
||||
@callback = sinon.stub()
|
||||
|
||||
describe "successfully", ->
|
||||
beforeEach ->
|
||||
@request.del = sinon.stub().callsArgWith(1, null, {statusCode: 204}, "")
|
||||
|
@ -171,7 +166,6 @@ describe 'DocumentUpdaterHandler', ->
|
|||
|
||||
describe "setDocument", ->
|
||||
beforeEach ->
|
||||
@callback = sinon.stub()
|
||||
@source = "dropbox"
|
||||
|
||||
describe "successfully", ->
|
||||
|
@ -213,9 +207,6 @@ describe 'DocumentUpdaterHandler', ->
|
|||
.should.equal true
|
||||
|
||||
describe "getDocument", ->
|
||||
beforeEach ->
|
||||
@callback = sinon.stub()
|
||||
|
||||
describe "successfully", ->
|
||||
beforeEach ->
|
||||
@body = JSON.stringify
|
||||
|
@ -254,7 +245,6 @@ describe 'DocumentUpdaterHandler', ->
|
|||
|
||||
describe "getProjectDocsIfMatch", ->
|
||||
beforeEach ->
|
||||
@callback = sinon.stub()
|
||||
@project_state_hash = "1234567890abcdef"
|
||||
|
||||
describe "successfully", ->
|
||||
|
@ -295,9 +285,6 @@ describe 'DocumentUpdaterHandler', ->
|
|||
|
||||
|
||||
describe "clearProjectState", ->
|
||||
beforeEach ->
|
||||
@callback = sinon.stub()
|
||||
|
||||
describe "successfully", ->
|
||||
beforeEach ->
|
||||
@request.post = sinon.stub().callsArgWith(1, null, {statusCode: 200})
|
||||
|
@ -332,7 +319,6 @@ describe 'DocumentUpdaterHandler', ->
|
|||
describe "acceptChanges", ->
|
||||
beforeEach ->
|
||||
@change_id = "mock-change-id-1"
|
||||
@callback = sinon.stub()
|
||||
|
||||
describe "successfully", ->
|
||||
beforeEach ->
|
||||
|
@ -370,7 +356,6 @@ describe 'DocumentUpdaterHandler', ->
|
|||
describe "deleteThread", ->
|
||||
beforeEach ->
|
||||
@thread_id = "mock-thread-id-1"
|
||||
@callback = sinon.stub()
|
||||
|
||||
describe "successfully", ->
|
||||
beforeEach ->
|
||||
|
@ -401,3 +386,54 @@ describe 'DocumentUpdaterHandler', ->
|
|||
@callback
|
||||
.calledWith(new Error("doc updater returned failure status code: 500"))
|
||||
.should.equal true
|
||||
|
||||
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 ->
|
||||
@settings.apis.project_history.enabled = false
|
||||
@request.post = sinon.stub()
|
||||
|
||||
@handler.updateProjectStructure @project_id, @user_id, @oldDocs, @newDocs, @oldFiles, @newFiles, @callback
|
||||
|
||||
it 'does not make a web request', ->
|
||||
@request.post.called.should.equal false
|
||||
|
||||
it 'calls the callback', ->
|
||||
@callback.called.should.equal true
|
||||
|
||||
describe "with project history enabled", ->
|
||||
beforeEach ->
|
||||
@settings.apis.project_history.enabled = true
|
||||
@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"
|
||||
]
|
||||
|
||||
url = "#{@settings.apis.documentupdater.url}/project/#{@project_id}"
|
||||
@request.post
|
||||
.calledWith(url: url, json: {docUpdates, fileUpdates: [], userId: @user_id})
|
||||
.should.equal true
|
||||
|
||||
it "should call the callback with no error", ->
|
||||
@callback.calledWith(null).should.equal true
|
||||
|
|
|
@ -489,55 +489,51 @@ describe "EditorController", ->
|
|||
|
||||
|
||||
describe "renameEntity", ->
|
||||
|
||||
beforeEach ->
|
||||
@err = "errro"
|
||||
@entity_id = "entity_id_here"
|
||||
@entityType = "doc"
|
||||
@newName = "bobsfile.tex"
|
||||
@ProjectEntityHandler.renameEntity = sinon.stub().callsArgWith(4, @err)
|
||||
@ProjectEntityHandler.renameEntity = sinon.stub().callsArg(5)
|
||||
@EditorRealTimeController.emitToRoom = sinon.stub()
|
||||
|
||||
it "should call the project handler", (done)->
|
||||
@EditorController.renameEntity @project_id, @entity_id, @entityType, @newName, =>
|
||||
@ProjectEntityHandler.renameEntity.calledWith(@project_id, @entity_id, @entityType, @newName).should.equal true
|
||||
@EditorController.renameEntity @project_id, @entity_id, @entityType, @newName, @user_id, =>
|
||||
@ProjectEntityHandler.renameEntity.calledWith(@project_id, @entity_id, @entityType, @newName, @user_id).should.equal true
|
||||
done()
|
||||
|
||||
|
||||
it "should emit the update to the room", (done)->
|
||||
@EditorController.renameEntity @project_id, @entity_id, @entityType, @newName, =>
|
||||
@EditorController.renameEntity @project_id, @entity_id, @entityType, @newName, @user_id, =>
|
||||
@EditorRealTimeController.emitToRoom.calledWith(@project_id, 'reciveEntityRename', @entity_id, @newName).should.equal true
|
||||
done()
|
||||
|
||||
describe "moveEntity", ->
|
||||
|
||||
beforeEach ->
|
||||
@err = "errro"
|
||||
@entity_id = "entity_id_here"
|
||||
@entityType = "doc"
|
||||
@folder_id = "313dasd21dasdsa"
|
||||
@ProjectEntityHandler.moveEntity = sinon.stub().callsArgWith(4, @err)
|
||||
@ProjectEntityHandler.moveEntity = sinon.stub().callsArg(5)
|
||||
@EditorRealTimeController.emitToRoom = sinon.stub()
|
||||
@LockManager.releaseLock.callsArgWith(1)
|
||||
@LockManager.getLock.callsArgWith(1)
|
||||
|
||||
it "should call the ProjectEntityHandler", (done)->
|
||||
@EditorController.moveEntity @project_id, @entity_id, @folder_id, @entityType, =>
|
||||
@ProjectEntityHandler.moveEntity.calledWith(@project_id, @entity_id, @folder_id, @entityType).should.equal true
|
||||
@EditorController.moveEntity @project_id, @entity_id, @folder_id, @entityType, @user_id, =>
|
||||
@ProjectEntityHandler.moveEntity.calledWith(@project_id, @entity_id, @folder_id, @entityType, @user_id).should.equal true
|
||||
done()
|
||||
|
||||
it "should take the lock", (done)->
|
||||
@EditorController.moveEntity @project_id, @entity_id, @folder_id, @entityType, =>
|
||||
@EditorController.moveEntity @project_id, @entity_id, @folder_id, @entityType, @user_id, =>
|
||||
@LockManager.getLock.calledWith(@project_id).should.equal true
|
||||
done()
|
||||
|
||||
it "should release the lock", (done)->
|
||||
@EditorController.moveEntity @project_id, @entity_id, @folder_id, @entityType, =>
|
||||
@EditorController.moveEntity @project_id, @entity_id, @folder_id, @entityType, @user_id, =>
|
||||
@LockManager.releaseLock.calledWith(@project_id).should.equal true
|
||||
done()
|
||||
|
||||
it "should emit the update to the room", (done)->
|
||||
@EditorController.moveEntity @project_id, @entity_id, @folder_id, @entityType, =>
|
||||
@EditorController.moveEntity @project_id, @entity_id, @folder_id, @entityType, @user_id, =>
|
||||
@EditorRealTimeController.emitToRoom.calledWith(@project_id, 'reciveEntityMove', @entity_id, @folder_id).should.equal true
|
||||
done()
|
||||
|
||||
|
|
|
@ -19,11 +19,14 @@ describe "EditorHttpController", ->
|
|||
"../Collaborators/CollaboratorsHandler": @CollaboratorsHandler = {}
|
||||
"../Collaborators/CollaboratorsInviteHandler": @CollaboratorsInviteHandler = {}
|
||||
"../TokenAccess/TokenAccessHandler": @TokenAccessHandler = {}
|
||||
"../Authentication/AuthenticationController": @AuthenticationController = {}
|
||||
|
||||
@project_id = "mock-project-id"
|
||||
@doc_id = "mock-doc-id"
|
||||
@user_id = "mock-user-id"
|
||||
@parent_folder_id = "mock-folder-id"
|
||||
@userId = 1234
|
||||
@AuthenticationController.getLoggedInUserId = sinon.stub().returns(@userId)
|
||||
@req = {}
|
||||
@res =
|
||||
send: sinon.stub()
|
||||
|
@ -264,12 +267,12 @@ describe "EditorHttpController", ->
|
|||
entity_type: @entity_type = "entity-type"
|
||||
@req.body =
|
||||
name: @name = "new-name"
|
||||
@EditorController.renameEntity = sinon.stub().callsArg(4)
|
||||
@EditorController.renameEntity = sinon.stub().callsArg(5)
|
||||
@EditorHttpController.renameEntity @req, @res
|
||||
|
||||
it "should call EditorController.renameEntity", ->
|
||||
@EditorController.renameEntity
|
||||
.calledWith(@project_id, @entity_id, @entity_type, @name)
|
||||
.calledWith(@project_id, @entity_id, @entity_type, @name, @userId)
|
||||
.should.equal true
|
||||
|
||||
it "should send back a success response", ->
|
||||
|
@ -290,7 +293,6 @@ describe "EditorHttpController", ->
|
|||
@res.sendStatus.calledWith(400).should.equal true
|
||||
|
||||
describe "rename entity with 0 length name", ->
|
||||
|
||||
beforeEach ->
|
||||
@req.params =
|
||||
Project_id: @project_id
|
||||
|
@ -304,7 +306,6 @@ describe "EditorHttpController", ->
|
|||
it "should send back a bad request status code", ->
|
||||
@res.sendStatus.calledWith(400).should.equal true
|
||||
|
||||
|
||||
describe "moveEntity", ->
|
||||
beforeEach ->
|
||||
@req.params =
|
||||
|
@ -313,12 +314,12 @@ describe "EditorHttpController", ->
|
|||
entity_type: @entity_type = "entity-type"
|
||||
@req.body =
|
||||
folder_id: @folder_id = "folder-id-123"
|
||||
@EditorController.moveEntity = sinon.stub().callsArg(4)
|
||||
@EditorController.moveEntity = sinon.stub().callsArg(5)
|
||||
@EditorHttpController.moveEntity @req, @res
|
||||
|
||||
it "should call EditorController.moveEntity", ->
|
||||
@EditorController.moveEntity
|
||||
.calledWith(@project_id, @entity_id, @folder_id, @entity_type)
|
||||
.calledWith(@project_id, @entity_id, @folder_id, @entity_type, @userId)
|
||||
.should.equal true
|
||||
|
||||
it "should send back a success response", ->
|
||||
|
|
|
@ -14,6 +14,7 @@ describe 'ProjectEntityHandler', ->
|
|||
doc_id = '4eecb1c1bffa66588e0000a2'
|
||||
folder_id = "4eecaffcbffa66588e000008"
|
||||
rootFolderId = "4eecaffcbffa66588e000007"
|
||||
userId = 1234
|
||||
|
||||
beforeEach ->
|
||||
@FileStoreHandler =
|
||||
|
@ -235,10 +236,18 @@ describe 'ProjectEntityHandler', ->
|
|||
@pathAfterMove = {
|
||||
fileSystem: "/somewhere/else.txt"
|
||||
}
|
||||
@ProjectEntityHandler._removeElementFromMongoArray = sinon.stub().callsArg(3)
|
||||
@ProjectEntityHandler._removeElementFromMongoArray = sinon.stub().callsArgWith(3, null, @project)
|
||||
@ProjectEntityHandler._putElement = sinon.stub().callsArgWith(4, null, path: @pathAfterMove)
|
||||
@ProjectGetter.getProject.callsArgWith(2, null, @project)
|
||||
@tpdsUpdateSender.moveEntity = sinon.stub().callsArg(1)
|
||||
@tpdsUpdateSender.moveEntity = sinon.stub()
|
||||
@documentUpdaterHandler.updateProjectStructure = sinon.stub().callsArg(6)
|
||||
@ProjectEntityHandler.getAllEntitiesFromProject = sinon.stub()
|
||||
@ProjectEntityHandler.getAllEntitiesFromProject
|
||||
.onFirstCall()
|
||||
.callsArgWith(1, null, @oldDocs = ['old-doc'], @oldFiles = ['old-file'])
|
||||
@ProjectEntityHandler.getAllEntitiesFromProject
|
||||
.onSecondCall()
|
||||
.callsArgWith(1, null, @newDocs = ['new-doc'], @newFiles = ['new-file'])
|
||||
|
||||
describe "moving a doc", ->
|
||||
beforeEach (done) ->
|
||||
|
@ -246,14 +255,26 @@ describe 'ProjectEntityHandler', ->
|
|||
@doc = {lines:["1234","312343d"], rev: "1234"}
|
||||
@path = {
|
||||
mongo:"folders[0]"
|
||||
fileSystem:"/somewhere.txt"
|
||||
fileSystem:"/old_folder/somewhere.txt"
|
||||
}
|
||||
@projectLocator.findElement = sinon.stub().callsArgWith(1, null, @doc, @path)
|
||||
@ProjectEntityHandler.moveEntity project_id, @docId, folder_id, "docs", done
|
||||
@destFolder = { name: "folder" }
|
||||
@destFolderPath = {
|
||||
mongo: "folders[0]"
|
||||
fileSystem: "/dest_folder"
|
||||
}
|
||||
@projectLocator.findElement = sinon.stub()
|
||||
@projectLocator.findElement.withArgs({project: @project, element_id: @docId, type: 'docs'})
|
||||
.callsArgWith(1, null, @doc, @path)
|
||||
@ProjectEntityHandler.moveEntity project_id, @docId, folder_id, "docs", userId, done
|
||||
|
||||
it 'should find the project then element', ->
|
||||
it 'should find the doc to move', ->
|
||||
@projectLocator.findElement.calledWith({element_id: @docId, type: "docs", project: @project }).should.equal true
|
||||
|
||||
it "should should send the update to the doc updater", ->
|
||||
@documentUpdaterHandler.updateProjectStructure
|
||||
.calledWith(project_id, userId, @oldDocs, @newDocs, @oldFiles, @newFiles)
|
||||
.should.equal true
|
||||
|
||||
it 'should remove the element from its current position', ->
|
||||
@ProjectEntityHandler._removeElementFromMongoArray
|
||||
.calledWith(@ProjectModel, project_id, @path.mongo ).should.equal true
|
||||
|
@ -278,28 +299,19 @@ describe 'ProjectEntityHandler', ->
|
|||
@move_to_folder_id = "folder-to-move-to"
|
||||
@folder = { name: "folder" }
|
||||
@folder_to_move_to = { name: "folder to move to" }
|
||||
@path = {
|
||||
mongo: "folders[0]"
|
||||
fileSystem: "/somewhere.txt"
|
||||
}
|
||||
@pathToMoveTo = {
|
||||
mongo: "folders[0]"
|
||||
fileSystem: "/somewhere.txt"
|
||||
}
|
||||
@projectLocator.findElement = (options, callback) =>
|
||||
if options.element_id == @folder_id
|
||||
callback(null, @folder, @path)
|
||||
else if options.element_id == @move_to_folder_id
|
||||
callback(null, @folder_to_move_to, @pathToMoveTo)
|
||||
else
|
||||
console.log "UNKNOWN ID", options
|
||||
sinon.spy @projectLocator, "findElement"
|
||||
@path = { mongo:"folders[0]" }
|
||||
@pathToMoveTo = { mongo: "folders[0]" }
|
||||
@projectLocator.findElement = sinon.stub()
|
||||
@projectLocator.findElement.withArgs({project: @project, element_id: @folder_id, type: 'folder'})
|
||||
.callsArgWith(1, null, @folder, @path)
|
||||
@projectLocator.findElement.withArgs({project: @project, element_id: @move_to_folder_id, type: 'folder'})
|
||||
.callsArgWith(1, null, @folder_to_move_to, @pathToMoveTo)
|
||||
|
||||
describe "when the destination folder is outside the moving folder", ->
|
||||
beforeEach (done) ->
|
||||
@path.fileSystem = "/one/directory"
|
||||
@pathToMoveTo.fileSystem = "/another/directory"
|
||||
@ProjectEntityHandler.moveEntity project_id, @folder_id, @move_to_folder_id, "folder", done
|
||||
@path.fileSystem = "/one/src_dir"
|
||||
@pathToMoveTo.fileSystem = "/two/dest_dir"
|
||||
@ProjectEntityHandler.moveEntity project_id, @folder_id, @move_to_folder_id, "folder", userId, done
|
||||
|
||||
it 'should find the project then element', ->
|
||||
@projectLocator.findElement
|
||||
|
@ -310,6 +322,11 @@ describe 'ProjectEntityHandler', ->
|
|||
})
|
||||
.should.equal true
|
||||
|
||||
it "should should send the update to the doc updater", ->
|
||||
@documentUpdaterHandler.updateProjectStructure
|
||||
.calledWith(project_id, userId, @oldDocs, @newDocs, @oldFiles, @newFiles)
|
||||
.should.equal true
|
||||
|
||||
it 'should remove the element from its current position', ->
|
||||
@ProjectEntityHandler._removeElementFromMongoArray
|
||||
.calledWith(
|
||||
|
@ -345,9 +362,9 @@ describe 'ProjectEntityHandler', ->
|
|||
@path.fileSystem = "/one/two"
|
||||
@pathToMoveTo.fileSystem = "/one/two/three"
|
||||
@callback = sinon.stub()
|
||||
@ProjectEntityHandler.moveEntity project_id, @folder_id, @move_to_folder_id, "folder", @callback
|
||||
@ProjectEntityHandler.moveEntity project_id, @folder_id, @move_to_folder_id, "folder", userId, @callback
|
||||
|
||||
it 'should find the folder we are moving to as well element', ->
|
||||
it 'should find the folder we are moving to element', ->
|
||||
@projectLocator.findElement
|
||||
.calledWith({
|
||||
element_id: @move_to_folder_id,
|
||||
|
@ -361,23 +378,29 @@ describe 'ProjectEntityHandler', ->
|
|||
.calledWith(new Error("destination folder is a child folder of me"))
|
||||
.should.equal true
|
||||
|
||||
describe 'removing element from mongo array', ->
|
||||
it 'should call update with log the path', (done)->
|
||||
mongoPath = "folders[0].folders[5]"
|
||||
id = "12344"
|
||||
firstUpdate = true
|
||||
model =
|
||||
update: (conditions, update, opts, callback)->
|
||||
if firstUpdate
|
||||
conditions._id.should.equal id
|
||||
update.$unset[mongoPath].should.equal 1
|
||||
firstUpdate = false
|
||||
callback()
|
||||
else
|
||||
conditions._id.should.equal id
|
||||
assert.deepEqual update, { '$pull': { 'folders[0]': null } }
|
||||
done()
|
||||
@ProjectEntityHandler._removeElementFromMongoArray model, id, mongoPath, ->
|
||||
describe '_removeElementFromMongoArray ', ->
|
||||
beforeEach ->
|
||||
@mongoPath = "folders[0].folders[5]"
|
||||
@id = "12344"
|
||||
@project = 'a project'
|
||||
@ProjectModel.update = sinon.stub().callsArg(3)
|
||||
@ProjectModel.findOneAndUpdate = sinon.stub().callsArgWith(3, null, @project)
|
||||
@ProjectEntityHandler._removeElementFromMongoArray @ProjectModel, @id, @mongoPath, @callback
|
||||
|
||||
it 'should unset', ->
|
||||
update = { '$unset': { } }
|
||||
update['$unset'][@mongoPath] = 1
|
||||
@ProjectModel.update
|
||||
.calledWith({ _id: @id }, update, {})
|
||||
.should.equal true
|
||||
|
||||
it 'should pull', ->
|
||||
@ProjectModel.findOneAndUpdate
|
||||
.calledWith({ _id: @id }, { '$pull': { 'folders[0]': null } }, {'new': true})
|
||||
.should.equal true
|
||||
|
||||
it 'should call the callback', ->
|
||||
@callback.calledWith(null, @project).should.equal true
|
||||
|
||||
describe 'getDoc', ->
|
||||
beforeEach ->
|
||||
|
@ -976,20 +999,36 @@ describe 'ProjectEntityHandler', ->
|
|||
@entityType = "doc"
|
||||
@newName = "new.tex"
|
||||
@path = mongo: "mongo.path", fileSystem: "/file/system/old.tex"
|
||||
@projectLocator.findElement = sinon.stub().callsArgWith(1, null, @entity = { _id: @entity_id, name:"old.tex", rev:4 }, @path)
|
||||
@ProjectModel.update = sinon.stub().callsArgWith(3)
|
||||
@tpdsUpdateSender.moveEntity = sinon.stub()
|
||||
|
||||
@ProjectGetter.getProject.callsArgWith(2, null, @project)
|
||||
@ProjectEntityHandler.getAllEntitiesFromProject = sinon.stub()
|
||||
@ProjectEntityHandler.getAllEntitiesFromProject
|
||||
.onFirstCall()
|
||||
.callsArgWith(1, null, @oldDocs = ['old-doc'], @oldFiles = ['old-file'])
|
||||
@ProjectEntityHandler.getAllEntitiesFromProject
|
||||
.onSecondCall()
|
||||
.callsArgWith(1, null, @newDocs = ['new-doc'], @newFiles = ['new-file'])
|
||||
|
||||
@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)
|
||||
|
||||
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)
|
||||
.should.equal true
|
||||
done()
|
||||
|
||||
it "should update the name in mongo", (done)->
|
||||
|
||||
@ProjectEntityHandler.renameEntity @project_id, @entity_id, @entityType, @newName, =>
|
||||
@ProjectModel.update.calledWith({_id : @project_id}, {"$set":{"mongo.path.name":@newName}}).should.equal true
|
||||
@ProjectEntityHandler.renameEntity project_id, @entity_id, @entityType, @newName, userId, =>
|
||||
@ProjectModel.findOneAndUpdate.calledWith({_id: project_id}, {"$set":{"mongo.path.name": @newName}}, {"new": true}).should.equal true
|
||||
done()
|
||||
|
||||
it "should send the update to the tpds", (done)->
|
||||
@ProjectEntityHandler.renameEntity @project_id, @entity_id, @entityType, @newName, =>
|
||||
@tpdsUpdateSender.moveEntity.calledWith({project_id:@project_id, startPath:@path.fileSystem, endPath:"/file/system/new.tex", project_name:@project.name, rev:4}).should.equal true
|
||||
@ProjectEntityHandler.renameEntity project_id, @entity_id, @entityType, @newName, userId, =>
|
||||
@tpdsUpdateSender.moveEntity.calledWith({project_id:project_id, startPath:@path.fileSystem, endPath:"/file/system/new.tex", project_name:@project.name, rev:4}).should.equal true
|
||||
done()
|
||||
|
||||
describe "_insertDeletedDocReference", ->
|
||||
|
@ -1085,27 +1124,28 @@ describe 'ProjectEntityHandler', ->
|
|||
@path = mongo: "mongo.path", fileSystem: "/file/system/old.tex"
|
||||
@ProjectGetter.getProject.callsArgWith(2, null, @project)
|
||||
@projectLocator.findElement.callsArgWith(1, null, @folder, @path)
|
||||
@ProjectUpdateStub.callsArgWith(3)
|
||||
|
||||
@ProjectModel.findOneAndUpdate = sinon.stub().callsArgWith(3, null, @project)
|
||||
|
||||
describe "updating the project", ->
|
||||
|
||||
|
||||
it "should use the correct mongo path", (done)->
|
||||
@ProjectEntityHandler._putElement @project, @folder._id, @doc, "docs", (err)=>
|
||||
@ProjectModel.update.args[0][0]._id.should.equal @project._id
|
||||
assert.deepEqual @ProjectModel.update.args[0][1].$push[@path.mongo+".docs"], @doc
|
||||
@ProjectModel.findOneAndUpdate.args[0][0]._id.should.equal @project._id
|
||||
assert.deepEqual @ProjectModel.findOneAndUpdate.args[0][1].$push[@path.mongo+".docs"], @doc
|
||||
done()
|
||||
|
||||
it "should return the project in the callback", (done)->
|
||||
@ProjectEntityHandler._putElement @project, @folder._id, @doc, "docs", (err, path, project)=>
|
||||
expect(project).to.equal @project
|
||||
done()
|
||||
|
||||
it "should add an s onto the type if not included", (done)->
|
||||
@ProjectEntityHandler._putElement @project, @folder._id, @doc, "doc", (err)=>
|
||||
assert.deepEqual @ProjectModel.update.args[0][1].$push[@path.mongo+".docs"], @doc
|
||||
assert.deepEqual @ProjectModel.findOneAndUpdate.args[0][1].$push[@path.mongo+".docs"], @doc
|
||||
done()
|
||||
|
||||
|
||||
it "should not call update if elemenet is null", (done)->
|
||||
it "should not call update if element is null", (done)->
|
||||
@ProjectEntityHandler._putElement @project, @folder._id, null, "doc", (err)=>
|
||||
@ProjectModel.update.called.should.equal false
|
||||
@ProjectModel.findOneAndUpdate.called.should.equal false
|
||||
done()
|
||||
|
||||
it "should default to root folder insert", (done)->
|
||||
|
@ -1117,11 +1157,9 @@ describe 'ProjectEntityHandler', ->
|
|||
doc =
|
||||
name:"something"
|
||||
@ProjectEntityHandler._putElement @project, @folder._id, doc, "doc", (err)=>
|
||||
@ProjectModel.update.called.should.equal false
|
||||
@ProjectModel.findOneAndUpdate.called.should.equal false
|
||||
done()
|
||||
|
||||
|
||||
|
||||
describe "_countElements", ->
|
||||
|
||||
beforeEach ->
|
||||
|
|
Loading…
Reference in a new issue