Merge pull request #3492 from overleaf/jel-calc-notification-period

Flag emails in affiliation notification period

GitOrigin-RevId: d2d4868ba3a49e69b85a3bdca16d12276ac5c006
This commit is contained in:
Jessica Lawshe
2021-01-20 03:04:37 +00:00
committed by Copybot
parent 37f083809a
commit b44aed56dd
6 changed files with 804 additions and 41 deletions
@@ -2,6 +2,7 @@ const { ObjectId } = require('mongodb')
const should = require('chai').should()
const SandboxedModule = require('sandboxed-module')
const assert = require('assert')
const moment = require('moment')
const path = require('path')
const sinon = require('sinon')
const modulePath = path.join(
@@ -41,7 +42,6 @@ describe('UserGetter', function() {
},
ObjectId
}
const settings = { apis: { v1: { url: 'v1.url', user: '', pass: '' } } }
this.getUserAffiliations = sinon.stub().resolves([])
this.UserGetter = SandboxedModule.require(modulePath, {
@@ -57,7 +57,9 @@ describe('UserGetter', function() {
'@overleaf/metrics': {
timeAsyncMethod: sinon.stub()
},
'settings-sharelatex': settings,
'settings-sharelatex': (this.settings = {
reconfirmNotificationDays: 14
}),
'../Institutions/InstitutionsAPI': {
promises: {
getUserAffiliations: this.getUserAffiliations
@@ -192,7 +194,8 @@ describe('UserGetter', function() {
inferred: affiliationsData[0].inferred,
department: affiliationsData[0].department,
role: affiliationsData[0].role,
licence: affiliationsData[0].licence
licence: affiliationsData[0].licence,
inReconfirmNotificationPeriod: false
}
},
{
@@ -262,6 +265,528 @@ describe('UserGetter', function() {
}
)
})
describe('affiliation reconfirmation', function() {
const institutionNonSSO = {
id: 1,
name: 'University Name',
commonsAccount: true,
isUniversity: true,
confirmed: true,
ssoBeta: false,
ssoEnabled: false,
maxConfirmationMonths: 12
}
const institutionSSO = {
id: 2,
name: 'SSO University Name',
isUniversity: true,
confirmed: true,
ssoBeta: false,
ssoEnabled: true,
maxConfirmationMonths: 12
}
describe('non-SSO institutions', function() {
const email1 = 'leonard@example-affiliation.com'
const email2 = 'mccoy@example-affiliation.com'
const affiliationsData = [
{
email: email1,
role: 'Prof',
department: 'Medicine',
inferred: false,
licence: 'pro_plus',
institution: institutionNonSSO
},
{
email: email2,
role: 'Prof',
department: 'Medicine',
inferred: false,
licence: 'pro_plus',
institution: institutionNonSSO
}
]
it('should flag inReconfirmNotificationPeriod for all affiliations in period', function(done) {
const user = {
_id: '12390i',
email: email1,
emails: [
{
email: email1,
reversedHostname: 'moc.noitailiffa-elpmaxe',
confirmedAt: moment()
.subtract(
institutionNonSSO.maxConfirmationMonths + 2,
'months'
)
.toDate(),
default: true
},
{
email: email2,
reversedHostname: 'moc.noitailiffa-elpmaxe',
confirmedAt: moment()
.subtract(
institutionNonSSO.maxConfirmationMonths + 1,
'months'
)
.toDate()
}
]
}
this.getUserAffiliations.resolves(affiliationsData)
this.UserGetter.promises.getUser = sinon.stub().resolves(user)
this.UserGetter.getUserFullEmails(
this.fakeUser._id,
(error, fullEmails) => {
expect(error).to.not.exist
expect(
fullEmails[0].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
expect(
fullEmails[1].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
done()
}
)
})
it('should not flag affiliations outside of notification period', function(done) {
const aboutToBeWithinPeriod = moment()
.subtract(institutionNonSSO.maxConfirmationMonths, 'months')
.add(15, 'days')
.toDate() // expires in 15 days
const user = {
_id: '12390i',
email: email1,
emails: [
{
email: email1,
reversedHostname: 'moc.noitailiffa-elpmaxe',
confirmedAt: new Date(),
default: true
},
{
email: email2,
reversedHostname: 'moc.noitailiffa-elpmaxe',
confirmedAt: aboutToBeWithinPeriod
}
]
}
this.getUserAffiliations.resolves(affiliationsData)
this.UserGetter.promises.getUser = sinon.stub().resolves(user)
this.UserGetter.getUserFullEmails(
this.fakeUser._id,
(error, fullEmails) => {
expect(error).to.not.exist
expect(
fullEmails[0].affiliation.inReconfirmNotificationPeriod
).to.equal(false)
expect(
fullEmails[1].affiliation.inReconfirmNotificationPeriod
).to.equal(false)
done()
}
)
})
})
describe('SSO institutions', function() {
it('should flag only linked email, if in notification period', function(done) {
const email1 = 'email1@sso.bar'
const email2 = 'email2@sso.bar'
const email3 = 'email3@sso.bar'
const affiliationsData = [
{
email: email1,
role: 'Prof',
department: 'Maths',
inferred: false,
licence: 'pro_plus',
institution: institutionSSO
},
{
email: email2,
role: 'Prof',
department: 'Maths',
inferred: false,
licence: 'pro_plus',
institution: institutionSSO
},
{
email: email3,
role: 'Prof',
department: 'Maths',
inferred: false,
licence: 'pro_plus',
institution: institutionSSO
}
]
const user = {
_id: '12390i',
email: email1,
emails: [
{
email: email1,
reversedHostname: 'rab.oss',
confirmedAt: new Date('2019-09-24'),
reconfirmedAt: new Date('2019-09-24'),
default: true
},
{
email: email2,
reversedHostname: 'rab.oss',
confirmedAt: new Date('2019-09-24'),
reconfirmedAt: new Date('2019-09-24'),
samlProviderId: institutionSSO.id
},
{
email: email3,
reversedHostname: 'rab.oss',
confirmedAt: new Date('2019-09-24'),
reconfirmedAt: new Date('2019-09-24')
}
],
samlIdentifiers: [
{
providerId: institutionSSO.id,
externalUserId: 'abc123'
}
]
}
this.getUserAffiliations.resolves(affiliationsData)
this.UserGetter.promises.getUser = sinon.stub().resolves(user)
this.UserGetter.getUserFullEmails(
this.fakeUser._id,
(error, fullEmails) => {
expect(error).to.not.exist
expect(
fullEmails[0].affiliation.inReconfirmNotificationPeriod
).to.equal(false)
expect(
fullEmails[1].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
expect(
fullEmails[2].affiliation.inReconfirmNotificationPeriod
).to.equal(false)
done()
}
)
})
})
describe('multiple institution affiliations', function() {
it('should flag each institution', function(done) {
const email1 = 'email1@sso.bar'
const email2 = 'email2@sso.bar'
const email3 = 'email3@foo.bar'
const email4 = 'email4@foo.bar'
const affiliationsData = [
{
email: email1,
role: 'Prof',
department: 'Maths',
inferred: false,
licence: 'pro_plus',
institution: institutionSSO
},
{
email: email2,
role: 'Prof',
department: 'Maths',
inferred: false,
licence: 'pro_plus',
institution: institutionSSO
},
{
email: email3,
role: 'Prof',
department: 'Maths',
inferred: false,
licence: 'pro_plus',
institution: institutionNonSSO
},
{
email: email4,
role: 'Prof',
department: 'Maths',
inferred: false,
licence: 'pro_plus',
institution: institutionNonSSO
}
]
const user = {
_id: '12390i',
email: email1,
emails: [
{
email: email1,
reversedHostname: 'rab.oss',
confirmedAt: '2019-09-24T20:25:08.503Z',
default: true
},
{
email: email2,
reversedHostname: 'rab.oss',
confirmedAt: new Date('2019-09-24T20:25:08.503Z'),
samlProviderId: institutionSSO.id
},
{
email: email3,
reversedHostname: 'rab.oof',
confirmedAt: new Date('2019-10-24T20:25:08.503Z')
},
{
email: email4,
reversedHostname: 'rab.oof',
confirmedAt: new Date('2019-09-24T20:25:08.503Z')
}
],
samlIdentifiers: [
{
providerId: institutionSSO.id,
externalUserId: 'abc123'
}
]
}
this.getUserAffiliations.resolves(affiliationsData)
this.UserGetter.promises.getUser = sinon.stub().resolves(user)
this.UserGetter.getUserFullEmails(
this.fakeUser._id,
(error, fullEmails) => {
expect(error).to.not.exist
expect(
fullEmails[0].affiliation.inReconfirmNotificationPeriod
).to.to.equal(false)
expect(
fullEmails[1].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
expect(
fullEmails[2].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
expect(
fullEmails[3].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
done()
}
)
})
})
describe('reconfirmedAt', function() {
it('only use confirmedAt when no reconfirmedAt', function(done) {
const email1 = 'email1@foo.bar'
const email2 = 'email2@foo.bar'
const email3 = 'email3@foo.bar'
const affiliationsData = [
{
email: email1,
role: 'Prof',
department: 'Maths',
inferred: false,
licence: 'pro_plus',
institution: institutionNonSSO
},
{
email: email2,
role: 'Prof',
department: 'Maths',
inferred: false,
licence: 'pro_plus',
institution: institutionNonSSO
},
{
email: email3,
role: 'Prof',
department: 'Maths',
inferred: false,
licence: 'pro_plus',
institution: institutionNonSSO
}
]
const user = {
_id: '12390i',
email: email1,
emails: [
{
email: email1,
reversedHostname: 'rab.oof',
confirmedAt: moment().subtract(
institutionSSO.maxConfirmationMonths * 2,
'months'
),
reconfirmedAt: moment().subtract(
institutionSSO.maxConfirmationMonths * 3,
'months'
),
default: true
},
{
email: email2,
reversedHostname: 'rab.oof',
confirmedAt: moment().subtract(
institutionSSO.maxConfirmationMonths * 3,
'months'
),
reconfirmedAt: moment().subtract(
institutionSSO.maxConfirmationMonths * 2,
'months'
)
},
{
email: email3,
reversedHostname: 'rab.oof',
confirmedAt: moment().subtract(
institutionSSO.maxConfirmationMonths * 4,
'months'
),
reconfirmedAt: moment().subtract(
institutionSSO.maxConfirmationMonths * 4,
'months'
)
}
]
}
this.getUserAffiliations.resolves(affiliationsData)
this.UserGetter.promises.getUser = sinon.stub().resolves(user)
this.UserGetter.getUserFullEmails(
this.fakeUser._id,
(error, fullEmails) => {
expect(error).to.not.exist
expect(
fullEmails[0].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
expect(
fullEmails[1].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
expect(
fullEmails[2].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
done()
}
)
})
})
describe('before reconfirmation period expires and within reconfirmation notification period', function() {
const email = 'leonard@example-affiliation.com'
it('should flag the email', function(done) {
const confirmedAt = moment()
.subtract(institutionNonSSO.maxConfirmationMonths, 'months')
.subtract(14, 'days')
.toDate() // expires in 14 days
const affiliationsData = [
{
email,
role: 'Prof',
department: 'Medicine',
inferred: false,
licence: 'pro_plus',
institution: institutionNonSSO
}
]
const user = {
_id: '12390i',
email,
emails: [
{
email,
confirmedAt,
default: true
}
]
}
this.getUserAffiliations.resolves(affiliationsData)
this.UserGetter.promises.getUser = sinon.stub().resolves(user)
this.UserGetter.getUserFullEmails(
this.fakeUser._id,
(error, fullEmails) => {
expect(error).to.not.exist
expect(
fullEmails[0].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
done()
}
)
})
})
describe('when no Settings.reconfirmNotificationDays', function() {
it('should always return inReconfirmNotificationPeriod:false', function(done) {
const email1 = 'email1@sso.bar'
const email2 = 'email2@foo.bar'
const email3 = 'email3@foo.bar'
const confirmedAtAboutToExpire = moment()
.subtract(institutionNonSSO.maxConfirmationMonths, 'months')
.subtract(14, 'days')
.toDate() // expires in 14 days
const affiliationsData = [
{
email: email1,
institution: institutionSSO
},
{
email: email2,
institution: institutionNonSSO
},
{
email: email3,
institution: institutionNonSSO
}
]
const user = {
_id: '12390i',
email: email1,
emails: [
{
email: email1,
confirmedAt: confirmedAtAboutToExpire,
default: true,
samlProviderId: institutionSSO.id
},
{
email: email2,
confirmedAt: new Date('2019-09-24T20:25:08.503Z')
},
{
email: email3,
confirmedAt: new Date('2019-10-24T20:25:08.503Z')
}
],
samlIdentifiers: [
{
providerId: institutionSSO.id,
externalUserId: 'abc123'
}
]
}
this.settings.reconfirmNotificationDays = undefined
this.getUserAffiliations.resolves(affiliationsData)
this.UserGetter.promises.getUser = sinon.stub().resolves(user)
this.UserGetter.getUserFullEmails(
this.fakeUser._id,
(error, fullEmails) => {
expect(error).to.not.exist
expect(
fullEmails[0].affiliation.inReconfirmNotificationPeriod
).to.to.equal(false)
expect(
fullEmails[1].affiliation.inReconfirmNotificationPeriod
).to.equal(false)
expect(
fullEmails[2].affiliation.inReconfirmNotificationPeriod
).to.equal(false)
done()
}
)
})
})
})
})
describe('getUserbyMainEmail', function() {