mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Merge pull request #41 from sharelatex/ja-transfer-projects
Add method to transfer projects from one user_id to another
This commit is contained in:
commit
f0079bb7a4
2 changed files with 152 additions and 0 deletions
|
@ -157,3 +157,55 @@ module.exports = CollaboratorsHandler =
|
|||
return callback(error)
|
||||
{owner, members} = ProjectEditorHandler.buildOwnerAndMembersViews(rawMembers)
|
||||
callback(null, members)
|
||||
|
||||
transferProjects: (from_user_id, to_user_id, callback=(err, projects) ->) ->
|
||||
MEMBER_KEYS = ['collaberator_refs', 'readOnly_refs']
|
||||
|
||||
# Find all the projects this user is part of so we can flush them to TPDS
|
||||
query =
|
||||
$or:
|
||||
[{ owner_ref: from_user_id }]
|
||||
.concat(
|
||||
MEMBER_KEYS.map (key) ->
|
||||
q = {}
|
||||
q[key] = from_user_id
|
||||
return q
|
||||
) # [{ collaberator_refs: from_user_id }, ...]
|
||||
Project.find query, { _id: 1 }, (error, projects = []) ->
|
||||
return callback(error) if error?
|
||||
|
||||
project_ids = projects.map (p) -> p._id
|
||||
logger.log {project_ids, from_user_id, to_user_id}, "transferring projects"
|
||||
|
||||
update_jobs = []
|
||||
update_jobs.push (cb) ->
|
||||
Project.update { owner_ref: from_user_id }, { $set: { owner_ref: to_user_id }}, { multi: true }, cb
|
||||
for key in MEMBER_KEYS
|
||||
do (key) ->
|
||||
update_jobs.push (cb) ->
|
||||
query = {}
|
||||
addNewUserUpdate = $addToSet: {}
|
||||
removeOldUserUpdate = $pull: {}
|
||||
query[key] = from_user_id
|
||||
removeOldUserUpdate.$pull[key] = from_user_id
|
||||
addNewUserUpdate.$addToSet[key] = to_user_id
|
||||
# Mongo won't let us pull and addToSet in the same query, so do it in
|
||||
# two. Note we need to add first, since the query is based on the old user.
|
||||
Project.update query, addNewUserUpdate, { multi: true }, (error) ->
|
||||
return cb(error) if error?
|
||||
Project.update query, removeOldUserUpdate, { multi: true }, cb
|
||||
|
||||
# Flush each project to TPDS to add files to new user's Dropbox
|
||||
ProjectEntityHandler = require("../Project/ProjectEntityHandler")
|
||||
flush_jobs = []
|
||||
for project_id in project_ids
|
||||
do (project_id) ->
|
||||
flush_jobs.push (cb) ->
|
||||
ProjectEntityHandler.flushProjectToThirdPartyDataStore project_id, cb
|
||||
|
||||
# Flush in background, no need to block on this
|
||||
async.series flush_jobs, (error) ->
|
||||
if error?
|
||||
logger.err {err: error, project_ids, from_user_id, to_user_id}, "error flushing tranferred projects to TPDS"
|
||||
|
||||
async.series update_jobs, callback
|
||||
|
|
|
@ -344,3 +344,103 @@ describe "CollaboratorsHandler", ->
|
|||
|
||||
it 'should not call ProjectEditorHandler.buildOwnerAndMembersViews', ->
|
||||
@ProjectEditorHandler.buildOwnerAndMembersViews.callCount.should.equal 0
|
||||
|
||||
describe 'transferProjects', ->
|
||||
beforeEach ->
|
||||
@from_user_id = "from-user-id"
|
||||
@to_user_id = "to-user-id"
|
||||
@projects = [{
|
||||
_id: "project-id-1"
|
||||
}, {
|
||||
_id: "project-id-2"
|
||||
}]
|
||||
@Project.find = sinon.stub().yields(null, @projects)
|
||||
@Project.update = sinon.stub().yields()
|
||||
@ProjectEntityHandler.flushProjectToThirdPartyDataStore = sinon.stub().yields()
|
||||
|
||||
describe "successfully", ->
|
||||
beforeEach ->
|
||||
@CollaboratorHandler.transferProjects @from_user_id, @to_user_id, @callback
|
||||
|
||||
it "should look up the affected projects", ->
|
||||
@Project.find
|
||||
.calledWith({
|
||||
$or : [
|
||||
{ owner_ref: @from_user_id }
|
||||
{ collaberator_refs: @from_user_id }
|
||||
{ readOnly_refs: @from_user_id }
|
||||
]
|
||||
})
|
||||
.should.equal true
|
||||
|
||||
it "should transfer owned projects", ->
|
||||
@Project.update
|
||||
.calledWith({
|
||||
owner_ref: @from_user_id
|
||||
}, {
|
||||
$set: { owner_ref: @to_user_id }
|
||||
}, {
|
||||
multi: true
|
||||
})
|
||||
.should.equal true
|
||||
|
||||
it "should transfer collaborator projects", ->
|
||||
@Project.update
|
||||
.calledWith({
|
||||
collaberator_refs: @from_user_id
|
||||
}, {
|
||||
$addToSet: { collaberator_refs: @to_user_id }
|
||||
}, {
|
||||
multi: true
|
||||
})
|
||||
.should.equal true
|
||||
@Project.update
|
||||
.calledWith({
|
||||
collaberator_refs: @from_user_id
|
||||
}, {
|
||||
$pull: { collaberator_refs: @from_user_id }
|
||||
}, {
|
||||
multi: true
|
||||
})
|
||||
.should.equal true
|
||||
|
||||
it "should transfer read only collaborator projects", ->
|
||||
@Project.update
|
||||
.calledWith({
|
||||
readOnly_refs: @from_user_id
|
||||
}, {
|
||||
$addToSet: { readOnly_refs: @to_user_id }
|
||||
}, {
|
||||
multi: true
|
||||
})
|
||||
.should.equal true
|
||||
@Project.update
|
||||
.calledWith({
|
||||
readOnly_refs: @from_user_id
|
||||
}, {
|
||||
$pull: { readOnly_refs: @from_user_id }
|
||||
}, {
|
||||
multi: true
|
||||
})
|
||||
.should.equal true
|
||||
|
||||
it "should flush each project to the TPDS", ->
|
||||
for project in @projects
|
||||
@ProjectEntityHandler.flushProjectToThirdPartyDataStore
|
||||
.calledWith(project._id)
|
||||
.should.equal true
|
||||
|
||||
it "should call the callback", ->
|
||||
@callback.called.should.equal true
|
||||
|
||||
describe "when flushing to TPDS fails", ->
|
||||
beforeEach ->
|
||||
@ProjectEntityHandler.flushProjectToThirdPartyDataStore = sinon.stub().yields(new Error('oops'))
|
||||
@CollaboratorHandler.transferProjects @from_user_id, @to_user_id, @callback
|
||||
|
||||
it "should log an error", ->
|
||||
@logger.err.called.should.equal true
|
||||
|
||||
it "should not return an error since it happens in the background", ->
|
||||
@callback.called.should.equal true
|
||||
@callback.calledWith(new Error('oops')).should.equal false
|
Loading…
Reference in a new issue