🎨 Improved copy on too many login attempts

fixes https://github.com/TryGhost/Team/issues/2391
This commit is contained in:
Simon Backx 2023-06-20 14:31:09 +02:00
parent 49931d05e7
commit fd2ef61b3c
3 changed files with 67 additions and 60 deletions

View File

@ -58,6 +58,8 @@ export default class SigninController extends Controller.extend(ValidationEngine
return this.notifications.showAPIError(error);
}
this.signin.errors.clear();
if (error && error.payload && error.payload.errors) {
let [mainError] = error.payload.errors;
@ -66,6 +68,11 @@ export default class SigninController extends Controller.extend(ValidationEngine
this.flowErrors = (mainError.context.string || mainError.message.string);
if (mainError.type === 'TooManyRequestsError') {
// Prefer full message in this case
this.flowErrors = mainError.message.string;
}
if (mainError.type === 'PasswordResetRequiredError') {
this.passwordResetEmailSent = true;
}

View File

@ -12,68 +12,68 @@
</header>
</div>
{{else}}
<form id="login" method="post" class="gh-signin" novalidate="novalidate" {{on "submit" (perform this.validateAndAuthenticateTask)}}>
<header>
<div class="gh-site-icon" style={{site-icon-style}}></div>
<h1>Sign in to {{this.config.blogTitle}}.</h1>
</header>
<GhFormGroup @errors={{this.signin.errors}} @hasValidated={{this.hasValidated}} @property="identification">
<label for="identification">Email address</label>
<span class="gh-input-icon gh-icon-mail">
<input
id="identification"
type="email"
class="gh-input email"
placeholder="jamie@example.com"
name="identification"
autocapitalize="off"
autocorrect="off"
autocomplete="username"
value={{this.signin.identification}}
{{on "input" this.handleInput}}
{{on "blur" (fn this.validateProperty "identification")}}
/>
</span>
</GhFormGroup>
<GhFormGroup @errors={{this.signin.errors}} @hasValidated={{this.hasValidated}} @property="password">
<label for="password">Password</label>
<span class="gh-input-icon gh-icon-lock forgotten-wrap">
<input
id="password"
type="password"
class="gh-input password"
placeholder="•••••••••••••••"
name="password"
autocomplete="current-password"
autocorrect="off"
value={{this.signin.password}}
{{on "input" this.handleInput}}
/>
<form id="login" method="post" class="gh-signin" novalidate="novalidate" {{on "submit" (perform this.validateAndAuthenticateTask)}}>
<header>
<div class="gh-site-icon" style={{site-icon-style}}></div>
<h1>Sign in to {{this.config.blogTitle}}.</h1>
</header>
<GhFormGroup @errors={{this.signin.errors}} @hasValidated={{this.hasValidated}} @property="identification">
<label for="identification">Email address</label>
<span class="gh-input-icon gh-icon-mail">
<input
id="identification"
type="email"
class="gh-input email"
placeholder="jamie@example.com"
name="identification"
autocapitalize="off"
autocorrect="off"
autocomplete="username"
value={{this.signin.identification}}
{{on "input" this.handleInput}}
{{on "blur" (fn this.validateProperty "identification")}}
/>
</span>
</GhFormGroup>
<GhFormGroup @errors={{this.signin.errors}} @hasValidated={{this.hasValidated}} @property="password">
<label for="password">Password</label>
<span class="gh-input-icon gh-icon-lock forgotten-wrap">
<input
id="password"
type="password"
class="gh-input password"
placeholder="•••••••••••••••"
name="password"
autocomplete="current-password"
autocorrect="off"
value={{this.signin.password}}
{{on "input" this.handleInput}}
/>
<GhTaskButton
@task={{this.forgotPasswordTask}}
@class="forgotten-link gh-btn gh-btn-link gh-btn-icon"
@type="button"
@successClass=""
@failureClass=""
as |task|
>
<span>{{#if task.isRunning}}{{svg-jar "spinner" class="gh-spinner"}}{{else}}Forgot?{{/if}}</span>
</GhTaskButton>
</span>
</GhFormGroup>
<GhTaskButton
@task={{this.forgotPasswordTask}}
@class="forgotten-link gh-btn gh-btn-link gh-btn-icon"
@type="button"
@successClass=""
@failureClass=""
as |task|
>
<span>{{#if task.isRunning}}{{svg-jar "spinner" class="gh-spinner"}}{{else}}Forgot?{{/if}}</span>
</GhTaskButton>
</span>
</GhFormGroup>
<GhTaskButton
@buttonText="Sign in &rarr;"
@task={{this.validateAndAuthenticateTask}}
@showSuccess={{false}}
@class="login gh-btn gh-btn-login gh-btn-block gh-btn-icon"
@type="submit"
style={{accent-color-background}}
data-test-button="sign-in" />
</form>
<GhTaskButton
@buttonText="Sign in &rarr;"
@task={{this.validateAndAuthenticateTask}}
@showSuccess={{false}}
@class="login gh-btn gh-btn-login gh-btn-block gh-btn-icon"
@type="submit"
style={{accent-color-background}}
data-test-button="sign-in" />
</form>
<p class="main-error">{{if this.flowErrors this.flowErrors}}&nbsp;</p>
<p class="main-error">{{if this.flowErrors this.flowErrors}}&nbsp;</p>
{{/if}}
</section>
</div>

View File

@ -235,7 +235,7 @@ const userLogin = () => {
attachResetToRequest: true,
failCallback(req, res, next, nextValidRequestDate) {
return next(new errors.TooManyRequestsError({
message: `Too many sign-in attempts try again in ${moment(nextValidRequestDate).fromNow(true)}`,
message: `Too many login attempts. Please wait ${moment(nextValidRequestDate).fromNow(true)} before trying again, or reset your password.`,
context: tpl(messages.tooManySigninAttempts.context),
help: tpl(messages.tooManySigninAttempts.context)
}));