mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 13:13:45 +01:00
Merge pull request #36310 from overleaf/jel-confirm-existing-email
[web] Check if domain captured by group when showing confirm email UI GitOrigin-RevId: bb6add82e083497c8036739d877610a47e35ecfd
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { UserEmailData } from '../../../../../../types/user-email'
|
||||
import { ssoAvailableForInstitution } from '../../utils/sso'
|
||||
import OLBadge from '@/shared/components/ol/ol-badge'
|
||||
import ResendConfirmationCodeModal from '@/features/settings/components/emails/resend-confirmation-code-modal'
|
||||
import { useUserEmailsContext } from '@/features/settings/context/user-email-context'
|
||||
import { emailMustBeConfirmedViaSAML } from '../../utils/email-confirmation'
|
||||
|
||||
type EmailProps = {
|
||||
userEmailData: UserEmailData
|
||||
@@ -16,8 +16,8 @@ function Email({ userEmailData }: EmailProps) {
|
||||
setLoading: setUserEmailsContextLoading,
|
||||
getEmails,
|
||||
} = useUserEmailsContext()
|
||||
const ssoAvailable = ssoAvailableForInstitution(
|
||||
userEmailData.affiliation?.institution || null
|
||||
const mustConfirmViaSAML = emailMustBeConfirmedViaSAML(
|
||||
userEmailData.affiliation || null
|
||||
)
|
||||
|
||||
const isPrimary = userEmailData.default
|
||||
@@ -37,7 +37,7 @@ function Email({ userEmailData }: EmailProps) {
|
||||
<div className="small">
|
||||
<strong>{t('unconfirmed')}.</strong>
|
||||
<br />
|
||||
{!ssoAvailable && (
|
||||
{!mustConfirmViaSAML && (
|
||||
<ResendConfirmationCodeModal
|
||||
email={userEmailData.email}
|
||||
setGroupLoading={setUserEmailsContextLoading}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import getMeta from '@/utils/meta'
|
||||
import { Affiliation } from '../../../../../types/affiliation'
|
||||
import { ssoAvailableForInstitution } from './sso'
|
||||
|
||||
export const emailMustBeConfirmedViaSAML = (
|
||||
affiliation: Affiliation | null
|
||||
): boolean => {
|
||||
const { hasSamlFeature } = getMeta('ol-ExposedSettings')
|
||||
if (
|
||||
!hasSamlFeature ||
|
||||
!affiliation ||
|
||||
!affiliation.institution ||
|
||||
!affiliation.institution.confirmed
|
||||
) {
|
||||
return false
|
||||
}
|
||||
// both groups and Commons have affiliation.institution, but only Commons has SAML
|
||||
// information in affiliation.institution
|
||||
// ssoAvailableForInstitution will only check affiliation.institution for Commons
|
||||
// and there are different rules for whether SAML is enabled or not for groups with
|
||||
// domain capture or Commons
|
||||
|
||||
const samlViaCommons = ssoAvailableForInstitution(affiliation.institution)
|
||||
|
||||
const samlViaGroup =
|
||||
affiliation.domainCapturedByGroup &&
|
||||
affiliation.group?.domainCaptureEnabled &&
|
||||
affiliation.group?.managedUsersEnabled
|
||||
|
||||
return samlViaCommons || samlViaGroup || false
|
||||
}
|
||||
+41
@@ -9,6 +9,7 @@ import {
|
||||
import EmailsSection from '../../../../../../frontend/js/features/settings/components/emails-section'
|
||||
import { expect } from 'chai'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import {
|
||||
confirmedUserData,
|
||||
fakeUsersData,
|
||||
@@ -111,6 +112,46 @@ describe('<EmailsSection />', function () {
|
||||
await screen.findByRole('button', { name: 'Send confirmation code' })
|
||||
})
|
||||
|
||||
describe('SAML emails', function () {
|
||||
beforeEach(function () {
|
||||
Object.assign(getMeta('ol-ExposedSettings'), {
|
||||
hasSamlFeature: true,
|
||||
})
|
||||
fetchMock.removeRoutes().clearHistory()
|
||||
})
|
||||
|
||||
it('hides resend link when an unconfirmed affiliated email must be confirmed via Commons SAML', async function () {
|
||||
const commonsSamlEmail = cloneDeep(professionalUserData)
|
||||
delete commonsSamlEmail.confirmedAt
|
||||
commonsSamlEmail.affiliation.institution.ssoEnabled = true
|
||||
|
||||
fetchMock.get('/user/emails?ensureAffiliation=true', [commonsSamlEmail])
|
||||
renderEmailsSection()
|
||||
|
||||
await screen.findByText(/unconfirmed/i)
|
||||
expect(screen.queryByRole('button', { name: 'Send confirmation code' }))
|
||||
.to.be.null
|
||||
})
|
||||
|
||||
it('hides resend link when an unconfirmed affiliated email must be confirmed via managed group SAML', async function () {
|
||||
const managedGroupEmail = cloneDeep(professionalUserData)
|
||||
delete managedGroupEmail.confirmedAt
|
||||
managedGroupEmail.affiliation.domainCapturedByGroup = true
|
||||
managedGroupEmail.affiliation.group = {
|
||||
_id: 'group123',
|
||||
domainCaptureEnabled: true,
|
||||
managedUsersEnabled: true,
|
||||
}
|
||||
|
||||
fetchMock.get('/user/emails?ensureAffiliation=true', [managedGroupEmail])
|
||||
renderEmailsSection()
|
||||
|
||||
await screen.findByText(/unconfirmed/i)
|
||||
expect(screen.queryByRole('button', { name: 'Send confirmation code' }))
|
||||
.to.be.null
|
||||
})
|
||||
})
|
||||
|
||||
it('renders commons label', async function () {
|
||||
fetchMock.get('/user/emails?ensureAffiliation=true', [professionalUserData])
|
||||
renderEmailsSection()
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
import { expect } from 'chai'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { professionalUserData } from '../fixtures/test-user-email-data'
|
||||
import { Affiliation } from '../../../../../types/affiliation'
|
||||
import { emailMustBeConfirmedViaSAML } from '../../../../../frontend/js/features/settings/utils/email-confirmation'
|
||||
|
||||
describe('emailMustBeConfirmedViaSAML', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache.set('ol-ExposedSettings', {
|
||||
hasSamlFeature: true,
|
||||
hasSamlBeta: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('returns false when hasSamlFeature is false', function () {
|
||||
window.metaAttributesCache.set('ol-ExposedSettings', {
|
||||
hasSamlFeature: false,
|
||||
hasSamlBeta: false,
|
||||
})
|
||||
|
||||
const affiliation: Affiliation = cloneDeep(professionalUserData.affiliation)
|
||||
affiliation.domainCapturedByGroup = true
|
||||
affiliation.group = {
|
||||
_id: 'group123',
|
||||
domainCaptureEnabled: true,
|
||||
managedUsersEnabled: true,
|
||||
}
|
||||
|
||||
expect(emailMustBeConfirmedViaSAML(affiliation)).to.be.false
|
||||
})
|
||||
|
||||
it('returns false when affiliation is null', function () {
|
||||
expect(emailMustBeConfirmedViaSAML(null)).to.be.false
|
||||
})
|
||||
|
||||
it('returns false when institution is not confirmed', function () {
|
||||
const affiliation: Affiliation = cloneDeep(professionalUserData.affiliation)
|
||||
affiliation.institution.confirmed = false
|
||||
affiliation.domainCapturedByGroup = true
|
||||
affiliation.group = {
|
||||
_id: 'group123',
|
||||
domainCaptureEnabled: true,
|
||||
managedUsersEnabled: true,
|
||||
}
|
||||
|
||||
expect(emailMustBeConfirmedViaSAML(affiliation)).to.be.false
|
||||
})
|
||||
|
||||
it('returns true when Commons SSO is available for the institution', function () {
|
||||
const affiliation: Affiliation = cloneDeep(professionalUserData.affiliation)
|
||||
affiliation.institution.ssoEnabled = true
|
||||
|
||||
expect(emailMustBeConfirmedViaSAML(affiliation)).to.be.true
|
||||
})
|
||||
|
||||
it('returns true when the email is captured by a managed domain-capture group', function () {
|
||||
const affiliation: Affiliation = cloneDeep(professionalUserData.affiliation)
|
||||
affiliation.domainCapturedByGroup = true
|
||||
affiliation.group = {
|
||||
_id: 'group123',
|
||||
domainCaptureEnabled: true,
|
||||
managedUsersEnabled: true,
|
||||
}
|
||||
|
||||
expect(emailMustBeConfirmedViaSAML(affiliation)).to.be.true
|
||||
})
|
||||
|
||||
it('returns false when the group is managed but the email domain is not captured by the group', function () {
|
||||
const affiliation: Affiliation = cloneDeep(professionalUserData.affiliation)
|
||||
affiliation.domainCapturedByGroup = false
|
||||
affiliation.group = {
|
||||
_id: 'group123',
|
||||
domainCaptureEnabled: true,
|
||||
managedUsersEnabled: true,
|
||||
}
|
||||
|
||||
expect(emailMustBeConfirmedViaSAML(affiliation)).to.be.false
|
||||
})
|
||||
|
||||
it('returns false when the email is captured but managed users are disabled', function () {
|
||||
const affiliation: Affiliation = cloneDeep(professionalUserData.affiliation)
|
||||
affiliation.domainCapturedByGroup = true
|
||||
affiliation.group = {
|
||||
_id: 'group123',
|
||||
domainCaptureEnabled: true,
|
||||
managedUsersEnabled: false,
|
||||
}
|
||||
|
||||
expect(emailMustBeConfirmedViaSAML(affiliation)).to.be.false
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user