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

[web] Redirect to domain capture page

GitOrigin-RevId: 15d2b8046beb5a40fc4937c337ee9655abaed8fd
This commit is contained in:
Jessica Lawshe
2025-08-19 10:18:29 -05:00
committed by Copybot
parent 9b90b5e823
commit 1aef3acca9
7 changed files with 107 additions and 4 deletions

View File

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

View File

@@ -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)

View File

@@ -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

View File

@@ -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) {

View File

@@ -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,
},
},
])
})

View File

@@ -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)

View File

@@ -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 => {