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)
|
return callback(error)
|
||||||
{owner, members} = ProjectEditorHandler.buildOwnerAndMembersViews(rawMembers)
|
{owner, members} = ProjectEditorHandler.buildOwnerAndMembersViews(rawMembers)
|
||||||
callback(null, members)
|
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', ->
|
it 'should not call ProjectEditorHandler.buildOwnerAndMembersViews', ->
|
||||||
@ProjectEditorHandler.buildOwnerAndMembersViews.callCount.should.equal 0
|
@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