Merge pull request #1006 from sharelatex/hb-v2-affiliations-callback

Add affiliations on university domain confirmation
This commit is contained in:
Hugh O'Brien 2018-10-16 11:17:01 +01:00 committed by GitHub
commit 876663f94b
8 changed files with 116 additions and 9 deletions

View file

@ -0,0 +1,24 @@
logger = require("logger-sharelatex")
UserGetter = require("../User/UserGetter")
{ addAffiliation } = require("../Institutions/InstitutionsAPI")
async = require('async')
module.exports = InstitutionsController =
confirmDomain: (req, res, next) ->
hostname = req.body.hostname
reversedHostname = hostname.trim().split('').reverse().join('')
UserGetter.getUsersByHostname hostname, {_id:1, emails:1}, (error, users) ->
if error?
logger.err error: error, 'problem fetching users by hostname'
return next(error)
async.map users, ((user) ->
matchingEmails = user.emails.filter (email) -> email.reversedHostname == reversedHostname
for email in matchingEmails
addAffiliation user._id, email.email, {confirmedAt: email.confirmedAt}, (error) =>
if error?
logger.err error: error, 'problem adding affiliation while confirming hostname'
return next(error)
), (error) ->
if error?
return next(error)
res.sendStatus 200

View file

@ -58,6 +58,11 @@ module.exports = UserGetter =
# well
@getUserByMainEmail email, projection, callback
getUsersByHostname: (hostname, projection, callback = (error, users) ->) ->
reversedHostname = hostname.trim().split('').reverse().join('')
query = emails: { $exists: true }, 'emails.reversedHostname': reversedHostname
db.users.find query, projection, callback
getUsers: (user_ids, projection, callback = (error, users) ->) ->
try
user_ids = user_ids.map (u) -> ObjectId(u.toString())

View file

@ -66,7 +66,8 @@ module.exports = UserUpdater =
logger.err error: error, 'problem adding affiliation while adding email'
return callback(error)
update = $push: emails: email: newEmail, createdAt: new Date()
reversedHostname = newEmail.split('@')[1].split('').reverse().join('')
update = $push: emails: email: newEmail, createdAt: new Date(), reversedHostname: reversedHostname
@updateUser userId, update, (error) ->
if error?
logger.err error: error, 'problem updating users emails'

View file

@ -10,6 +10,7 @@ UserSchema = new Schema
email : {type : String, default : ''}
emails: [{
email: { type : String, default : '' },
reversedHostname: { type : String, default : '' },
createdAt: { type : Date, default: () -> new Date() },
confirmedAt: { type: Date }
}],

View file

@ -50,6 +50,7 @@ TokenAccessController = require('./Features/TokenAccess/TokenAccessController')
Features = require('./infrastructure/Features')
LinkedFilesRouter = require './Features/LinkedFiles/LinkedFilesRouter'
TemplatesRouter = require './Features/Templates/TemplatesRouter'
InstitutionsController = require './Features/Institutions/InstitutionsController'
UserMembershipRouter = require './Features/UserMembership/UserMembershipRouter'
logger = require("logger-sharelatex")
@ -332,6 +333,7 @@ module.exports = class Router
),
AuthenticationController.httpAuth,
CompileController.getFileFromClsiWithoutUser
publicApiRouter.post '/api/institutions/confirm_university_domain', AuthenticationController.httpAuth, InstitutionsController.confirmDomain
webRouter.get '/teams', (req, res, next) ->
# Match v1 behaviour - if the user is signed in, show their teams list

View file

@ -0,0 +1,57 @@
should = require('chai').should()
SandboxedModule = require('sandboxed-module')
assert = require('assert')
path = require('path')
sinon = require('sinon')
modulePath = path.join __dirname, "../../../../app/js/Features/Institutions/InstitutionsController"
expect = require("chai").expect
describe "InstitutionsController", ->
beforeEach ->
@logger = err: sinon.stub(), log: ->
@host = "mit.edu".split('').reverse().join('')
@stubbedUser1 =
_id: "3131231"
name:"bob"
email:"hello@world.com"
emails: [
{"email":"stubb1@mit.edu","reversedHostname":@host},
{"email":"test@test.com","reversedHostname":"test.com"},
{"email":"another@mit.edu","reversedHostname":@host}
]
@stubbedUser2 =
_id: "3131232"
name:"test"
email:"hello2@world.com"
emails: [
{"email":"subb2@mit.edu","reversedHostname":@host}
]
@getUsersByHostname = sinon.stub().callsArgWith(2, null, [ @stubbedUser1, @stubbedUser2 ])
@addAffiliation = sinon.stub().callsArgWith(3, null)
@InstitutionsController = SandboxedModule.require modulePath, requires:
'logger-sharelatex': @logger
'../User/UserGetter':
getUsersByHostname: @getUsersByHostname
'../Institutions/InstitutionsAPI':
addAffiliation: @addAffiliation
@req =
body:{}
@res =
send: sinon.stub()
json: sinon.stub()
@next = sinon.stub()
describe 'confirmDomain', ->
it 'should add affiliations for matching users', (done)->
@req.body.hostname = "mit.edu"
@res.sendStatus = (code) =>
@getUsersByHostname.calledOnce.should.equal true
@addAffiliation.calledThrice.should.equal true
@addAffiliation.calledWith(@stubbedUser1._id, @stubbedUser1.emails[0].email).should.equal true
@addAffiliation.calledWith(@stubbedUser1._id, @stubbedUser1.emails[2].email).should.equal true
done()
@InstitutionsController.confirmDomain @req, @res, @next

View file

@ -14,12 +14,15 @@ describe "UserGetter", ->
_id: '12390i'
email: 'email2@foo.bar'
emails: [
{ email: 'email1@foo.bar' }
{ email: 'email2@foo.bar' }
{ email: 'email1@foo.bar', reversedHostname: 'rab.oof' }
{ email: 'email2@foo.bar', reversedHostname: 'rab.oof' }
]
@findOne = sinon.stub().callsArgWith(2, null, @fakeUser)
@find = sinon.stub().callsArgWith(2, null, [ @fakeUser ])
@Mongo =
db: users: findOne: @findOne
db: users:
findOne: @findOne
find: @find
ObjectId: (id) -> return id
settings = apis: { v1: { url: 'v1.url', user: '', pass: '' } }
@getUserAffiliations = sinon.stub().callsArgWith(1, null, [])
@ -66,8 +69,8 @@ describe "UserGetter", ->
@UserGetter.getUser = sinon.stub().callsArgWith(2, null, @fakeUser)
@UserGetter.getUserFullEmails @fakeUser._id, (error, fullEmails) =>
assert.deepEqual fullEmails, [
{ email: 'email1@foo.bar', default: false }
{ email: 'email2@foo.bar', default: true }
{ email: 'email1@foo.bar', reversedHostname: 'rab.oof', default: false }
{ email: 'email2@foo.bar', reversedHostname: 'rab.oof', default: true }
]
done()
@ -86,7 +89,8 @@ describe "UserGetter", ->
@UserGetter.getUserFullEmails @fakeUser._id, (error, fullEmails) =>
assert.deepEqual fullEmails, [
{
email: 'email1@foo.bar'
email: 'email1@foo.bar',
reversedHostname: 'rab.oof'
default: false
affiliation:
institution: affiliationsData[0].institution
@ -94,7 +98,7 @@ describe "UserGetter", ->
department: affiliationsData[0].department
role: affiliationsData[0].role
}
{ email: 'email2@foo.bar', default: true }
{ email: 'email2@foo.bar', reversedHostname: 'rab.oof', default: true }
]
done()
@ -161,6 +165,18 @@ describe "UserGetter", ->
@findOne.calledWith(email: email, projection).should.equal true
done()
describe "getUsersByHostname", ->
it "should find user by hostname", (done)->
hostname = "bar.foo"
expectedQuery =
emails: {$exists: true },
'emails.reversedHostname': hostname.split('').reverse().join('')
projection = emails: 1
@UserGetter.getUsersByHostname hostname, projection, (error, users) =>
@find.calledOnce.should.equal true
@find.calledWith(expectedQuery, projection).should.equal true
done()
describe 'ensureUniqueEmailAddress', ->
beforeEach ->
@UserGetter.getUserByAnyEmail = sinon.stub()

View file

@ -90,9 +90,10 @@ describe "UserUpdater", ->
@UserUpdater.addEmailAddress @stubbedUser._id, @newEmail, (err)=>
@UserGetter.ensureUniqueEmailAddress.called.should.equal true
should.not.exist(err)
reversedHostname = @newEmail.split('@')[1].split('').reverse().join('')
@UserUpdater.updateUser.calledWith(
@stubbedUser._id,
$push: { emails: { email: @newEmail, createdAt: sinon.match.date } }
$push: { emails: { email: @newEmail, createdAt: sinon.match.date, reversedHostname: reversedHostname } }
).should.equal true
done()