mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-06-01 21:31:36 +02:00
[web] Create CIAM versions of the password reset screens (#30087)
* Make CIAM copies of Pug files
passwordResetCiam.pug
setPasswordCiam.pug
* Update controller with split test assignment
* Use CIAM layout in passwordResetCiam.pug
* Style passwordResetCiam according to designs
* Use CIAM layout in setPasswordCiam.pug
* Style setPasswordCiam according to designs
* Use settings value in registration screen for must_be_at_least_n_characters
* Retrieve email input with a script
* Replace mb-4 by --ds-spacing-800
* Add eye icon to toggle password visibility
* Avoid double dots after some translated strings
* Use `ciamCustomFormDangerMessage`
* Use `ciamErrorNotification`
* Use `ciamButtonContentLoading`
* Replace remaining "mb" classes
* Move new password errors to the top of the form
* Fix CIAM mixins path after rebase
* Use `ciamCustomFormDangerMessage`
* Add `data-ol-spinner-inflight` to buttons
* Replace classname ciam-notification by notification-ds
Remove borders from CIAM notifications
Fix font size
* Revert "Use settings value in registration screen for must_be_at_least_n_characters"
This reverts commit a0af95c11e171097750ad7ee871f6baf89d5c0cb.
(It's Friday afternoon so I don't want to update unrelated stuff :D)
* Update: check_your_inbox
* Remove `.ciam-card` min-height.
Unnecessary thanks to `.confirm-email-success-form`'s min-height: 400px;
* Use phosphor icons
* Style `formMessagesNewStyle` with DS notifications within CIAM pages
Alternatively, we could extend/duplicate `showMessagesNewStyle` with a CIAM variant
* Revert "Style `formMessagesNewStyle` with DS notifications within CIAM pages"
This reverts commit ed382dc1e8cdf5b916c1527f4da0a825167e9675.
* Fix styling of dynamically-created DS notifications
* Set password length info to secondary color
* Move `ciamSamlErrorNotLoggedIn` to saas-authentication module
Prevents errors in CE:
Error: ENOENT: no such file or directory, open '/overleaf/services/web/modules/saas-authentication/app/views/_mixins.pug'
at /overleaf/services/web/app/views/_mixins/ciam_mixins.pug line 3
---------
Co-authored-by: Tim Down <158919+timdown@users.noreply.github.com>
GitOrigin-RevId: afe58f18ecee92460ab628a285b6edb48a5c678d
This commit is contained in:
@@ -9,6 +9,7 @@ import OError from '@overleaf/o-error'
|
||||
import EmailsHelper from '../Helpers/EmailHelper.mjs'
|
||||
import { expressify } from '@overleaf/promise-utils'
|
||||
import { z, validateReq } from '../../infrastructure/Validation.mjs'
|
||||
import SplitTestHandler from '../SplitTests/SplitTestHandler.mjs'
|
||||
|
||||
const setNewUserPasswordSchema = z.object({
|
||||
body: z.object({
|
||||
@@ -186,16 +187,20 @@ async function renderSetPasswordForm(req, res, next) {
|
||||
return res.redirect('/user/password/reset?error=token_expired')
|
||||
}
|
||||
req.session.resetToken = query.passwordResetToken
|
||||
let emailQuery = ''
|
||||
|
||||
const params = new URLSearchParams()
|
||||
if (typeof query.email === 'string') {
|
||||
const email = EmailsHelper.parseEmail(query.email)
|
||||
if (email) {
|
||||
emailQuery = `?email=${encodeURIComponent(email)}`
|
||||
params.append('email', email)
|
||||
}
|
||||
}
|
||||
|
||||
return res.redirect('/user/password/set' + emailQuery)
|
||||
if (req.query.uniaccessphase1) {
|
||||
// Preserve uniaccessphase1 flag in the redirect so it can be tested
|
||||
params.append('uniaccessphase1', req.query.uniaccessphase1)
|
||||
}
|
||||
const queryString = params.toString() ? `?${params.toString()}` : ''
|
||||
return res.redirect('/user/password/set' + queryString)
|
||||
} catch (err) {
|
||||
if (err.name === 'ForbiddenError') {
|
||||
return next(err)
|
||||
@@ -214,11 +219,22 @@ async function renderSetPasswordForm(req, res, next) {
|
||||
const passwordResetToken = req.session.resetToken
|
||||
delete req.session.resetToken
|
||||
|
||||
res.render('user/setPassword', {
|
||||
title: 'set_password',
|
||||
email,
|
||||
passwordResetToken,
|
||||
})
|
||||
const ciamAssignment = await SplitTestHandler.promises.getAssignment(
|
||||
req,
|
||||
res,
|
||||
'uniaccessphase1'
|
||||
)
|
||||
|
||||
res.render(
|
||||
ciamAssignment.variant === 'enabled'
|
||||
? 'user/setPasswordCiam'
|
||||
: 'user/setPassword',
|
||||
{
|
||||
title: 'set_password',
|
||||
email,
|
||||
passwordResetToken,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const renderRequestResetFormSchema = z.object({
|
||||
@@ -235,10 +251,21 @@ async function renderRequestResetForm(req, res) {
|
||||
error = 'password_reset_token_expired'
|
||||
}
|
||||
|
||||
res.render('user/passwordReset', {
|
||||
title: 'reset_password',
|
||||
error,
|
||||
})
|
||||
const ciamAssignment = await SplitTestHandler.promises.getAssignment(
|
||||
req,
|
||||
res,
|
||||
'uniaccessphase1'
|
||||
)
|
||||
|
||||
res.render(
|
||||
ciamAssignment.variant === 'enabled'
|
||||
? 'user/passwordResetCiam'
|
||||
: 'user/passwordReset',
|
||||
{
|
||||
title: 'reset_password',
|
||||
error,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
include terms_of_service
|
||||
include recaptcha
|
||||
include ../../../modules/saas-authentication/app/views/_mixins
|
||||
|
||||
mixin ciamLogo
|
||||
header.ciam-logo
|
||||
@@ -10,7 +9,7 @@ mixin ciamLogo
|
||||
mixin ciamCardSeparator
|
||||
hr.ciam-card-separator
|
||||
|
||||
mixin ciamCardFooter
|
||||
mixin ciamCardFooter(short)
|
||||
section.ciam-card-footer
|
||||
+ciamCardSeparator
|
||||
.ciam-footer-ds-logo
|
||||
@@ -24,7 +23,10 @@ mixin ciamCardFooter
|
||||
alt='Digital Science — home'
|
||||
)
|
||||
p
|
||||
| !{translate('advancing_research_with', null, [{ name: 'a', attrs: { href: 'https://www.overleaf.com/', target: '_blank', rel: 'noopener noreferrer' }}, { name: 'a', attrs: { href: 'https://www.papersapp.com/', target: '_blank', rel: 'noopener noreferrer' }}])}
|
||||
if short
|
||||
| !{translate('overleaf_is_a_ds_product')}
|
||||
else
|
||||
| !{translate('advancing_research_with', null, [{ name: 'a', attrs: { href: 'https://www.overleaf.com/', target: '_blank', rel: 'noopener noreferrer' }}, { name: 'a', attrs: { href: 'https://www.papersapp.com/', target: '_blank', rel: 'noopener noreferrer' }}])}
|
||||
|
||||
mixin ciamTermsOfServiceAgreement
|
||||
p
|
||||
@@ -36,7 +38,7 @@ mixin ciamRecaptchaConditions
|
||||
|
||||
mixin ciamCustomFormDangerMessage(key)
|
||||
div(
|
||||
class='notification ciam-notification notification-type-error'
|
||||
class='notification notification-ds notification-type-error'
|
||||
hidden
|
||||
data-ol-custom-form-message=key
|
||||
role='alert'
|
||||
@@ -47,10 +49,6 @@ mixin ciamCustomFormDangerMessage(key)
|
||||
.notification-content.text-left
|
||||
block
|
||||
|
||||
mixin ciamSamlErrorNotLoggedIn(error)
|
||||
+samlErrorNotLoggedIn(error)
|
||||
ph-warning-circle(aria-hidden='true')
|
||||
|
||||
mixin ciamFooter
|
||||
footer
|
||||
.footer-links
|
||||
|
||||
98
services/web/app/views/user/passwordResetCiam.pug
Normal file
98
services/web/app/views/user/passwordResetCiam.pug
Normal file
@@ -0,0 +1,98 @@
|
||||
extends ../layout-website-redesign
|
||||
include ../_mixins/recaptcha
|
||||
include ../_mixins/notification
|
||||
include ../_mixins/ciam_mixins
|
||||
|
||||
block vars
|
||||
- var suppressNavbar = true
|
||||
- var suppressFooter = true
|
||||
- var suppressSkipToContent = true
|
||||
- isWebsiteRedesign = true
|
||||
|
||||
block content
|
||||
- var showCaptcha = settings.recaptcha && settings.recaptcha.siteKey && !(settings.recaptcha.disabled && settings.recaptcha.disabled.passwordReset)
|
||||
|
||||
if showCaptcha
|
||||
script(
|
||||
type='text/javascript'
|
||||
nonce=scriptNonce
|
||||
src='https://www.recaptcha.net/recaptcha/api.js?render=explicit'
|
||||
)
|
||||
div(
|
||||
id='recaptcha'
|
||||
class='g-recaptcha'
|
||||
data-sitekey=settings.recaptcha.siteKey
|
||||
data-size='invisible'
|
||||
data-badge='inline'
|
||||
)
|
||||
|
||||
.ciam-enabled.ciam-layout.ciam-password-reset(
|
||||
data-ol-captcha-retry-trigger-area=''
|
||||
)
|
||||
+ciamLogo
|
||||
.ciam-container
|
||||
main#main-content.ciam-card
|
||||
form(
|
||||
name='passwordResetForm'
|
||||
captcha-action-name=showCaptcha ? 'passwordReset' : false
|
||||
data-ciam-form
|
||||
data-ol-async-form
|
||||
action='/user/password/reset'
|
||||
method='POST'
|
||||
captcha=showCaptcha ? '' : false
|
||||
)
|
||||
if error === 'password_reset_token_expired'
|
||||
h1 #{translate("sorry_your_token_expired")}
|
||||
p.intro-p #{translate('please_request_a_new_password_reset_email_and_follow_the_link')}.
|
||||
else
|
||||
h1(data-ol-not-sent) #{translate("reset_your_password")}
|
||||
h1(hidden data-ol-sent) #{translate("check_your_inbox")}
|
||||
p.intro-p(data-ol-not-sent) #{translate("enter_your_email_and_we_will_send_reset_instructions")}
|
||||
|
||||
div(data-ol-not-sent)
|
||||
+formMessagesNewStyle
|
||||
if error && error !== 'password_reset_token_expired'
|
||||
+ciamErrorNotification
|
||||
p #{translate(error)}
|
||||
|
||||
div(data-ol-custom-form-message='no-password-allowed-due-to-sso' hidden)
|
||||
+ciamErrorNotification
|
||||
p !{translate('you_cant_reset_password_due_to_sso', {}, [{name: 'a', attrs: {href: '/sso-login'}}])}
|
||||
input(name='_csrf' type='hidden' value=csrfToken)
|
||||
.form-group.form-group-ds
|
||||
label.form-label(for='email') #{translate("email")}
|
||||
input#email.form-control.form-control-ds.form-control-lg(
|
||||
name='email'
|
||||
type='email'
|
||||
required
|
||||
autocomplete='username'
|
||||
autofocus
|
||||
)
|
||||
.actions
|
||||
button.btn.btn-ds.btn-lg.btn-primary.w-100(
|
||||
type='submit'
|
||||
data-ol-disabled-inflight
|
||||
data-ol-spinner-inflight
|
||||
aria-label=translate('send_reset_link')
|
||||
)
|
||||
+ciamButtonContentLoading(`${translate('requesting_password_reset')}…`)= translate('send_reset_link')
|
||||
p.ciam-login-text
|
||||
a(href='/login') #{translate("back_to_log_in")}
|
||||
div(hidden data-ol-sent)
|
||||
p.intro-p !{translate('if_theres_an_account_youll_get_reset_email', {email: '<span id="sent-email-display">your email</span>'})}
|
||||
p.ciam-login-text.text-start
|
||||
a(href='/login') #{translate('back_to_log_in')}
|
||||
|
||||
if showCaptcha
|
||||
.ciam-disclaimers
|
||||
+ciamRecaptchaConditions
|
||||
|
||||
+ciamCardFooter(true)
|
||||
|
||||
// retrieve and display the email used for password reset after form is sent
|
||||
script(nonce=scriptNonce).
|
||||
document.querySelector('form[name="passwordResetForm"]').addEventListener('sent', function () {
|
||||
const email = this.querySelector('input[name="email"]').value
|
||||
const display = document.getElementById('sent-email-display')
|
||||
if (display) display.textContent = email
|
||||
})
|
||||
@@ -28,11 +28,11 @@ block content
|
||||
+formMessagesNewStyle
|
||||
|
||||
+customFormMessageNewStyle('password-contains-email', 'danger')
|
||||
| #{translate('invalid_password_contains_email')}.
|
||||
| #{translate('invalid_password_contains_email')}
|
||||
| #{translate('use_a_different_password')}.
|
||||
|
||||
+customFormMessageNewStyle('password-too-similar', 'danger')
|
||||
| #{translate('invalid_password_too_similar')}.
|
||||
| #{translate('invalid_password_too_similar')}
|
||||
| #{translate('use_a_different_password')}.
|
||||
|
||||
+customFormMessageNewStyle('token-expired', 'danger')
|
||||
@@ -65,7 +65,7 @@ block content
|
||||
| #{translate('password_cant_be_the_same_as_current_one')}.
|
||||
|
||||
+customValidationMessageNewStyle('password-must-be-strong')
|
||||
| !{translate('password_was_detected_on_a_public_list_of_known_compromised_passwords', {}, [{name: 'a', attrs: {href: 'https://haveibeenpwned.com/passwords', rel: 'noopener noreferrer', target: '_blank'}}])}.
|
||||
| !{translate('password_was_detected_on_a_public_list_of_known_compromised_passwords', {}, [{name: 'a', attrs: {href: 'https://haveibeenpwned.com/passwords', rel: 'noopener noreferrer', target: '_blank'}}])}
|
||||
| #{translate('use_a_different_password')}.
|
||||
|
||||
input(name='passwordResetToken' type='hidden' value=passwordResetToken)
|
||||
|
||||
110
services/web/app/views/user/setPasswordCiam.pug
Normal file
110
services/web/app/views/user/setPasswordCiam.pug
Normal file
@@ -0,0 +1,110 @@
|
||||
extends ../layout-website-redesign
|
||||
include ../_mixins/ciam_mixins
|
||||
|
||||
block vars
|
||||
- var suppressNavbar = true
|
||||
- var suppressFooter = true
|
||||
- var suppressSkipToContent = true
|
||||
- isWebsiteRedesign = true
|
||||
|
||||
block content
|
||||
.ciam-enabled.ciam-layout.ciam-password-set
|
||||
+ciamLogo
|
||||
.ciam-container
|
||||
main#main-content.ciam-card
|
||||
form(
|
||||
name='passwordResetForm'
|
||||
data-ciam-form
|
||||
data-ol-async-form
|
||||
action='/user/password/set'
|
||||
method='POST'
|
||||
data-ol-hide-on-error='token-expired'
|
||||
)
|
||||
div(hidden data-ol-sent)
|
||||
h1 #{translate("your_password_has_been_reset")}
|
||||
p.intro-p #{translate("you_can_now_sign_in_with_new_password")}.
|
||||
a.btn.btn-ds.btn-lg.btn-primary.w-100(href='/login') #{translate("go_to_sign_in")}
|
||||
|
||||
div(data-ol-not-sent)
|
||||
h1 #{translate("choose_a_new_password")}
|
||||
+formMessagesNewStyle
|
||||
|
||||
+ciamCustomFormDangerMessage('password-contains-email')
|
||||
| #{translate('invalid_password_contains_email')}
|
||||
| #{translate('use_a_different_password')}.
|
||||
|
||||
+ciamCustomFormDangerMessage('password-too-similar')
|
||||
| #{translate('invalid_password_too_similar')}
|
||||
| #{translate('use_a_different_password')}.
|
||||
|
||||
+ciamCustomFormDangerMessage('token-expired')
|
||||
| #{translate('password_reset_token_expired')}
|
||||
br
|
||||
a(href='/user/password/reset')
|
||||
| #{translate('request_new_password_reset_email')}
|
||||
|
||||
+ciamCustomFormDangerMessage('invalid-password')
|
||||
| #{translate('invalid_password')}.
|
||||
|
||||
+ciamCustomFormDangerMessage('password-must-be-different')
|
||||
| #{translate('password_cant_be_the_same_as_current_one')}.
|
||||
|
||||
+ciamCustomFormDangerMessage('password-must-be-strong')
|
||||
| !{translate('password_was_detected_on_a_public_list_of_known_compromised_passwords', {}, [{name: 'a', attrs: {href: 'https://haveibeenpwned.com/passwords', rel: 'noopener noreferrer', target: '_blank'}}])}
|
||||
| #{translate('use_a_different_password')}.
|
||||
|
||||
input(name='_csrf' type='hidden' value=csrfToken)
|
||||
input(
|
||||
name='email'
|
||||
type='text'
|
||||
hidden
|
||||
autocomplete='username'
|
||||
value=email
|
||||
)
|
||||
|
||||
.form-group.form-group-ds
|
||||
label.form-label(
|
||||
for='passwordField'
|
||||
data-ol-hide-on-error-message='token-expired'
|
||||
) #{translate("password")}
|
||||
.form-group-password
|
||||
.form-group-password-input
|
||||
.form-complex-input-container
|
||||
input#passwordField.form-control.form-control-ds.form-control-lg(
|
||||
name='password'
|
||||
type='password'
|
||||
autocomplete='new-password'
|
||||
autofocus
|
||||
required
|
||||
minlength=settings.passwordStrengthOptions.length.min
|
||||
data-ol-password-visibility-target
|
||||
)
|
||||
button.visibility-toggle(
|
||||
type='button'
|
||||
data-ol-password-visibility-toggle='visibilityOn'
|
||||
aria-controls='password'
|
||||
aria-label=translate('turn_on_password_visibility')
|
||||
)
|
||||
ph-eye.form-input-icon-ds
|
||||
button.visibility-toggle(
|
||||
type='button'
|
||||
data-ol-password-visibility-toggle='visibilityOff'
|
||||
aria-controls='password'
|
||||
aria-label=translate('turn_off_password_visibility')
|
||||
hidden
|
||||
)
|
||||
ph-eye-slash.form-input-icon-ds
|
||||
|
||||
input(name='passwordResetToken' type='hidden' value=passwordResetToken)
|
||||
div(data-ol-hide-on-error-message='token-expired')
|
||||
p.password-policy #{translate('must_be_at_least_n_characters', {n: settings.passwordStrengthOptions.length.min})}
|
||||
.actions
|
||||
button.btn.btn-ds.btn-lg.btn-primary.w-100(
|
||||
type='submit'
|
||||
data-ol-disabled-inflight
|
||||
data-ol-spinner-inflight
|
||||
aria-label=translate('save_new_password')
|
||||
)
|
||||
+ciamButtonContentLoading(`${translate('processing')}…`)= translate('save_new_password')
|
||||
|
||||
+ciamCardFooter(true)
|
||||
@@ -304,6 +304,8 @@ function showMessagesNewStyle(
|
||||
el.hidden = true
|
||||
})
|
||||
|
||||
const isDsBranded = formEl.dataset.ciamForm !== undefined
|
||||
|
||||
// Render messages
|
||||
messageBag.forEach(message => {
|
||||
const customErrorElements = message.key
|
||||
@@ -322,6 +324,7 @@ function showMessagesNewStyle(
|
||||
messageElContainer.className = classNames('notification', {
|
||||
'notification-type-error': message.type === 'error',
|
||||
'notification-type-success': message.type !== 'error',
|
||||
'notification-ds': isDsBranded,
|
||||
})
|
||||
const messageEl = document.createElement('div')
|
||||
|
||||
@@ -344,7 +347,6 @@ function showMessagesNewStyle(
|
||||
}
|
||||
|
||||
// create the left icon
|
||||
const isDsBranded = formEl.dataset.ciamForm !== undefined
|
||||
const messageIcon = document.createElement('div')
|
||||
messageIcon.className = 'notification-icon'
|
||||
if (
|
||||
|
||||
@@ -177,16 +177,16 @@ function PasswordForm() {
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
. {t('use_a_different_password')}.
|
||||
{t('use_a_different_password')}.
|
||||
</>
|
||||
) : getErrorMessageKey(error) === 'password-contains-email' ? (
|
||||
<>
|
||||
{t('invalid_password_contains_email')}.{' '}
|
||||
{t('invalid_password_contains_email')}{' '}
|
||||
{t('use_a_different_password')}.
|
||||
</>
|
||||
) : getErrorMessageKey(error) === 'password-too-similar' ? (
|
||||
<>
|
||||
{t('invalid_password_too_similar')}.{' '}
|
||||
{t('invalid_password_too_similar')}{' '}
|
||||
{t('use_a_different_password')}.
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
@import 'ciam-layout';
|
||||
@import 'ciam-links';
|
||||
@import 'ciam-login';
|
||||
@import 'ciam-password-reset';
|
||||
@import 'ciam-register';
|
||||
@import 'ciam-six-digits';
|
||||
@import 'ciam-try-premium';
|
||||
|
||||
@@ -108,7 +108,6 @@
|
||||
border-radius: var(--ds-border-radius-400);
|
||||
max-width: 464px;
|
||||
margin: 0 auto;
|
||||
min-height: 500px;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
padding: var(--ds-spacing-1300);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
.ciam-password-set,
|
||||
.ciam-password-reset {
|
||||
h1 {
|
||||
margin-bottom: var(--ds-spacing-600);
|
||||
}
|
||||
|
||||
p.intro-p {
|
||||
margin-bottom: var(--ds-spacing-800);
|
||||
}
|
||||
|
||||
.notification {
|
||||
margin-bottom: var(--ds-spacing-800);
|
||||
}
|
||||
|
||||
.password-policy {
|
||||
color: var(--ds-color-text-secondary);
|
||||
}
|
||||
|
||||
.form-group-ds {
|
||||
margin-bottom: var(--ds-spacing-400);
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--ds-spacing-400);
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,9 @@
|
||||
flex-direction: column;
|
||||
|
||||
.form-group-password-input {
|
||||
input.form-control {
|
||||
input.form-control,
|
||||
// needlessly specific selectors to override competing styles
|
||||
input.form-control.form-control-ds.form-control-lg {
|
||||
padding-right: var(--password-visibility-toggle-width);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,10 +330,12 @@
|
||||
"chat_error": "Could not load chat messages, please try again.",
|
||||
"chat_with_sales_team_50_or_more": "Chat with our sales team about larger discounts for groups of 50 or more.",
|
||||
"check_your_email": "Check your email",
|
||||
"check_your_inbox": "Check your inbox",
|
||||
"checking": "Checking",
|
||||
"checking_dropbox_status": "Checking Dropbox status",
|
||||
"checking_project_github_status": "Checking project status in GitHub",
|
||||
"choose_a_custom_color": "Choose a custom color",
|
||||
"choose_a_new_password": "Choose a new password",
|
||||
"choose_from_group_members": "Choose from group members",
|
||||
"choose_how_you_search_your_references": "Choose how you search your references",
|
||||
"choose_which_experiments": "Choose which experiments you’d like to try.",
|
||||
@@ -720,6 +722,7 @@
|
||||
"enter_the_number_of_licenses_youd_like_to_add_to_see_the_cost_breakdown": "Enter the number of licenses you’d like to add to see the cost breakdown.",
|
||||
"enter_your_email": "Enter your email",
|
||||
"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_email_and_we_will_send_reset_instructions": "Enter your email and we’ll send reset instructions.",
|
||||
"enter_your_password": "Enter your password",
|
||||
"equation_generator": "Equation Generator",
|
||||
"equation_preview": "Equation preview",
|
||||
@@ -953,6 +956,7 @@
|
||||
"go_to_pdf_location_in_code": "Go to PDF location in code (Tip: double click on the PDF for best results)",
|
||||
"go_to_previous_page": "Go to previous page",
|
||||
"go_to_settings": "Go to settings",
|
||||
"go_to_sign_in": "Go to sign in",
|
||||
"go_to_subscriptions": "Go to Subscriptions",
|
||||
"go_to_writefull": "Go to Writefull",
|
||||
"good_news_you_already_purchased_this_add_on": "Good news! You already have this add-on, so no need to pay again.",
|
||||
@@ -1058,6 +1062,7 @@
|
||||
"id": "ID",
|
||||
"if_have_existing_can_link": "If you have an existing <b>__appName__</b> account on another email, you can link it to your <b>__institutionName__</b> account by clicking <b>__clickText__</b>.",
|
||||
"if_owner_can_link": "If you own the <b>__appName__</b> account with <b>__email__</b>, you will be allowed to link it to your <b>__institutionName__</b> institutional account.",
|
||||
"if_theres_an_account_youll_get_reset_email": "If there’s an account for __email__, you’ll get an email with reset instructions.",
|
||||
"if_you_find_any_issues_with_texlive": "If you find any issues with TeX Live, packages, or compilation, please <0>provide feedback</0>. If you hit problems, you can <1>switch your compiler</1>.",
|
||||
"if_you_need_to_customize_your_table_further_you_can": "If you need to customize your table further, you can. Using LaTeX code, you can change anything from table styles and border styles to colors and column widths. <0>Read our guide</0> to using tables in LaTeX to help you get started.",
|
||||
"if_you_need_to_delete_your_writefull_account": "If you need to delete your Writefull account, go to your <a>Writefull account settings.</a>",
|
||||
@@ -1597,6 +1602,7 @@
|
||||
"overleaf_group_plans": "Overleaf group plans",
|
||||
"overleaf_history_system": "Overleaf History System",
|
||||
"overleaf_individual_plans": "Overleaf individual plans",
|
||||
"overleaf_is_a_ds_product": "Overleaf is a Digital Science product.",
|
||||
"overleaf_is_easy_to_use": "Overleaf is easy to use.",
|
||||
"overleaf_labs": "Overleaf Labs",
|
||||
"overleaf_logo": "Overleaf logo",
|
||||
@@ -2003,6 +2009,7 @@
|
||||
"saml_response": "SAML Response",
|
||||
"save": "Save",
|
||||
"save_20_percent": "save 20%",
|
||||
"save_new_password": "Save new password",
|
||||
"save_or_cancel-cancel": "Cancel",
|
||||
"save_or_cancel-or": "or",
|
||||
"save_or_cancel-save": "Save",
|
||||
@@ -2083,6 +2090,7 @@
|
||||
"send_first_message": "Send your first message to your collaborators",
|
||||
"send_message": "Send message",
|
||||
"send_request": "Send request",
|
||||
"send_reset_link": "Send reset link",
|
||||
"send_test_email": "Send a test email",
|
||||
"sending": "Sending",
|
||||
"sent": "Sent",
|
||||
@@ -2801,6 +2809,7 @@
|
||||
"you_can_now_enable_sso": "You can now enable SSO on your group settings page.",
|
||||
"you_can_now_log_in_sso": "You can now log in through your institution and if eligible you will receive <0>__appName__ Professional features</0>.",
|
||||
"you_can_now_search_and_add_references_from_your_rm_library_without_needing_to_import_files": "You can now search and add references from your __referenceManager__ library without needing to import files—just type <code>\\cite{}</code> in your .tex file. <a>Learn more</a>",
|
||||
"you_can_now_sign_in_with_new_password": "You can now sign in with your new password.",
|
||||
"you_can_opt_in_and_out_of_the_program_at_any_time_on_this_page": "You can <0>opt in and out</0> of the program at any time on this page",
|
||||
"you_can_request_a_maximum_of_limit_fixes_per_day": "You can request a maximum of __limit__ fixes per day. Please try again tomorrow.",
|
||||
"you_can_select_or_invite_collaborator": "You can select or invite __count__ collaborator on your current plan. Upgrade to add more editors or reviewers.",
|
||||
@@ -2853,6 +2862,7 @@
|
||||
"your_message_to_collaborators": "Send a message to your collaborators",
|
||||
"your_name_and_email_address_will_be_visible_to_the_project_owner_and_other_editors": "Your name and email address will be visible to the project owner and other editors.",
|
||||
"your_new_plan": "Your new plan",
|
||||
"your_password_has_been_reset": "Your password has been reset",
|
||||
"your_password_has_been_successfully_changed": "Your password has been successfully changed",
|
||||
"your_password_was_detected": "Your password is on a <0>public list of known compromised passwords</0>. Keep your account safe by changing your password now.",
|
||||
"your_plan": "Your plan",
|
||||
|
||||
@@ -57,6 +57,11 @@ describe('PasswordResetController', function () {
|
||||
removeReconfirmFlag: sinon.stub().resolves(),
|
||||
},
|
||||
}
|
||||
ctx.SplitTestHandler = {
|
||||
promises: {
|
||||
getAssignment: sinon.stub().resolves({ variant: 'default' }),
|
||||
},
|
||||
}
|
||||
|
||||
vi.doMock('@overleaf/settings', () => ({
|
||||
default: ctx.settings,
|
||||
@@ -105,6 +110,13 @@ describe('PasswordResetController', function () {
|
||||
default: ctx.UserUpdater,
|
||||
}))
|
||||
|
||||
vi.doMock(
|
||||
'../../../../app/src/Features/SplitTests/SplitTestHandler',
|
||||
() => ({
|
||||
default: ctx.SplitTestHandler,
|
||||
})
|
||||
)
|
||||
|
||||
ctx.PasswordResetController = (await import(MODULE_PATH)).default
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user