Эх сурвалжийг харах

Merge pull request #28744 from overleaf/jel-domain-capture-joined

[web] Success message after user is created via domain capture and group is managed

GitOrigin-RevId: 0615cf0e06af5f3851f2c6de30d870a3adace286
Jessica Lawshe 10 сар өмнө
parent
commit
6e9df02c16

+ 12 - 3
services/web/app/src/Features/Project/ProjectListController.mjs

@@ -321,14 +321,23 @@ async function projectListPage(req, res, next) {
     if (samlSession) {
       // Notification institution SSO: After SSO Linked
       if (samlSession.linked) {
+        let templateKey = 'notification_institution_sso_linked'
+
+        if (
+          samlSession.userCreatedViaDomainCapture &&
+          samlSession.managedUsersEnabled
+        ) {
+          templateKey =
+            'notification_account_created_via_group_domain_capture_and_managed_users_enabled'
+        } else if (samlSession.domainCaptureEnabled) {
+          templateKey = 'notification_group_sso_linked'
+        }
         notificationsInstitution.push({
           email: samlSession.institutionEmail,
           institutionName:
             samlSession.linked.universityName ||
             samlSession.linked.providerName,
-          templateKey: samlSession.domainCaptureEnabled
-            ? 'notification_group_sso_linked'
-            : 'notification_institution_sso_linked',
+          templateKey,
         })
       }
 

+ 2 - 0
services/web/frontend/extracted-translations.json

@@ -57,6 +57,7 @@
   "account_has_past_due_invoice_change_plan_warning": "",
   "account_help": "",
   "account_managed_by_group_administrator": "",
+  "account_managed_by_group_teamname": "",
   "account_not_linked_to_dropbox": "",
   "account_settings": "",
   "acct_linked_to_institution_acct_2": "",
@@ -1392,6 +1393,7 @@
   "read_lines_from_path": "",
   "read_more": "",
   "read_more_about_free_compile_timeouts_servers": "",
+  "read_more_about_managed_users": "",
   "read_only_dropbox_sync_message": "",
   "read_only_token": "",
   "read_write_token": "",

+ 28 - 0
services/web/frontend/js/features/project-list/components/notifications/groups/institution.tsx

@@ -103,6 +103,34 @@ function Institution() {
                 }
               />
             )}
+            {templateKey ===
+              'notification_account_created_via_group_domain_capture_and_managed_users_enabled' && (
+              <Notification
+                type="info"
+                onDismiss={() => id && handleDismiss(id)}
+                content={
+                  <>
+                    <Trans
+                      i18nKey="account_managed_by_group_teamname"
+                      components={
+                        /* eslint-disable-next-line jsx-a11y/anchor-has-content, react/jsx-key */
+                        [<strong />]
+                      }
+                      values={{ appName, email, teamName: institutionName }}
+                      shouldUnescape
+                      tOptions={{ interpolation: { escapeValue: true } }}
+                    />
+                    &nbsp;
+                    <a
+                      href="/learn/how-to/Understanding_Managed_Overleaf_Accounts"
+                      target="_blank"
+                    >
+                      {t('read_more_about_managed_users')}
+                    </a>
+                  </>
+                }
+              />
+            )}
             {templateKey === 'notification_institution_sso_non_canonical' && (
               <Notification
                 type="warning"

+ 2 - 0
services/web/locales/en.json

@@ -63,6 +63,7 @@
   "account_help": "Account and help",
   "account_linking": "Account linking",
   "account_managed_by_group_administrator": "Your account is managed by your group administrator (__admin__)",
+  "account_managed_by_group_teamname": "Your __appName__ account on <0>__email__</0> is managed by <0>__teamName__</0>.",
   "account_not_linked_to_dropbox": "Your account is not linked to Dropbox",
   "account_settings": "Account settings",
   "account_with_email_exists": "It looks like an <b>__appName__</b> account with the email <b>__email__</b> already exists.",
@@ -1805,6 +1806,7 @@
   "read_lines_from_path": "Read lines from __path__",
   "read_more": "Read more",
   "read_more_about_free_compile_timeouts_servers": "Read more about changes to free compile timeouts and servers",
+  "read_more_about_managed_users": "Read more about managed users",
   "read_only_dropbox_sync_message": "As a read-only viewer you can sync the current project version to Dropbox, but changes made in Dropbox will <0>not</0> sync back to Overleaf.",
   "read_only_token": "Read-Only Token",
   "read_write_token": "Read-Write Token",

+ 95 - 0
services/web/test/unit/src/Project/ProjectListController.test.mjs

@@ -541,6 +541,101 @@ describe('ProjectListController', function () {
       })
     })
 
+    describe('when user linked to SSO', function () {
+      const linkedEmail = 'picard@starfleet.com'
+      const universityName = 'Starfleet'
+      const notificationData = {
+        email: linkedEmail,
+        institutionName: universityName,
+      }
+      beforeEach(function (ctx) {
+        ctx.Features.hasFeature.withArgs('saml').returns(true)
+        ctx.req.session.saml = {
+          institutionEmail: linkedEmail,
+          linked: {
+            universityName,
+          },
+        }
+      })
+
+      it('should render with Commons template when Commons was linked', async function (ctx) {
+        await new Promise(resolve => {
+          ctx.res.render = (pageName, opts) => {
+            expect(opts.notificationsInstitution).to.deep.equal([
+              Object.assign(
+                { templateKey: 'notification_institution_sso_linked' },
+                notificationData
+              ),
+            ])
+            resolve()
+          }
+          ctx.ProjectListController.projectListPage(ctx.req, ctx.res)
+        })
+      })
+
+      describe('when via domain capture', function () {
+        beforeEach(function (ctx) {
+          ctx.req.session.saml.domainCaptureEnabled = true
+        })
+
+        it('should render with group template', async function (ctx) {
+          await new Promise(resolve => {
+            ctx.res.render = (pageName, opts) => {
+              expect(opts.notificationsInstitution).to.deep.equal([
+                Object.assign(
+                  { templateKey: 'notification_group_sso_linked' },
+                  notificationData
+                ),
+              ])
+              resolve()
+            }
+            ctx.ProjectListController.projectListPage(ctx.req, ctx.res)
+          })
+        })
+
+        describe('user created via domain capture and group is managed', function () {
+          beforeEach(function (ctx) {
+            ctx.req.session.saml.userCreatedViaDomainCapture = true
+          })
+          it('should render with notification_group_sso_linked', async function (ctx) {
+            await new Promise(resolve => {
+              ctx.res.render = (pageName, opts) => {
+                expect(opts.notificationsInstitution).to.deep.equal([
+                  Object.assign(
+                    {
+                      templateKey: 'notification_group_sso_linked',
+                    },
+                    notificationData
+                  ),
+                ])
+                resolve()
+              }
+              ctx.ProjectListController.projectListPage(ctx.req, ctx.res)
+            })
+          })
+
+          it('should render with notification_account_created_via_group_domain_capture_and_managed_users_enabled when managed user is enabled', async function (ctx) {
+            ctx.req.session.saml.managedUsersEnabled = true
+            await new Promise(resolve => {
+              ctx.res.render = (pageName, opts) => {
+                expect(opts.notificationsInstitution).to.deep.equal([
+                  Object.assign(
+                    {
+                      templateKey:
+                        'notification_account_created_via_group_domain_capture_and_managed_users_enabled',
+                    },
+                    notificationData
+                  ),
+                ])
+                resolve()
+              }
+              ctx.ProjectListController.projectListPage(ctx.req, ctx.res)
+            })
+          })
+        })
+      })
+    })
+
     describe('With Institution SSO feature', function () {
       beforeEach(async function (ctx) {
         await new Promise(resolve => {