diff --git a/services/web/app/src/Features/Email/EmailBuilder.js b/services/web/app/src/Features/Email/EmailBuilder.js
index 84b79c78b2..db68342d48 100644
--- a/services/web/app/src/Features/Email/EmailBuilder.js
+++ b/services/web/app/src/Features/Email/EmailBuilder.js
@@ -445,6 +445,44 @@ templates.inviteNewUserToJoinManagedUsers = ctaTemplate({
},
})
+templates.managedUsersDisabledSSO = ctaTemplate({
+ subject(opts) {
+ return `Action required: Set your Overleaf password`
+ },
+ title(opts) {
+ return `Single sign-on disabled`
+ },
+ message(opts) {
+ return [
+ `Hi,
+
+ Your group administrator has disabled single sign-on for your group.
+
+
+
+ What does this mean for you?
+
+
+
+ You now need an email address and password to sign in to your Overleaf account.
+
+ `,
+ ]
+ },
+ secondaryMessage(opts) {
+ return [``]
+ },
+ ctaURL(opts) {
+ return opts.setNewPasswordUrl
+ },
+ ctaText(opts) {
+ return 'Set your new password'
+ },
+ greeting() {
+ return ''
+ },
+})
+
templates.surrenderAccountForManagedUsers = ctaTemplate({
subject(opts) {
const admin = _.escape(_formatUserNameAndEmail(opts.admin, 'an admin'))
diff --git a/services/web/frontend/stories/subscription/sso/disable-modal.stories.tsx b/services/web/frontend/stories/subscription/sso/disable-modal.stories.tsx
new file mode 100644
index 0000000000..4e287979f4
--- /dev/null
+++ b/services/web/frontend/stories/subscription/sso/disable-modal.stories.tsx
@@ -0,0 +1,37 @@
+import SSODisableModal, {
+ type SSODisableModalProps,
+} from '../../../../modules/managed-users/frontend/js/components/modals/sso-disable-modal'
+import useFetchMock from '../../hooks/use-fetch-mock'
+import { useMeta } from '../../hooks/use-meta'
+
+export const DisableSSOModalDefault = (args: SSODisableModalProps) => {
+ useMeta({ 'ol-groupId': '123' })
+ useFetchMock(fetchMock => {
+ fetchMock.post('express:/manage/groups/:id/settings/disableSSO', 200, {
+ delay: 500,
+ })
+ })
+ return
+}
+
+export const DisableSSOModalError = (args: SSODisableModalProps) => {
+ useMeta({ 'ol-groupId': '123' })
+ useFetchMock(fetchMock => {
+ fetchMock.post('express:/manage/groups/:id/settings/enableSSO', 500, {
+ delay: 500,
+ })
+ })
+ return
+}
+
+export default {
+ title: 'Subscription / SSO / Disable Modal',
+ component: SSODisableModal,
+ args: {
+ show: true,
+ },
+ argTypes: {
+ handleHide: { action: 'close modal' },
+ onDisableSSO: { action: 'callback' },
+ },
+}
diff --git a/services/web/test/frontend/features/group-management/components/sso/group-settings-sso.spec.tsx b/services/web/test/frontend/features/group-management/components/sso/group-settings-sso.spec.tsx
index b2b1ec167c..848418658d 100644
--- a/services/web/test/frontend/features/group-management/components/sso/group-settings-sso.spec.tsx
+++ b/services/web/test/frontend/features/group-management/components/sso/group-settings-sso.spec.tsx
@@ -135,5 +135,74 @@ describe('GroupSettingsSSO', function () {
})
})
})
+ describe('SSO disable modal', function () {
+ beforeEach(function () {
+ cy.intercept('GET', `/manage/groups/${GROUP_ID}/settings/sso`, {
+ statusCode: 200,
+ body: {
+ entryPoint: 'entrypoint',
+ certificate: 'cert',
+ signatureAlgorithm: 'sha1',
+ userIdAttribute: 'email',
+ enabled: true,
+ },
+ }).as('sso')
+
+ cy.mount()
+
+ cy.wait('@sso')
+
+ cy.get('.group-settings-sso-enable').within(() => {
+ cy.get('.switch-input').within(() => {
+ cy.get('.invisible-input').click({ force: true })
+ })
+ })
+ })
+
+ it('render disable modal correctly', function () {
+ // disable modal
+ cy.get('.modal-dialog').within(() => {
+ cy.contains('Disable single sign-on')
+ cy.contains(
+ 'You’re about to disable single sign-on for all group members.'
+ )
+ })
+ })
+
+ it('close disable modal if Cancel button is clicked', function () {
+ cy.get('.modal-dialog').within(() => {
+ cy.findByRole('button', { name: 'Cancel' }).click()
+ })
+
+ cy.get('.modal-dialog').should('not.exist')
+ })
+
+ it('disables SSO if Disable SSO button is clicked', function () {
+ cy.intercept('POST', `/manage/groups/${GROUP_ID}/settings/disableSSO`, {
+ statusCode: 200,
+ }).as('disableSSO')
+
+ cy.intercept('GET', `/manage/groups/${GROUP_ID}/settings/sso`, {
+ statusCode: 200,
+ body: {
+ entryPoint: 'entrypoint',
+ certificate: 'cert',
+ signatureAlgorithm: 'sha1',
+ userIdAttribute: 'email',
+ enabled: false,
+ },
+ }).as('sso')
+
+ cy.get('.modal-dialog').within(() => {
+ cy.findByRole('button', { name: 'Disable SSO' }).click()
+ })
+ cy.get('.modal-dialog').should('not.exist')
+ cy.get('.group-settings-sso-enable').within(() => {
+ cy.get('.switch-input').within(() => {
+ cy.get('.invisible-input').should('not.be.checked')
+ })
+ })
+ })
+ })
})
})