diff --git a/services/web/app/src/Features/Institutions/InstitutionsAPI.js b/services/web/app/src/Features/Institutions/InstitutionsAPI.js index e6d5411a8a..3276cb347d 100644 --- a/services/web/app/src/Features/Institutions/InstitutionsAPI.js +++ b/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), } } diff --git a/services/web/app/src/Features/Project/ProjectController.js b/services/web/app/src/Features/Project/ProjectController.js index 74ba21e04d..9b5c9ad2ed 100644 --- a/services/web/app/src/Features/Project/ProjectController.js +++ b/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) diff --git a/services/web/app/src/Features/Project/ProjectListController.mjs b/services/web/app/src/Features/Project/ProjectListController.mjs index bb7bf0b2c9..712168f912 100644 --- a/services/web/app/src/Features/Project/ProjectListController.mjs +++ b/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 diff --git a/services/web/app/src/Features/User/UserGetter.js b/services/web/app/src/Features/User/UserGetter.js index 84bcb884ae..1bc86f98cf 100644 --- a/services/web/app/src/Features/User/UserGetter.js +++ b/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) { diff --git a/services/web/test/unit/src/Institutions/InstitutionsAPITests.js b/services/web/test/unit/src/Institutions/InstitutionsAPITests.js index fcd36dd1ad..c76f4f9a2f 100644 --- a/services/web/test/unit/src/Institutions/InstitutionsAPITests.js +++ b/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, + }, + }, ]) }) diff --git a/services/web/test/unit/src/Project/ProjectControllerTests.js b/services/web/test/unit/src/Project/ProjectControllerTests.js index 1898302202..2c2f95bfd3 100644 --- a/services/web/test/unit/src/Project/ProjectControllerTests.js +++ b/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) diff --git a/services/web/test/unit/src/Project/ProjectListController.test.mjs b/services/web/test/unit/src/Project/ProjectListController.test.mjs index 1f83bfb0c5..57ccb5887a 100644 --- a/services/web/test/unit/src/Project/ProjectListController.test.mjs +++ b/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 => {