From 6718729087be3e8b1fa939eadbc7f2688b623935 Mon Sep 17 00:00:00 2001 From: David <33458145+davidmcpowell@users.noreply.github.com> Date: Mon, 13 May 2024 15:57:52 +0100 Subject: [PATCH] Merge pull request #18318 from overleaf/dp-revert-secondary-email Revert "Merge pull request #18139 from overleaf/dp-add-secondary-prompt-ui" GitOrigin-RevId: d8af37a5c332ac21ddd4c85679553df0bda326f9 --- .../src/Features/User/UserEmailsController.js | 73 +--- .../web/app/src/Features/User/UserGetter.js | 14 - services/web/app/src/router.js | 15 - .../web/app/views/user/addSecondaryEmail.pug | 14 - .../app/views/user/confirmSecondaryEmail.pug | 15 - .../web/frontend/extracted-translations.json | 8 +- .../emails/add-secondary-email-prompt.tsx | 151 -------- .../components/emails/confirm-email.tsx | 326 ------------------ .../js/pages/user/add-secondary-email.tsx | 12 - .../js/pages/user/confirm-secondary-email.tsx | 13 - .../app/add-secondary-email-prompt.less | 16 - .../stylesheets/app/confirm-email.less | 23 -- .../stylesheets/components/interstitial.less | 1 - .../web/frontend/stylesheets/main-style.less | 3 - .../modules/overleaf-integration.less | 22 ++ services/web/locales/en.json | 8 +- services/web/locales/zh-CN.json | 1 + .../acceptance/src/AddSecondaryEmailTests.js | 3 +- .../acceptance/src/PrimaryEmailCheckTests.js | 92 +---- .../src/User/UserEmailsControllerTests.js | 4 +- .../web/test/unit/src/User/UserGetterTests.js | 39 --- 21 files changed, 42 insertions(+), 811 deletions(-) delete mode 100644 services/web/app/views/user/addSecondaryEmail.pug delete mode 100644 services/web/app/views/user/confirmSecondaryEmail.pug delete mode 100644 services/web/frontend/js/features/settings/components/emails/add-secondary-email-prompt.tsx delete mode 100644 services/web/frontend/js/features/settings/components/emails/confirm-email.tsx delete mode 100644 services/web/frontend/js/pages/user/add-secondary-email.tsx delete mode 100644 services/web/frontend/js/pages/user/confirm-secondary-email.tsx delete mode 100644 services/web/frontend/stylesheets/app/add-secondary-email-prompt.less delete mode 100644 services/web/frontend/stylesheets/app/confirm-email.less diff --git a/services/web/app/src/Features/User/UserEmailsController.js b/services/web/app/src/Features/User/UserEmailsController.js index faa5301497..cfb692798d 100644 --- a/services/web/app/src/Features/User/UserEmailsController.js +++ b/services/web/app/src/Features/User/UserEmailsController.js @@ -17,9 +17,7 @@ const AnalyticsManager = require('../Analytics/AnalyticsManager') const UserPrimaryEmailCheckHandler = require('../User/UserPrimaryEmailCheckHandler') const UserAuditLogHandler = require('./UserAuditLogHandler') const { RateLimiter } = require('../../infrastructure/RateLimiter') -const Features = require('../../infrastructure/Features') const tsscmp = require('tsscmp') -const Modules = require('../../infrastructure/Modules') const AUDIT_LOG_TOKEN_PREFIX_LENGTH = 10 @@ -210,7 +208,9 @@ async function addWithConfirmationCode(req, res) { confirmCodeExpiresTimestamp, } - return res.sendStatus(200) + return res.json({ + redir: '/user/emails/confirm-secondary', + }) } catch (err) { if (err.name === 'EmailExistsError') { return res.status(409).json({ @@ -414,45 +414,6 @@ async function resendSecondaryEmailConfirmationCode(req, res) { } } -async function confirmSecondaryEmailPage(req, res) { - const userId = SessionManager.getLoggedInUserId(req.session) - - if (!req.session.pendingSecondaryEmail) { - const redirectURL = - AuthenticationController.getRedirectFromSession(req) || '/project' - return res.redirect(redirectURL) - } - - AnalyticsManager.recordEventForUser( - userId, - 'confirm-secondary-email-page-displayed' - ) - - res.render('user/confirmSecondaryEmail', { - email: req.session.pendingSecondaryEmail.email, - }) -} - -async function addSecondaryEmailPage(req, res) { - const userId = SessionManager.getLoggedInUserId(req.session) - - const confirmedEmails = - await UserGetter.promises.getUserConfirmedEmails(userId) - - if (confirmedEmails.length >= 2) { - const redirectURL = - AuthenticationController.getRedirectFromSession(req) || '/project' - return res.redirect(redirectURL) - } - - AnalyticsManager.recordEventForUser( - userId, - 'add-secondary-email-page-displayed' - ) - - res.render('user/addSecondaryEmail') -} - async function primaryEmailCheckPage(req, res) { const userId = SessionManager.getLoggedInUserId(req.session) const user = await UserGetter.promises.getUser(userId, { @@ -479,30 +440,6 @@ async function primaryEmailCheck(req, res) { $set: { lastPrimaryEmailCheck: new Date() }, }) AnalyticsManager.recordEventForUser(userId, 'primary-email-check-done') - - // We want to redirect to prompt a user to add a secondary email if their primary - // is an institutional email and they dont' already have a secondary. - if (Features.hasFeature('affiliations')) { - const confirmedEmails = - await UserGetter.promises.getUserConfirmedEmails(userId) - - if (confirmedEmails.length < 2) { - const primaryEmail = await UserGetter.promises.getUserEmail(userId) - const primaryEmailDomain = EmailHelper.getDomain(primaryEmail) - - const institution = ( - await Modules.promises.hooks.fire( - 'getInstitutionViaDomain', - primaryEmailDomain - ) - )?.[0] - - if (institution) { - return AsyncFormHelper.redirect(req, res, '/user/emails/add-secondary') - } - } - } - AsyncFormHelper.redirect(req, res, '/project') } @@ -614,10 +551,6 @@ const UserEmailsController = { sendReconfirmation, - addSecondaryEmailPage: expressify(addSecondaryEmailPage), - - confirmSecondaryEmailPage: expressify(confirmSecondaryEmailPage), - primaryEmailCheckPage: expressify(primaryEmailCheckPage), primaryEmailCheck: expressify(primaryEmailCheck), diff --git a/services/web/app/src/Features/User/UserGetter.js b/services/web/app/src/Features/User/UserGetter.js index 4729fea3d3..2d68f3c24d 100644 --- a/services/web/app/src/Features/User/UserGetter.js +++ b/services/web/app/src/Features/User/UserGetter.js @@ -79,18 +79,6 @@ async function getUserFullEmails(userId) { ) } -async function getUserConfirmedEmails(userId) { - const user = await UserGetter.promises.getUser(userId, { - emails: 1, - }) - - if (!user) { - throw new Error('User not Found') - } - - return user.emails.filter(email => !!email.confirmedAt) -} - async function getSsoUsersAtInstitution(institutionId, projection) { if (!projection) { throw new Error('missing projection') @@ -136,8 +124,6 @@ const UserGetter = { getUserFullEmails: callbackify(getUserFullEmails), - getUserConfirmedEmails: callbackify(getUserConfirmedEmails), - getUserByMainEmail(email, projection, callback) { email = email.trim() if (arguments.length === 2) { diff --git a/services/web/app/src/router.js b/services/web/app/src/router.js index aa398e81fd..484b44e644 100644 --- a/services/web/app/src/router.js +++ b/services/web/app/src/router.js @@ -348,7 +348,6 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) { CaptchaMiddleware.validateCaptcha('addEmail'), UserEmailsController.add ) - webRouter.post( '/user/emails/delete', AuthenticationController.requireLogin(), @@ -391,20 +390,6 @@ function initialize(webRouter, privateApiRouter, publicApiRouter) { RateLimiterMiddleware.rateLimit(rateLimiters.resendConfirmationCode), UserEmailsController.resendSecondaryEmailConfirmationCode ) - - webRouter.get( - '/user/emails/add-secondary', - AuthenticationController.requireLogin(), - PermissionsController.requirePermission('add-secondary-email'), - UserEmailsController.addSecondaryEmailPage - ) - - webRouter.get( - '/user/emails/confirm-secondary', - AuthenticationController.requireLogin(), - PermissionsController.requirePermission('add-secondary-email'), - UserEmailsController.confirmSecondaryEmailPage - ) } webRouter.get( diff --git a/services/web/app/views/user/addSecondaryEmail.pug b/services/web/app/views/user/addSecondaryEmail.pug deleted file mode 100644 index 643a740b27..0000000000 --- a/services/web/app/views/user/addSecondaryEmail.pug +++ /dev/null @@ -1,14 +0,0 @@ -extends ../layout-marketing - -block vars - - var suppressNavbar = true - - var suppressSkipToContent = true - -block entrypointVar - - entrypoint = 'pages/user/add-secondary-email' - -block append meta - -block content - main.content.content-alt - #add-secondary-email diff --git a/services/web/app/views/user/confirmSecondaryEmail.pug b/services/web/app/views/user/confirmSecondaryEmail.pug deleted file mode 100644 index 4d0c59e9db..0000000000 --- a/services/web/app/views/user/confirmSecondaryEmail.pug +++ /dev/null @@ -1,15 +0,0 @@ -extends ../layout-marketing - -block vars - - var suppressNavbar = true - - var suppressSkipToContent = true - -block entrypointVar - - entrypoint = 'pages/user/confirm-secondary-email' - -block append meta - meta(name="ol-email" content=email) - -block content - main.content.content-alt - #confirm-secondary-email diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index db32fb3dc2..4a0b614fa3 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -33,7 +33,6 @@ "actions": "", "active": "", "add": "", - "add_a_recovery_email_address": "", "add_additional_certificate": "", "add_affiliation": "", "add_another_address_line": "", @@ -42,7 +41,6 @@ "add_comma_separated_emails_help": "", "add_comment": "", "add_company_details": "", - "add_email_address": "", "add_email_to_claim_features": "", "add_files": "", "add_more_collaborators": "", @@ -207,6 +205,7 @@ "confirm_primary_email_change": "", "confirm_remove_sso_config_enter_email": "", "confirm_your_email": "", + "confirmation_code_message": "", "confirming": "", "conflicting_paths_found": "", "congratulations_youve_successfully_join_group": "", @@ -357,7 +356,6 @@ "email_confirmed_onboarding_message": "", "email_limit_reached": "", "email_link_expired": "", - "email_must_be_linked_to_institution": "", "email_or_password_wrong_try_again": "", "emails_and_affiliations_explanation": "", "emails_and_affiliations_title": "", @@ -371,7 +369,6 @@ "enter_6_digit_code": "", "enter_any_size_including_units_or_valid_latex_command": "", "enter_image_url": "", - "enter_the_confirmation_code": "", "error": "", "error_opening_document": "", "error_opening_document_detail": "", @@ -639,7 +636,6 @@ "justify": "", "keep_current_plan": "", "keep_personal_projects_separate": "", - "keep_your_account_safe_add_another_email": "", "keybindings": "", "labels_help_you_to_easily_reference_your_figures": "", "labels_help_you_to_reference_your_tables": "", @@ -664,7 +660,6 @@ "layout": "", "layout_processing": "", "learn_more": "", - "learn_more_about_account": "", "learn_more_about_link_sharing": "", "learn_more_about_managed_users": "", "learn_more_about_other_causes_of_compile_timeouts": "", @@ -1311,7 +1306,6 @@ "test_configuration_successful": "", "tex_live_version": "", "thank_you_exclamation": "", - "thanks_for_confirming_your_email_address": "", "thanks_for_subscribing": "", "thanks_for_subscribing_you_help_sl": "", "thanks_settings_updated": "", diff --git a/services/web/frontend/js/features/settings/components/emails/add-secondary-email-prompt.tsx b/services/web/frontend/js/features/settings/components/emails/add-secondary-email-prompt.tsx deleted file mode 100644 index 664ac1e0c0..0000000000 --- a/services/web/frontend/js/features/settings/components/emails/add-secondary-email-prompt.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import { Interstitial } from '@/shared/components/interstitial' -import useWaitForI18n from '@/shared/hooks/use-wait-for-i18n' -import { Button } from 'react-bootstrap' -import { Trans, useTranslation } from 'react-i18next' -import EmailInput from './add-email/input' -import { useState } from 'react' -import MaterialIcon from '@/shared/components/material-icon' -import { sendMB } from '@/infrastructure/event-tracking' - -import { postJSON } from '../../../../infrastructure/fetch-json' - -type AddSecondaryEmailError = { - name: string - data: any -} - -export function AddSecondaryEmailPrompt() { - const isReady = useWaitForI18n() - const { t } = useTranslation() - const [email, setEmail] = useState() - const [error, setError] = useState() - const [isSubmitting, setIsSubmitting] = useState(false) - - if (!isReady) { - return null - } - - const onEmailChange = (newEmail: string) => { - if (newEmail !== email) { - setEmail(newEmail) - setError(undefined) - } - } - - const errorHandler = (err: any) => { - let errorName = 'generic_something_went_wrong' - - if (err?.response?.status === 409) { - errorName = 'email_already_registered' - } else if (err?.response?.status === 429) { - errorName = 'too_many_attempts' - } else if (err?.response?.status === 422) { - errorName = 'email_must_be_linked_to_institution' - } - - setError({ name: errorName, data: err?.data }) - sendMB('add-secondary-email-error', { errorName }) - } - - const handleSubmit = async (e?: React.FormEvent) => { - if (e) { - e.preventDefault() - } - - setIsSubmitting(true) - - await postJSON('/user/emails/secondary', { - body: { - email, - }, - }) - .then(() => { - location.assign('/user/emails/confirm-secondary') - }) - .catch(errorHandler) - .finally(() => { - setIsSubmitting(false) - }) - } - - return ( - <> - -
-

{t('keep_your_account_safe_add_another_email')}

- - - -
- {error && } -
- - - -

- , - ]} - /> -

- -
- - ) -} - -function ErrorMessage({ error }: { error: AddSecondaryEmailError }) { - const { t } = useTranslation() - - let errorText - - switch (error.name) { - case 'email_already_registered': - errorText = t('email_already_registered') - break - case 'too_many_attempts': - errorText = t('too_many_attempts') - break - case 'email_must_be_linked_to_institution': - errorText = ( - ]} - /> - ) - break - default: - errorText = t('generic_something_went_wrong') - } - - return ( -
- -
{errorText}
-
- ) -} diff --git a/services/web/frontend/js/features/settings/components/emails/confirm-email.tsx b/services/web/frontend/js/features/settings/components/emails/confirm-email.tsx deleted file mode 100644 index 8e3055a762..0000000000 --- a/services/web/frontend/js/features/settings/components/emails/confirm-email.tsx +++ /dev/null @@ -1,326 +0,0 @@ -import { postJSON } from '@/infrastructure/fetch-json' -import useWaitForI18n from '@/shared/hooks/use-wait-for-i18n' -import Notification from '@/shared/components/notification' -import getMeta from '@/utils/meta' -import { FormEvent, useState } from 'react' -import { Button } from 'react-bootstrap' -import { Trans, useTranslation } from 'react-i18next' -import LoadingSpinner from '@/shared/components/loading-spinner' -import MaterialIcon from '@/shared/components/material-icon' -import { sendMB } from '@/infrastructure/event-tracking' -import { Interstitial } from '@/shared/components/interstitial' - -type Feedback = { - type: 'input' | 'alert' - style: 'error' | 'info' - message: string -} - -type ConfirmEmailFormProps = { - isRegistrationForm: boolean -} - -export function ConfirmEmailForm({ - isRegistrationForm, -}: ConfirmEmailFormProps) { - const { t } = useTranslation() - const [confirmationCode, setConfirmationCode] = useState('') - const [feedback, setFeedback] = useState(null) - const [isConfirming, setIsConfirming] = useState(false) - const [isResending, setIsResending] = useState(false) - const [successRedirectPath, setSuccessRedirectPath] = useState('') - const email = getMeta('ol-email') - const { isReady } = useWaitForI18n() - - const errorHandler = (err: any, actionType?: string) => { - let errorName = err?.data?.message?.key || 'generic_something_went_wrong' - - if (err?.response?.status === 429) { - if (actionType === 'confirm') { - errorName = 'too_many_confirm_code_verification_attempts' - } else if (actionType === 'resend') { - errorName = 'too_many_confirm_code_resend_attempts' - } - setFeedback({ - type: 'alert', - style: 'error', - message: errorName, - }) - } else { - setFeedback({ - type: 'input', - style: 'error', - message: errorName, - }) - } - - sendMB('email-verification-error', { - errorName, - flow: isRegistrationForm ? 'registration' : 'secondary', - }) - } - - const invalidFormHandler = () => { - if (!confirmationCode) { - return setFeedback({ - type: 'input', - style: 'error', - message: 'please_enter_confirmation_code', - }) - } - } - - const submitHandler = (e: FormEvent) => { - e.preventDefault() - setIsConfirming(true) - setFeedback(null) - - const requestPath = isRegistrationForm - ? '/registration/confirm-email' - : '/user/emails/confirm-secondary' - - const requestBody = isRegistrationForm - ? { - _csrf: getMeta('ol-csrfToken'), - code: confirmationCode, - email, - } - : { - code: confirmationCode, - } - - postJSON(requestPath, { - body: requestBody, - }) - .then(data => { - setSuccessRedirectPath(data?.redir || '/') - }) - .catch(err => { - errorHandler(err, 'confirm') - }) - .finally(() => { - setIsConfirming(false) - }) - - sendMB('email-verification-click', { - button: 'verify', - flow: isRegistrationForm ? 'registration' : 'secondary', - }) - } - - const resendHandler = (e: FormEvent - - - - - ) -} - -function ConfirmEmailSuccessfullForm({ - isRegistrationForm, - redirectTo, -}: { - isRegistrationForm: boolean - redirectTo: string -}) { - const { t } = useTranslation() - const submitHandler = (e: FormEvent) => { - e.preventDefault() - location.assign(redirectTo) - } - - return ( - -
-
-

- {isRegistrationForm - ? t('email_confirmed_onboarding') - : t('thanks_for_confirming_your_email_address')} -

-

- {isRegistrationForm && ( - ]} - /> - )} -

-
- -
- -
-
-
- ) -} - -function ErrorMessage({ error }: { error: string }) { - const { t } = useTranslation() - - switch (error) { - case 'invalid_confirmation_code': - return {t('invalid_confirmation_code')} - - case 'expired_confirmation_code': - return ( - ]} - /> - ) - - case 'email_already_registered': - return {t('email_already_registered')} - - case 'too_many_confirm_code_resend_attempts': - return {t('too_many_confirm_code_resend_attempts')} - - case 'too_many_confirm_code_verification_attempts': - return {t('too_many_confirm_code_verification_attempts')} - - case 'we_sent_new_code': - return {t('we_sent_new_code')} - - case 'please_enter_confirmation_code': - return {t('please_enter_confirmation_code')} - - default: - return {t('generic_something_went_wrong')} - } -} diff --git a/services/web/frontend/js/pages/user/add-secondary-email.tsx b/services/web/frontend/js/pages/user/add-secondary-email.tsx deleted file mode 100644 index 8297d319af..0000000000 --- a/services/web/frontend/js/pages/user/add-secondary-email.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import '../../marketing' - -import ReactDOM from 'react-dom' -import { AddSecondaryEmailPrompt } from '../../features/settings/components/emails/add-secondary-email-prompt' - -const addSecondaryEmailContainer = document.getElementById( - 'add-secondary-email' -) - -if (addSecondaryEmailContainer) { - ReactDOM.render(, addSecondaryEmailContainer) -} diff --git a/services/web/frontend/js/pages/user/confirm-secondary-email.tsx b/services/web/frontend/js/pages/user/confirm-secondary-email.tsx deleted file mode 100644 index bce4619314..0000000000 --- a/services/web/frontend/js/pages/user/confirm-secondary-email.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import '../../marketing' - -import ReactDOM from 'react-dom' -import { ConfirmEmailForm } from '../../features/settings/components/emails/confirm-email' - -const confirmEmailContainer = document.getElementById('confirm-secondary-email') - -if (confirmEmailContainer) { - ReactDOM.render( - , - confirmEmailContainer - ) -} diff --git a/services/web/frontend/stylesheets/app/add-secondary-email-prompt.less b/services/web/frontend/stylesheets/app/add-secondary-email-prompt.less deleted file mode 100644 index 7a4eff71a7..0000000000 --- a/services/web/frontend/stylesheets/app/add-secondary-email-prompt.less +++ /dev/null @@ -1,16 +0,0 @@ -.add-secondary-email { - display: flex; - flex-direction: column; - gap: 12px; - - .add-secondary-email-error { - display: flex; - gap: 6px; - padding: 4px; - } - - .add-secondary-email-learn-more { - margin-top: 12px; - margin-bottom: 0; - } -} diff --git a/services/web/frontend/stylesheets/app/confirm-email.less b/services/web/frontend/stylesheets/app/confirm-email.less deleted file mode 100644 index 8ea0b2d9fb..0000000000 --- a/services/web/frontend/stylesheets/app/confirm-email.less +++ /dev/null @@ -1,23 +0,0 @@ -.confirm-email { - form { - .text-danger { - display: flex; - gap: 6px; - padding: 4px; - - .icon { - padding-top: 2px; - } - } - .form-actions { - display: flex; - flex-direction: column; - gap: 12px; - padding-top: 20px; - } - } - - .confirm-email-alert { - margin-bottom: 12px; - } -} diff --git a/services/web/frontend/stylesheets/components/interstitial.less b/services/web/frontend/stylesheets/components/interstitial.less index 1d83751e1c..ac51759182 100644 --- a/services/web/frontend/stylesheets/components/interstitial.less +++ b/services/web/frontend/stylesheets/components/interstitial.less @@ -9,7 +9,6 @@ .logo { width: 130px; margin: 0 auto; - margin-bottom: 24px; } .btn { diff --git a/services/web/frontend/stylesheets/main-style.less b/services/web/frontend/stylesheets/main-style.less index 6782633a29..5c56f96c5c 100644 --- a/services/web/frontend/stylesheets/main-style.less +++ b/services/web/frontend/stylesheets/main-style.less @@ -136,9 +136,6 @@ @import 'app/admin-hub.less'; @import 'app/import.less'; @import 'app/website-redesign.less'; -@import 'app/add-secondary-email-prompt.less'; -@import 'app/confirm-email.less'; - // Pages @import 'app/about.less'; @import 'app/blog-posts.less'; diff --git a/services/web/frontend/stylesheets/modules/overleaf-integration.less b/services/web/frontend/stylesheets/modules/overleaf-integration.less index bae3ebd68f..971d89ae86 100644 --- a/services/web/frontend/stylesheets/modules/overleaf-integration.less +++ b/services/web/frontend/stylesheets/modules/overleaf-integration.less @@ -1,3 +1,25 @@ +.onboarding-confirm-email { + gap: 24px; + + form { + .text-danger { + display: flex; + gap: 6px; + padding: 4px; + + .icon { + padding-top: 2px; + } + } + .form-actions { + display: flex; + flex-direction: column; + gap: 12px; + padding-top: 20px; + } + } +} + .onboarding-data-collection-wrapper { max-width: 720px; margin: 0 auto; diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 5e312943bc..fa9fb173b6 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -52,7 +52,6 @@ "activation_token_expired": "Your activation token has expired, you will need to get another one sent to you.", "active": "Active", "add": "Add", - "add_a_recovery_email_address": "Add a recovery email address", "add_additional_certificate": "Add another certificate", "add_affiliation": "Add Affiliation", "add_another_address_line": "Add another address line", @@ -62,7 +61,6 @@ "add_comment": "Add comment", "add_company_details": "Add Company Details", "add_email": "Add Email", - "add_email_address": "Add email address", "add_email_to_claim_features": "Add an institutional email address to claim your features.", "add_files": "Add Files", "add_more_collaborators": "Add more collaborators", @@ -299,6 +297,7 @@ "confirm_primary_email_change": "Confirm primary email change", "confirm_remove_sso_config_enter_email": "To confirm you want to remove your SSO configuration, enter your email address:", "confirm_your_email": "Confirm your email address", + "confirmation_code_message": "We’ve sent a 6-digit confirmation code to __email__. Please enter it below to confirm your email address.", "confirmation_link_broken": "Sorry, something is wrong with your confirmation link. Please try copy and pasting the link from the bottom of your confirmation email.", "confirmation_token_invalid": "Sorry, your confirmation token is invalid or has expired. Please request a new email confirmation link.", "confirming": "Confirming", @@ -500,7 +499,6 @@ "email_does_not_belong_to_university": "We don’t recognize that domain as being affiliated with your university. Please contact us to add the affiliation.", "email_limit_reached": "You can have a maximum of <0>__emailAddressLimit__ email addresses on this account. To add another email address, please delete an existing one.", "email_link_expired": "Email link expired, please request a new one.", - "email_must_be_linked_to_institution": "As a member of __institutionName__, this email address can only be added via single sign-on on your <0>account settings page. Please add a different recovery email address.", "email_or_password_wrong_try_again": "Your email or password is incorrect. Please try again.", "email_or_password_wrong_try_again_or_reset": "Your email or password is incorrect. Please try again, or <0>set or reset your password.", "email_required": "Email required", @@ -520,7 +518,6 @@ "enter_6_digit_code": "Enter 6-digit code", "enter_any_size_including_units_or_valid_latex_command": "Enter any size (including units) or valid LaTeX command", "enter_image_url": "Enter image URL", - "enter_the_confirmation_code": "Enter the 6-digit confirmation code sent to __email__.", "enter_your_email_address": "Enter your email address", "enter_your_email_address_below_and_we_will_send_you_a_link_to_reset_your_password": "Enter your email address below, and we will send you a link to reset your password", "enter_your_new_password": "Enter your new password", @@ -931,7 +928,6 @@ "keep_current_plan": "Keep my current plan", "keep_personal_projects_separate": "Keep personal projects separate", "keep_your_account_safe": "Keep your account safe", - "keep_your_account_safe_add_another_email": "Keep your account safe and make sure you don’t lose access to it by adding another email address.", "keep_your_email_updated": "Keep your email updated so that you don’t lose access to your account and data.", "keybindings": "Keybindings", "knowledge_base": "knowledge base", @@ -973,7 +969,6 @@ "ldap_create_admin_instructions": "Choose an email address for the first __appName__ admin account. This should correspond to an account in the LDAP system. You will then be asked to log in with this account.", "learn": "Learn", "learn_more": "Learn more", - "learn_more_about_account": "<0>Learn more about managing your __appName__ account.", "learn_more_about_emails": "<0>Learn more about managing your __appName__ emails.", "learn_more_about_link_sharing": "Learn more about Link Sharing", "learn_more_about_managed_users": "Learn more about Managed Users.", @@ -1867,7 +1862,6 @@ "thank_you_for_being_part_of_our_beta_program": "Thank you for being part of our Beta Program, where you can have <0>early access to new features and help us understand your needs better", "thank_you_for_being_part_of_our_labs_program": "Thank you for being part of our Labs program, where you can have <0>early access to experimental features and help us explore innovative ideas that help you work more quickly and effectively", "thanks": "Thanks", - "thanks_for_confirming_your_email_address": "Thanks for confirming your email address", "thanks_for_subscribing": "Thanks for subscribing!", "thanks_for_subscribing_you_help_sl": "Thank you for subscribing to the __planName__ plan. It’s support from people like yourself that allows __appName__ to continue to grow and improve.", "thanks_settings_updated": "Thanks, your settings have been updated.", diff --git a/services/web/locales/zh-CN.json b/services/web/locales/zh-CN.json index ecb6af70b2..3f96c2eb5c 100644 --- a/services/web/locales/zh-CN.json +++ b/services/web/locales/zh-CN.json @@ -297,6 +297,7 @@ "confirm_primary_email_change": "确认主电子邮件更改", "confirm_remove_sso_config_enter_email": "要确认您要删除 SSO 配置,请输入您的电子邮件地址:", "confirm_your_email": "确认您的电子邮件地址", + "confirmation_code_message": "我们已向__email__发送了一个6位数的验证码。请在下面输入以确认您的电子邮件地址。", "confirmation_link_broken": "抱歉,您的确认链接有问题。请尝试复制并粘贴邮件底部的链接。", "confirmation_token_invalid": "抱歉,您的确认令牌无效或已过期。请请求新的电子邮件确认链接。", "confirming": "确认", diff --git a/services/web/test/acceptance/src/AddSecondaryEmailTests.js b/services/web/test/acceptance/src/AddSecondaryEmailTests.js index b20bb027c7..526d69e724 100644 --- a/services/web/test/acceptance/src/AddSecondaryEmailTests.js +++ b/services/web/test/acceptance/src/AddSecondaryEmailTests.js @@ -46,8 +46,9 @@ describe('Add secondary email address confirmation code email', function () { spy.restore() }) - it('should send email with confirmation code', function () { + it('should redirect to confirm secondary email page', function () { expect(res.response.statusCode).to.equal(200) + expect(res.body.redir).to.equal('/user/emails/confirm-secondary') expect(confirmCode.length).to.equal(6) }) diff --git a/services/web/test/acceptance/src/PrimaryEmailCheckTests.js b/services/web/test/acceptance/src/PrimaryEmailCheckTests.js index 47a560f950..943baaa825 100644 --- a/services/web/test/acceptance/src/PrimaryEmailCheckTests.js +++ b/services/web/test/acceptance/src/PrimaryEmailCheckTests.js @@ -2,15 +2,9 @@ const UserHelper = require('./helpers/UserHelper') const Settings = require('@overleaf/settings') const { expect } = require('chai') const Features = require('../../../app/src/infrastructure/Features') -const MockV1ApiClass = require('./mocks/MockV1Api') describe('PrimaryEmailCheck', function () { let userHelper - let MockV1Api - - before(function () { - MockV1Api = MockV1ApiClass.instance() - }) beforeEach(async function () { userHelper = await UserHelper.createUser() @@ -206,84 +200,18 @@ describe('PrimaryEmailCheck', function () { await UserHelper.updateUser(userHelper.user._id, { $set: { lastPrimaryEmailCheck: new Date(time) }, }) + + checkResponse = await userHelper.fetch( + '/user/emails/primary-email-check', + { method: 'POST' } + ) }) - describe('when the user has a secondary email address', function () { - before(async function () { - if (!Features.hasFeature('saas')) { - this.skip() - } - }) - - beforeEach(async function () { - await userHelper.confirmEmail( - userHelper.user._id, - userHelper.user.email - ) - await userHelper.addEmailAndConfirm( - userHelper.user._id, - 'secondary@overleaf.com' - ) - - checkResponse = await userHelper.fetch( - '/user/emails/primary-email-check', - { method: 'POST' } - ) - }) - - it('should be redirected to the project list page', function () { - expect(checkResponse.status).to.equal(302) - expect(checkResponse.headers.get('location')).to.equal( - UserHelper.url('/project').toString() - ) - }) - }) - - describe('when the user has an institutional email and no secondary', function () { - before(async function () { - if (!Features.hasFeature('saas')) { - this.skip() - } - - if (!Features.hasFeature('saml')) { - this.skip() - } - }) - - beforeEach(async function () { - MockV1Api.createInstitution({ - name: 'Exampe Institution', - hostname: 'example.com', - licence: 'pro_plus', - confirmed: true, - }) - MockV1Api.addAffiliation(userHelper.user._id, userHelper.user.email) - - checkResponse = await userHelper.fetch( - '/user/emails/primary-email-check', - { method: 'POST' } - ) - }) - - it('should be redirected to the add secondary email page', function () { - expect(checkResponse.status).to.equal(302) - expect(checkResponse.headers.get('location')).to.equal( - UserHelper.url('/user/emails/add-secondary').toString() - ) - }) - }) - }) - - describe('when user has checked their primary email address', function () { - beforeEach(async function () { - const time = Date.now() - Settings.primary_email_check_expiration * 2 - await UserHelper.updateUser(userHelper.user._id, { - $set: { lastPrimaryEmailCheck: new Date(time) }, - }) - - await userHelper.fetch('/user/emails/primary-email-check', { - method: 'POST', - }) + it('should be redirected to the project list page', function () { + expect(checkResponse.status).to.equal(302) + expect(checkResponse.headers.get('location')).to.equal( + UserHelper.url('/project').toString() + ) }) it("shouldn't be redirected from project list to the primary email check page any longer", async function () { diff --git a/services/web/test/unit/src/User/UserEmailsControllerTests.js b/services/web/test/unit/src/User/UserEmailsControllerTests.js index 6d9c339d40..14fd99b841 100644 --- a/services/web/test/unit/src/User/UserEmailsControllerTests.js +++ b/services/web/test/unit/src/User/UserEmailsControllerTests.js @@ -301,8 +301,8 @@ describe('UserEmailsController', function () { it('sends an email confirmation', function (done) { this.UserEmailsController.addWithConfirmationCode(this.req, { - sendStatus: code => { - code.should.equal(200) + json: ({ redir }) => { + redir.should.equal('/user/emails/confirm-secondary') assertCalledWith( this.UserEmailsConfirmationHandler.promises.sendConfirmationCode, this.newEmail, diff --git a/services/web/test/unit/src/User/UserGetterTests.js b/services/web/test/unit/src/User/UserGetterTests.js index 36304b38a3..e76ffbd781 100644 --- a/services/web/test/unit/src/User/UserGetterTests.js +++ b/services/web/test/unit/src/User/UserGetterTests.js @@ -1008,45 +1008,6 @@ describe('UserGetter', function () { }) }) - describe('getUserConfirmedEmails', function () { - beforeEach(function () { - this.fakeUser = { - emails: [ - { - email: 'email1@foo.bar', - reversedHostname: 'rab.oof', - confirmedAt: new Date(), - }, - { email: 'email2@foo.bar', reversedHostname: 'rab.oof' }, - { - email: 'email3@foo.bar', - reversedHostname: 'rab.oof', - confirmedAt: new Date(), - }, - ], - } - this.UserGetter.promises.getUser = sinon.stub().resolves(this.fakeUser) - }) - - it('should get user', async function () { - const projection = { emails: 1 } - await this.UserGetter.promises.getUserConfirmedEmails(this.fakeUser._id) - - this.UserGetter.promises.getUser - .calledWith(this.fakeUser._id, projection) - .should.equal(true) - }) - - it('should return only confirmed emails', async function () { - const confirmedEmails = - await this.UserGetter.promises.getUserConfirmedEmails(this.fakeUser._id) - - expect(confirmedEmails.length).to.equal(2) - expect(confirmedEmails[0].email).to.equal('email1@foo.bar') - expect(confirmedEmails[1].email).to.equal('email3@foo.bar') - }) - }) - describe('getUserbyMainEmail', function () { it('query user by main email', function (done) { const email = 'hello@world.com'