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
This commit is contained in:
Jessica Lawshe
2025-10-16 09:53:29 -05:00
committed by Copybot
parent 046449d4bd
commit 6e9df02c16
5 changed files with 139 additions and 3 deletions

View File

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

View File

@@ -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": "",

View File

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

View File

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

View File

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