Merge pull request #3609 from overleaf/jel-admin-user-affiliations

Add confirmation/reconfirmation to admin user affiliation tab

GitOrigin-RevId: d1e065c5e4d6d97814327742db2c4b131d4f0195
This commit is contained in:
Jessica Lawshe 2021-02-02 08:26:31 -06:00 committed by Copybot
parent 2dd860c431
commit ac99738495
7 changed files with 68 additions and 14 deletions

View file

@ -13,14 +13,15 @@ const Errors = require('../Errors/Errors')
const Features = require('../../infrastructure/Features')
const { normalizeQuery, normalizeMultiQuery } = require('../Helpers/Mongo')
function _emailInReconfirmNotificationPeriod(emailData, institutionData) {
function _lastDayToReconfirm(emailData, institutionData) {
const globalReconfirmPeriod = settings.reconfirmNotificationDays
if (!globalReconfirmPeriod) return false
if (!globalReconfirmPeriod) return undefined
// only show notification for institutions with reconfirmation enabled
if (!institutionData || !institutionData.maxConfirmationMonths) return false
if (!institutionData || !institutionData.maxConfirmationMonths)
return undefined
if (!emailData.confirmedAt) return false
if (!emailData.confirmedAt) return undefined
if (institutionData.ssoEnabled && !emailData.samlProviderId) {
// For SSO, only show notification for linked email
@ -30,10 +31,21 @@ function _emailInReconfirmNotificationPeriod(emailData, institutionData) {
// reconfirmedAt will not always be set, use confirmedAt as fallback
const lastConfirmed = emailData.reconfirmedAt || emailData.confirmedAt
const lastDayToReconfirm = moment(lastConfirmed).add(
institutionData.maxConfirmationMonths,
'months'
)
return moment(lastConfirmed)
.add(institutionData.maxConfirmationMonths, 'months')
.toDate()
}
function _pastReconfirmDate(lastDayToReconfirm) {
if (!lastDayToReconfirm) return false
return moment(lastDayToReconfirm).isBefore()
}
function _emailInReconfirmNotificationPeriod(lastDayToReconfirm) {
const globalReconfirmPeriod = settings.reconfirmNotificationDays
if (!globalReconfirmPeriod || !lastDayToReconfirm) return false
const notificationStarts = moment(lastDayToReconfirm).subtract(
globalReconfirmPeriod,
'days'
@ -202,14 +214,17 @@ var decorateFullEmails = (
licence,
portal
} = affiliation
const lastDayToReconfirm = _lastDayToReconfirm(emailData, institution)
const pastReconfirmDate = _pastReconfirmDate(lastDayToReconfirm)
const inReconfirmNotificationPeriod = _emailInReconfirmNotificationPeriod(
emailData,
institution
lastDayToReconfirm
)
emailData.affiliation = {
institution,
inferred,
inReconfirmNotificationPeriod,
lastDayToReconfirm,
pastReconfirmDate,
role,
department,
licence,

View file

@ -31,6 +31,22 @@ App.filter(
}
)
App.filter(
'utcDate',
() =>
function(date, format) {
if (!date) return 'N/A'
if (format == null) {
format = 'D MMM YYYY, HH:mm:ss'
}
return (
moment(date)
.utc()
.format(format) + ' UTC'
)
}
)
App.filter('relativeDate', () => date => moment(date).calendar())
App.filter('fromNowDate', () => date => moment(date).fromNow())

View file

@ -389,3 +389,7 @@ address {
font-style: normal;
line-height: @line-height-base;
}
.orange-text {
color: @orange-dark;
}

View file

@ -33,6 +33,7 @@
@red: #a93529;
@yellow: #a1a729;
@orange: #f89406;
@orange-dark: #9e5e04;
@pink: #c3325f;
@purple: #7a43b6;

View file

@ -521,6 +521,8 @@ describe('Subscriptions', function() {
name: 'Stanford',
confirmed: true
},
lastDayToReconfirm: undefined,
pastReconfirmDate: false,
portal: undefined
}
])

View file

@ -998,6 +998,14 @@ describe('UserEmails', function() {
describe('notification period', function() {
let defaultEmail, userHelper, email1, email2, email3
const maxConfirmationMonths = 12
const lastDayToReconfirm = moment()
.subtract(maxConfirmationMonths, 'months')
.toDate()
const oneDayBeforeLastDayToReconfirm = moment(lastDayToReconfirm)
.add(1, 'day')
.toDate()
const daysToBackdate = moment().diff(oneDayBeforeLastDayToReconfirm, 'day')
const daysToBackdateForAfterDate = daysToBackdate + 1
beforeEach(async function() {
if (!Features.hasFeature('affiliations')) {
@ -1026,14 +1034,17 @@ describe('UserEmails', function() {
beforeEach(async function() {
// create a user with 3 affiliations at the institution.
// all are within in the notification period
const backdatedDays = maxConfirmationMonths * 2 * 30
const userId = userHelper.user._id
await userHelper.addEmailAndConfirm(userId, email1)
await userHelper.addEmailAndConfirm(userId, email2)
await userHelper.addEmailAndConfirm(userId, email3)
await userHelper.backdateConfirmation(userId, email1, backdatedDays)
await userHelper.backdateConfirmation(userId, email2, backdatedDays)
await userHelper.backdateConfirmation(userId, email3, backdatedDays)
await userHelper.backdateConfirmation(userId, email1, daysToBackdate)
await userHelper.backdateConfirmation(userId, email2, daysToBackdate)
await userHelper.backdateConfirmation(
userId,
email3,
daysToBackdateForAfterDate
)
})
it('should flag inReconfirmNotificationPeriod for all affiliations in period', async function() {
@ -1045,12 +1056,15 @@ describe('UserEmails', function() {
expect(
fullEmails[1].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
expect(fullEmails[1].affiliation.pastReconfirmDate).to.equal(false)
expect(
fullEmails[2].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
expect(fullEmails[2].affiliation.pastReconfirmDate).to.equal(false)
expect(
fullEmails[3].affiliation.inReconfirmNotificationPeriod
).to.equal(true)
expect(fullEmails[3].affiliation.pastReconfirmDate).to.equal(true)
})
describe('should flag emails before their confirmation expires, but within the notification period', function() {

View file

@ -195,8 +195,10 @@ describe('UserGetter', function() {
inferred: affiliationsData[0].inferred,
department: affiliationsData[0].department,
role: affiliationsData[0].role,
lastDayToReconfirm: undefined,
licence: affiliationsData[0].licence,
inReconfirmNotificationPeriod: false,
pastReconfirmDate: false,
portal: undefined
}
},