Separate error page when the recovery link was already used
This commit is contained in:
@@ -77,7 +77,13 @@ pub(crate) async fn get(
|
||||
.await?
|
||||
.context("Unknown session")?;
|
||||
|
||||
if !ticket.active(clock.now()) || session.consumed_at.is_some() {
|
||||
if session.consumed_at.is_some() {
|
||||
let context = EmptyContext.with_language(locale);
|
||||
let rendered = templates.render_recovery_consumed(&context)?;
|
||||
return Ok((cookie_jar, Html(rendered)).into_response());
|
||||
}
|
||||
|
||||
if !ticket.active(clock.now()) {
|
||||
let context = RecoveryExpiredContext::new(session)
|
||||
.with_csrf(csrf_token.form_value())
|
||||
.with_language(locale);
|
||||
@@ -118,6 +124,7 @@ pub(crate) async fn get(
|
||||
Ok((cookie_jar, Html(rendered)).into_response())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub(crate) async fn post(
|
||||
mut rng: BoxRng,
|
||||
clock: BoxClock,
|
||||
@@ -152,7 +159,13 @@ pub(crate) async fn post(
|
||||
.await?
|
||||
.context("Unknown session")?;
|
||||
|
||||
if !ticket.active(clock.now()) || session.consumed_at.is_some() {
|
||||
if session.consumed_at.is_some() {
|
||||
let context = EmptyContext.with_language(locale);
|
||||
let rendered = templates.render_recovery_consumed(&context)?;
|
||||
return Ok((cookie_jar, Html(rendered)).into_response());
|
||||
}
|
||||
|
||||
if !ticket.active(clock.now()) {
|
||||
let context = RecoveryExpiredContext::new(session)
|
||||
.with_csrf(csrf_token.form_value())
|
||||
.with_language(locale);
|
||||
|
||||
@@ -68,6 +68,12 @@ pub(crate) async fn get(
|
||||
.into_response());
|
||||
};
|
||||
|
||||
if recovery_session.consumed_at.is_some() {
|
||||
let context = EmptyContext.with_language(locale);
|
||||
let rendered = templates.render_recovery_consumed(&context)?;
|
||||
return Ok((cookie_jar, Html(rendered)).into_response());
|
||||
}
|
||||
|
||||
let context = RecoveryProgressContext::new(recovery_session)
|
||||
.with_csrf(csrf_token.form_value())
|
||||
.with_language(locale);
|
||||
@@ -115,6 +121,12 @@ pub(crate) async fn post(
|
||||
.into_response());
|
||||
};
|
||||
|
||||
if recovery_session.consumed_at.is_some() {
|
||||
let context = EmptyContext.with_language(locale);
|
||||
let rendered = templates.render_recovery_consumed(&context)?;
|
||||
return Ok((cookie_jar, Html(rendered)).into_response());
|
||||
}
|
||||
|
||||
// Verify the CSRF token
|
||||
let () = cookie_jar.verify_form(&clock, form)?;
|
||||
|
||||
|
||||
@@ -360,6 +360,9 @@ register_templates! {
|
||||
/// Render the account recovery link expired page
|
||||
pub fn render_recovery_expired(WithLanguage<WithCsrf<RecoveryExpiredContext>>) { "pages/recovery/expired.html" }
|
||||
|
||||
/// Render the account recovery link consumed page
|
||||
pub fn render_recovery_consumed(WithLanguage<EmptyContext>) { "pages/recovery/consumed.html" }
|
||||
|
||||
/// Render the account recovery disabled page
|
||||
pub fn render_recovery_disabled(WithLanguage<EmptyContext>) { "pages/recovery/disabled.html" }
|
||||
|
||||
@@ -432,6 +435,7 @@ impl Templates {
|
||||
check::render_recovery_progress(self, now, rng)?;
|
||||
check::render_recovery_finish(self, now, rng)?;
|
||||
check::render_recovery_expired(self, now, rng)?;
|
||||
check::render_recovery_consumed(self, now, rng)?;
|
||||
check::render_recovery_disabled(self, now, rng)?;
|
||||
check::render_reauth(self, now, rng)?;
|
||||
check::render_form_post::<EmptyContext>(self, now, rng)?;
|
||||
|
||||
32
templates/pages/recovery/consumed.html
Normal file
32
templates/pages/recovery/consumed.html
Normal file
@@ -0,0 +1,32 @@
|
||||
{#
|
||||
Copyright 2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.error() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.recovery.consumed.heading") }}</h1>
|
||||
<p class="text">{{ _("mas.recovery.consumed.description") }}</p>
|
||||
</div>
|
||||
|
||||
{{ button.link_outline(text=_("action.start_over"), href="/login") }}
|
||||
</header>
|
||||
{% endblock content %}
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"start_over": "Start over",
|
||||
"@start_over": {
|
||||
"context": "pages/recovery/expired.html:38:32-54"
|
||||
"context": "pages/recovery/consumed.html:30:32-54, pages/recovery/expired.html:38:32-54"
|
||||
}
|
||||
},
|
||||
"app": {
|
||||
@@ -389,6 +389,18 @@
|
||||
}
|
||||
},
|
||||
"recovery": {
|
||||
"consumed": {
|
||||
"description": "To create a new password, start over and select “Forgot password”.",
|
||||
"@description": {
|
||||
"context": "pages/recovery/consumed.html:27:25-63",
|
||||
"description": "Description on the error page shown when a user tries to use a recovery link that has already been used"
|
||||
},
|
||||
"heading": "The link to reset your password has already been used",
|
||||
"@heading": {
|
||||
"context": "pages/recovery/consumed.html:26:27-61",
|
||||
"description": "Title on the error page shown when a user tries to use a recovery link that has already been used"
|
||||
}
|
||||
},
|
||||
"disabled": {
|
||||
"description": "If you have lost your credentials, please contact the administrator to recover your account.",
|
||||
"@description": {
|
||||
|
||||
Reference in New Issue
Block a user