Browse Source

Merge pull request #27834 from overleaf/ii-domain-capture-not-in-group-redirect

[web] Redirect to domain capture page

GitOrigin-RevId: 15d2b8046beb5a40fc4937c337ee9655abaed8fd
Jessica Lawshe 11 months ago
parent
commit
1aef3acca9

+ 2 - 0
services/web/app/src/Features/Institutions/InstitutionsAPI.js

@@ -173,6 +173,8 @@ function getUserAffiliations(userId, callback) {
 
             if (group) {
               affiliation.group = {
+                _id: group._id,
+                managedUsersEnabled: Boolean(group.managedUsersEnabled),
                 domainCaptureEnabled: Boolean(group.domainCaptureEnabled),
               }
             }

+ 22 - 0
services/web/app/src/Features/Project/ProjectController.js

@@ -322,6 +322,28 @@ const _ProjectController = {
       userId = null
     }
 
+    if (Features.hasFeature('saas') && userId) {
+      const { variant: domainCaptureRedirect } =
+        await SplitTestHandler.promises.getAssignment(
+          req,
+          res,
+          'domain-capture-redirect'
+        )
+
+      if (domainCaptureRedirect === 'enabled') {
+        const subscription = (
+          await Modules.promises.hooks.fire(
+            'findDomainCaptureAndManagedUsersGroupUserShouldBePartOf',
+            userId
+          )
+        )?.[0]
+
+        if (subscription) {
+          return res.redirect('/domain-capture')
+        }
+      }
+    }
+
     const projectId = req.params.Project_id
 
     // should not be used in place of split tests query param overrides (?my-split-test-name=my-variant)

+ 23 - 0
services/web/app/src/Features/Project/ProjectListController.mjs

@@ -112,6 +112,29 @@ async function projectListPage(req, res, next) {
   const isSaas = Features.hasFeature('saas')
 
   const userId = SessionManager.getLoggedInUserId(req.session)
+
+  if (isSaas) {
+    const { variant: domainCaptureRedirect } =
+      await SplitTestHandler.promises.getAssignment(
+        req,
+        res,
+        'domain-capture-redirect'
+      )
+
+    if (domainCaptureRedirect === 'enabled') {
+      const subscription = (
+        await Modules.promises.hooks.fire(
+          'findDomainCaptureAndManagedUsersGroupUserShouldBePartOf',
+          userId
+        )
+      )?.[0]
+
+      if (subscription) {
+        return res.redirect('/domain-capture')
+      }
+    }
+  }
+
   const projectsBlobPending = _getProjects(userId).catch(err => {
     logger.err({ err, userId }, 'projects listing in background failed')
     return undefined

+ 4 - 0
services/web/app/src/Features/User/UserGetter.js

@@ -325,6 +325,7 @@ const decorateFullEmails = (
         past_reconfirm_date: cachedPastReconfirmDate,
         entitlement: cachedEntitlement,
         portal,
+        group,
       } = affiliation
       const lastDayToReconfirm = _lastDayToReconfirm(emailData, institution)
       let { last_day_to_reconfirm: cachedLastDayToReconfirm } = affiliation
@@ -353,6 +354,9 @@ const decorateFullEmails = (
         licence,
         portal,
       }
+      if (group) {
+        emailData.affiliation.group = group
+      }
     }
 
     if (emailData.samlProviderId) {

+ 18 - 4
services/web/test/unit/src/Institutions/InstitutionsAPITests.js

@@ -2,6 +2,7 @@ const { expect } = require('chai')
 const SandboxedModule = require('sandboxed-module')
 const path = require('path')
 const sinon = require('sinon')
+const { ObjectId } = require('mongodb-legacy')
 const modulePath = path.join(
   __dirname,
   '../../../../app/src/Features/Institutions/InstitutionsAPI'
@@ -160,9 +161,17 @@ describe('InstitutionsAPI', function () {
         },
       ]
       this.request.callsArgWith(1, null, { statusCode: 201 }, responseBody)
-      this.Modules.promises.hooks.fire.resolves([
-        { domainCaptureEnabled: true },
-      ])
+      const groupResponse = {
+        _id: new ObjectId(),
+        managedUsersEnabled: false,
+        domainCaptureEnabled: true,
+      }
+      this.Modules.promises.hooks.fire
+        .withArgs(
+          'getGroupWithDomainCaptureByV1Id',
+          responseBody[0].institution.id
+        )
+        .resolves([groupResponse])
       const body = await this.InstitutionsAPI.promises.getUserAffiliations(
         this.stubbedUser._id
       )
@@ -178,7 +187,12 @@ describe('InstitutionsAPI', function () {
       )
       expect(requestOptions.body).not.to.exist
       expect(body).to.deep.equal([
-        { ...responseBody[0], group: { domainCaptureEnabled: true } },
+        {
+          ...responseBody[0],
+          group: {
+            ...groupResponse,
+          },
+        },
       ])
     })
 

+ 18 - 0
services/web/test/unit/src/Project/ProjectControllerTests.js

@@ -594,6 +594,24 @@ describe('ProjectController', function () {
       this.ProjectController.loadEditor(this.req, this.res)
     })
 
+    it('should redirect to domain capture page', function (done) {
+      this.Features.hasFeature.withArgs('saas').returns(true)
+      this.SplitTestHandler.promises.getAssignment
+        .withArgs(this.req, this.res, 'domain-capture-redirect')
+        .resolves({ variant: 'enabled' })
+      this.Modules.promises.hooks.fire
+        .withArgs(
+          'findDomainCaptureAndManagedUsersGroupUserShouldBePartOf',
+          this.user._id
+        )
+        .resolves([{ _id: new ObjectId() }])
+      this.res.redirect = url => {
+        url.should.equal('/domain-capture')
+        done()
+      }
+      this.ProjectController.loadEditor(this.req, this.res)
+    })
+
     it('should add user', function (done) {
       this.res.render = (pageName, opts) => {
         opts.user.email.should.equal(this.user.email)

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

@@ -493,6 +493,26 @@ describe('ProjectListController', function () {
       })
     })
 
+    it('should redirect to domain capture page', async function (ctx) {
+      await new Promise(resolve => {
+        ctx.Features.hasFeature.withArgs('saas').returns(true)
+        ctx.SplitTestHandler.promises.getAssignment
+          .withArgs(ctx.req, ctx.res, 'domain-capture-redirect')
+          .resolves({ variant: 'enabled' })
+        ctx.Modules.promises.hooks.fire
+          .withArgs(
+            'findDomainCaptureAndManagedUsersGroupUserShouldBePartOf',
+            ctx.user._id
+          )
+          .resolves([{ _id: new ObjectId() }])
+        ctx.res.redirect = url => {
+          url.should.equal('/domain-capture')
+          resolve()
+        }
+        ctx.ProjectListController.projectListPage(ctx.req, ctx.res)
+      })
+    })
+
     describe('With Institution SSO feature', function () {
       beforeEach(async function (ctx) {
         await new Promise(resolve => {