Просмотр исходного кода

Merge pull request #29332 from overleaf/as-sso-prevent-double-linking

[web] Prevent users from attempting to link to the same SSO institution twice

GitOrigin-RevId: 7e708eadc9f9aedc2007cb83f7f48df83561fa84
MoxAmber 9 месяцев назад
Родитель
Сommit
87d8e142cc

+ 18 - 1
services/web/frontend/js/features/settings/components/emails/add-email.tsx

@@ -245,6 +245,7 @@ function AddEmail() {
                 <AddEmailViaSSO
                   email={newEmail}
                   domainInfo={newEmailMatchedDomain}
+                  userInstitutions={state.data.linkedInstitutionIds}
                 />
               </div>
             </Cell>
@@ -259,12 +260,28 @@ function AddEmail() {
 function AddEmailViaSSO({
   email,
   domainInfo,
+  userInstitutions,
 }: {
   email: string
   domainInfo: DomainInfo
+  userInstitutions: string[]
 }) {
   if (domainInfo.university.ssoEnabled) {
-    // SSO for Commons institution
+    // Check if the user has already linked this institution
+    if (userInstitutions.includes(domainInfo.university.id.toString())) {
+      return (
+        <Notification
+          type="error"
+          ariaLive="polite"
+          content={
+            <>
+              This institution is already linked with your account via another
+              email address.
+            </>
+          }
+        />
+      )
+    }
     return <SsoLinkingInfo email={email} domainInfo={domainInfo} />
   } else if (
     domainInfo.group?.domainCaptureEnabled &&

+ 26 - 0
services/web/test/frontend/features/settings/components/emails/emails-section-add-new-email.test.tsx

@@ -289,6 +289,32 @@ describe('<EmailsSection />', function () {
     await screen.findByRole('button', { name: 'Link accounts and add email' })
   })
 
+  it('prevents user from linking to same SSO institution twice', async function () {
+    fetchMock.get('/user/emails?ensureAffiliation=true', [
+      { email: 'bar@autocomplete.edu', samlProviderId: '1234' },
+    ])
+    render(<EmailsSection />)
+
+    const button = await screen.findByRole<HTMLButtonElement>('button', {
+      name: 'Add another email',
+    })
+
+    await fetchMock.callHistory.flush(true)
+    fetchMock.removeRoutes().clearHistory()
+    fetchMock.get('express:/institutions/domains', institutionDomainData)
+
+    await userEvent.click(button)
+
+    const input = screen.getByRole('textbox', { name: 'Email' })
+    fireEvent.change(input, {
+      target: { value: 'baz@autocomplete.edu' },
+    })
+
+    await screen.findByText(
+      'This institution is already linked with your account via another email address.'
+    )
+  })
+
   it('adds new email address with existing institution and custom departments', async function () {
     const country = 'Germany'
     const customDepartment = 'Custom department'