Ver Fonte

Merge pull request #726 from sharelatex/ta-affiliate-on-create

Infer Affiliation for New Users
Timothée Alby há 8 anos atrás
pai
commit
4ffc097804

+ 6 - 1
services/web/app/coffee/Features/User/UserAffiliationsManager.coffee

@@ -12,7 +12,12 @@ module.exports = UserAffiliationsManager =
 		}, callback
 
 
-	addAffiliation: (userId, email, { university, department, role }, callback = (error) ->) ->
+	addAffiliation: (userId, email, affiliationOptions, callback) ->
+		unless callback? # affiliationOptions is optional
+			callback = affiliationOptions
+			affiliationOptions = {}
+
+		{ university, department, role } = affiliationOptions
 		makeAffiliationRequest {
 			method: 'POST'
 			path: "/api/v2/users/#{userId.toString()}/affiliations"

+ 12 - 0
services/web/app/coffee/Features/User/UserCreator.coffee

@@ -1,6 +1,7 @@
 User = require("../../models/User").User
 logger = require("logger-sharelatex")
 metrics = require('metrics-sharelatex')
+{ addAffiliation } = require("./UserAffiliationsManager")
 
 
 module.exports = UserCreator =
@@ -26,6 +27,17 @@ module.exports = UserCreator =
 		user.save (err)->
 			callback(err, user)
 
+			# call addaffiliation after the main callback so it runs in the
+			# background. There is no guaranty this will run so we must no rely on it
+			addAffiliation user._id, user.email, (error) ->
+				if error
+					logger.log { userId: user._id, email: user.email, error: error },
+						"couldn't add affiliation for user on create"
+				else
+					logger.log { userId: user._id, email: user.email },
+					"added affiliation for user on create"
+
+
 metrics.timeAsyncMethod(
 	UserCreator, 'createNewUser',
 	'mongo.UserCreator',

+ 18 - 13
services/web/app/coffee/Features/User/UserUpdater.coffee

@@ -59,7 +59,7 @@ module.exports = UserUpdater =
 
 			addAffiliation userId, newEmail, affiliationOptions, (error) =>
 				if error?
-					logger.err error: error, 'problem adding affiliation'
+					logger.err error: error, 'problem adding affiliation while adding email'
 					return callback(error)
 
 				update = $push: emails: email: newEmail, createdAt: new Date()
@@ -110,18 +110,23 @@ module.exports = UserUpdater =
 		email = EmailHelper.parseEmail(email)
 		return callback(new Error('invalid email')) if !email?
 		logger.log {userId, email}, 'confirming user email'
-		query =
-			_id: userId
-			'emails.email': email
-		update =
-			$set:
-				'emails.$.confirmedAt': new Date()
-		@updateUser query, update, (error, res) ->
-			return callback(error) if error?
-			logger.log {res, userId, email}, "tried to confirm email"
-			if res.n == 0
-				return callback(new Errors.NotFoundError('user id and email do no match'))
-			callback()
+		addAffiliation userId, email, (error) =>
+			if error?
+				logger.err error: error, 'problem adding affiliation while confirming email'
+				return callback(error)
+
+			query =
+				_id: userId
+				'emails.email': email
+			update =
+				$set:
+					'emails.$.confirmedAt': new Date()
+			@updateUser query, update, (error, res) ->
+				return callback(error) if error?
+				logger.log {res, userId, email}, "tried to confirm email"
+				if res.n == 0
+					return callback(new Errors.NotFoundError('user id and email do no match'))
+				callback()
 
 [
 	'updateUser'

+ 11 - 1
services/web/test/unit/coffee/User/UserCreatorTests.coffee

@@ -17,11 +17,12 @@ describe "UserCreator", ->
 
 		@UserGetter =
 			getUserByMainEmail: sinon.stub()
+		@addAffiliation = sinon.stub().yields()
 		@UserCreator = SandboxedModule.require modulePath, requires:
 			"../../models/User": User:@UserModel
-			"./UserGetter":@UserGetter
 			"logger-sharelatex":{log:->}
 			'metrics-sharelatex': {timeAsyncMethod: ()->}
+			"./UserAffiliationsManager": addAffiliation: @addAffiliation
 
 		@email = "bob.oswald@gmail.com"
 
@@ -78,3 +79,12 @@ describe "UserCreator", ->
 				user.emails[0].email.should.equal @email
 				user.emails[0].createdAt.should.be.a 'date'
 				done()
+
+		it "should add affiliation in background", (done)->
+			@UserCreator.createNewUser email: @email, (err, user) =>
+				# addaffiliation should not be called before the callback but only after
+				# a tick of the event loop
+				sinon.assert.notCalled(@addAffiliation)
+				process.nextTick () =>
+					sinon.assert.calledWith(@addAffiliation, user._id, user.email)
+					done()

+ 17 - 2
services/web/test/unit/coffee/User/UserUpdaterTests.coffee

@@ -19,7 +19,7 @@ describe "UserUpdater", ->
 			getUserByAnyEmail: sinon.stub()
 			ensureUniqueEmailAddress: sinon.stub()
 		@logger = err: sinon.stub(), log: ->
-		@addAffiliation = sinon.stub().callsArgWith(3, null)
+		@addAffiliation = sinon.stub().yields()
 		@removeAffiliation = sinon.stub().callsArgWith(2, null)
 		@UserUpdater = SandboxedModule.require modulePath, requires:
 			"logger-sharelatex": @logger
@@ -201,9 +201,10 @@ describe "UserUpdater", ->
 				done()
 
 	describe 'confirmEmail', ->
-		it 'should update the email record', (done)->
+		beforeEach ->
 			@UserUpdater.updateUser = sinon.stub().callsArgWith(2, null, n: 1)
 
+		it 'should update the email record', (done)->
 			@UserUpdater.confirmEmail @stubbedUser._id, @newEmail, (err)=>
 				should.not.exist(err)
 				@UserUpdater.updateUser.calledWith(
@@ -212,6 +213,13 @@ describe "UserUpdater", ->
 				).should.equal true
 				done()
 
+		it 'add affiliation', (done)->
+			@UserUpdater.confirmEmail @stubbedUser._id, @newEmail, (err)=>
+				should.not.exist(err)
+				@addAffiliation.calledOnce.should.equal true
+				sinon.assert.calledWith(@addAffiliation, @stubbedUser._id, @newEmail)
+				done()
+
 		it 'handle error', (done)->
 			@UserUpdater.updateUser = sinon.stub().callsArgWith(2, new Error('nope'))
 
@@ -230,3 +238,10 @@ describe "UserUpdater", ->
 			@UserUpdater.confirmEmail @stubbedUser._id, '@', (err)=>
 				should.exist(err)
 				done()
+
+		it 'handle affiliation error', (done)->
+			@addAffiliation.callsArgWith(2, new Error('nope'))
+			@UserUpdater.confirmEmail @stubbedUser._id, @newEmail, (err)=>
+				should.exist(err)
+				@UserUpdater.updateUser.called.should.equal false
+				done()