1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-08-07 17:03:01 +03:00

Show a proper 'link expired' page

This commit is contained in:
Quentin Gliech
2024-06-26 15:27:19 +02:00
parent f9f2f4a3be
commit 96df94104e
6 changed files with 117 additions and 24 deletions

View File

@@ -28,8 +28,8 @@ use mas_policy::Policy;
use mas_router::UrlBuilder;
use mas_storage::{BoxClock, BoxRepository, BoxRng};
use mas_templates::{
EmptyContext, ErrorContext, FieldError, FormState, RecoveryFinishContext,
RecoveryFinishFormField, TemplateContext, Templates,
EmptyContext, ErrorContext, FieldError, FormState, RecoveryExpiredContext,
RecoveryFinishContext, RecoveryFinishFormField, TemplateContext, Templates,
};
use serde::{Deserialize, Serialize};
use zeroize::Zeroizing;
@@ -78,12 +78,10 @@ pub(crate) async fn get(
.context("Unknown session")?;
if !ticket.active(clock.now()) || session.consumed_at.is_some() {
// TODO: render a 'link expired' page
let rendered = templates.render_error(
&ErrorContext::new()
.with_code("Link expired")
.with_language(&locale),
)?;
let context = RecoveryExpiredContext::new(session)
.with_csrf(csrf_token.form_value())
.with_language(locale);
let rendered = templates.render_recovery_expired(&context)?;
return Ok((cookie_jar, Html(rendered)).into_response());
}
@@ -155,12 +153,10 @@ pub(crate) async fn post(
.context("Unknown session")?;
if !ticket.active(clock.now()) || session.consumed_at.is_some() {
// TODO: render a 'link expired' page
let rendered = templates.render_error(
&ErrorContext::new()
.with_code("Link expired")
.with_language(&locale),
)?;
let context = RecoveryExpiredContext::new(session)
.with_csrf(csrf_token.form_value())
.with_language(locale);
let rendered = templates.render_recovery_expired(&context)?;
return Ok((cookie_jar, Html(rendered)).into_response());
}

View File

@@ -1056,6 +1056,39 @@ impl TemplateContext for RecoveryProgressContext {
}
}
/// Context used by the `pages/recovery/expired.html` template
#[derive(Serialize)]
pub struct RecoveryExpiredContext {
session: UserRecoverySession,
}
impl RecoveryExpiredContext {
/// Constructs a context for the recovery expired page
#[must_use]
pub fn new(session: UserRecoverySession) -> Self {
Self { session }
}
}
impl TemplateContext for RecoveryExpiredContext {
fn sample(now: chrono::DateTime<Utc>, rng: &mut impl Rng) -> Vec<Self>
where
Self: Sized,
{
let session = UserRecoverySession {
id: Ulid::from_datetime_with_source(now.into(), rng),
email: "name@mail.com".to_owned(),
user_agent: UserAgent::parse("Mozilla/5.0".to_owned()),
ip_address: None,
locale: "en".to_owned(),
created_at: now,
consumed_at: None,
};
vec![Self { session }]
}
}
/// Fields of the account recovery finish form
#[derive(Serialize, Deserialize, Debug, Clone, Copy, Hash, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]

View File

@@ -46,12 +46,12 @@ pub use self::{
DeviceLinkFormField, EmailAddContext, EmailRecoveryContext, EmailVerificationContext,
EmailVerificationPageContext, EmptyContext, ErrorContext, FormPostContext, IndexContext,
LoginContext, LoginFormField, NotFoundContext, PolicyViolationContext, PostAuthContext,
PostAuthContextInner, ReauthContext, ReauthFormField, RecoveryFinishContext,
RecoveryFinishFormField, RecoveryProgressContext, RecoveryStartContext,
RecoveryStartFormField, RegisterContext, RegisterFormField, SiteBranding, SiteConfigExt,
SiteFeatures, TemplateContext, UpstreamExistingLinkContext, UpstreamRegister,
UpstreamRegisterFormField, UpstreamSuggestLink, WithCaptcha, WithCsrf, WithLanguage,
WithOptionalSession, WithSession,
PostAuthContextInner, ReauthContext, ReauthFormField, RecoveryExpiredContext,
RecoveryFinishContext, RecoveryFinishFormField, RecoveryProgressContext,
RecoveryStartContext, RecoveryStartFormField, RegisterContext, RegisterFormField,
SiteBranding, SiteConfigExt, SiteFeatures, TemplateContext, UpstreamExistingLinkContext,
UpstreamRegister, UpstreamRegisterFormField, UpstreamSuggestLink, WithCaptcha, WithCsrf,
WithLanguage, WithOptionalSession, WithSession,
},
forms::{FieldError, FormError, FormField, FormState, ToFormState},
};
@@ -357,6 +357,9 @@ register_templates! {
/// Render the account recovery finish page
pub fn render_recovery_finish(WithLanguage<WithCsrf<RecoveryFinishContext>>) { "pages/recovery/finish.html" }
/// Render the account recovery link expired page
pub fn render_recovery_expired(WithLanguage<WithCsrf<RecoveryExpiredContext>>) { "pages/recovery/expired.html" }
/// Render the account recovery disabled page
pub fn render_recovery_disabled(WithLanguage<EmptyContext>) { "pages/recovery/disabled.html" }
@@ -428,6 +431,7 @@ impl Templates {
check::render_recovery_start(self, now, rng)?;
check::render_recovery_progress(self, now, rng)?;
check::render_recovery_finish(self, now, rng)?;
check::render_recovery_expired(self, now, rng)?;
check::render_recovery_disabled(self, now, rng)?;
check::render_reauth(self, now, rng)?;
check::render_form_post::<EmptyContext>(self, now, rng)?;