From 1f1fc5eb9fa4d7f495413428daf53fd96c8ce25e Mon Sep 17 00:00:00 2001 From: Ginger Date: Wed, 6 May 2026 14:38:06 -0400 Subject: [PATCH] refactor: Use more consistent terminology for email validation pages --- src/service/firstrun/mod.rs | 2 +- src/web/pages/account/email.rs | 34 ++++++------ src/web/pages/account/password/reset.rs | 54 +++++++++---------- src/web/pages/account/register.rs | 18 ++++--- src/web/pages/templates/change_email.html.j2 | 50 ++++++++--------- .../templates/change_email_request.html.j2 | 35 ------------ .../templates/change_email_validate.html.j2 | 33 ++++++++++++ src/web/pages/templates/register.html.j2 | 1 + ...tml.j2 => register_email_validate.html.j2} | 0 .../pages/templates/reset_password.html.j2 | 38 ++++++------- .../templates/reset_password_request.html.j2 | 32 ----------- .../templates/reset_password_validate.html.j2 | 36 +++++++++++++ 12 files changed, 168 insertions(+), 165 deletions(-) delete mode 100644 src/web/pages/templates/change_email_request.html.j2 create mode 100644 src/web/pages/templates/change_email_validate.html.j2 rename src/web/pages/templates/{register_confirm_email.html.j2 => register_email_validate.html.j2} (100%) delete mode 100644 src/web/pages/templates/reset_password_request.html.j2 create mode 100644 src/web/pages/templates/reset_password_validate.html.j2 diff --git a/src/service/firstrun/mod.rs b/src/service/firstrun/mod.rs index 85759c4b9..f2b3452bb 100644 --- a/src/service/firstrun/mod.rs +++ b/src/service/firstrun/mod.rs @@ -6,7 +6,7 @@ use askama::Template; use async_trait::async_trait; use conduwuit::{Result, info, utils::ReadyExt}; -use futures::{FutureExt, StreamExt}; +use futures::StreamExt; use ruma::{UserId, events::room::message::RoomMessageEventContent}; use crate::{ diff --git a/src/web/pages/account/email.rs b/src/web/pages/account/email.rs index b68564e70..cc9b9e294 100644 --- a/src/web/pages/account/email.rs +++ b/src/web/pages/account/email.rs @@ -25,13 +25,13 @@ pub(crate) fn build() -> Router { Router::new() - .route("/change/", on(GET_POST, route_change_email_request)) - .route("/change/validate", get(get_change_email)) + .route("/change/", on(GET_POST, route_change_email)) + .route("/change/validate", get(get_change_email_validate)) .route("/change/delete", post(post_delete_email)) } template! { - struct ChangeEmailRequest use "change_email_request.html.j2" { + struct ChangeEmail use "change_email.html.j2" { user_card: UserCard, email: Option, form: Form<'static>, @@ -40,7 +40,7 @@ struct ChangeEmailRequest use "change_email_request.html.j2" { } form! { - struct ChangeEmailRequestForm { + struct ChangeEmailForm { email: Address where { input_type: "email", label: "Email address" @@ -51,9 +51,9 @@ struct ChangeEmailRequestForm { } template! { - struct ChangeEmail use "change_email.html.j2" { + struct ChangeEmailValidate use "change_email_validate.html.j2" { user_card: UserCard, - body: ChangeEmailBody + body: ChangeEmailValidateBody } } @@ -64,7 +64,7 @@ struct DeleteEmail use "delete_email.html.j2" { } #[derive(Debug)] -enum ChangeEmailBody { +enum ChangeEmailValidateBody { ValidationPending { session_id: OwnedSessionId, client_secret: OwnedClientSecret, @@ -73,16 +73,16 @@ enum ChangeEmailBody { Success, } -async fn route_change_email_request( +async fn route_change_email( State(services): State, Extension(context): Extension, user: User, - PostForm(form): PostForm, + PostForm(form): PostForm, ) -> Result { let user_id = user.expect_recent(LoginTarget::ChangeEmail)?; let Some(form) = form else { - return response!(ChangeEmailRequest::new( + return response!(ChangeEmail::new( context.clone(), UserCard::for_local_user(&services, user_id.clone()).await, services @@ -90,7 +90,7 @@ async fn route_change_email_request( .get_email_for_localpart(user_id.localpart()) .await .map(|address| address.to_string()), - ChangeEmailRequestForm::build(context), + ChangeEmailForm::build(context), services.threepid.email_requirement().may_remove(), )); }; @@ -128,10 +128,10 @@ async fn route_change_email_request( } }; - response!(ChangeEmail::new( + response!(ChangeEmailValidate::new( context, UserCard::for_local_user(&services, user_id).await, - ChangeEmailBody::ValidationPending { + ChangeEmailValidateBody::ValidationPending { session_id, client_secret, validation_error: false @@ -145,7 +145,7 @@ struct ChangeEmailQuery { threepid: ThreepidQuery, } -async fn get_change_email( +async fn get_change_email_validate( State(services): State, Extension(context): Extension, Expect(Query(ChangeEmailQuery { @@ -165,10 +165,10 @@ async fn get_change_email( .get_valid_session(&session_id, &client_secret) .await else { - return response!(ChangeEmail::new( + return response!(ChangeEmailValidate::new( context, user_card, - ChangeEmailBody::ValidationPending { + ChangeEmailValidateBody::ValidationPending { session_id, client_secret, validation_error: true @@ -186,7 +186,7 @@ async fn get_change_email( return response!(BadRequest(err.message())); } - response!(ChangeEmail::new(context, user_card, ChangeEmailBody::Success)) + response!(ChangeEmailValidate::new(context, user_card, ChangeEmailValidateBody::Success)) } async fn post_delete_email( diff --git a/src/web/pages/account/password/reset.rs b/src/web/pages/account/password/reset.rs index 0cd6b5ffe..5802ee8f8 100644 --- a/src/web/pages/account/password/reset.rs +++ b/src/web/pages/account/password/reset.rs @@ -28,18 +28,18 @@ pub(crate) fn build() -> Router { Router::new() - .route("/", on(GET_POST, route_reset_password_request)) - .route("/validate", on(GET_POST, route_reset_password)) + .route("/", on(GET_POST, route_reset_password)) + .route("/validate", on(GET_POST, route_reset_password_validate)) } template! { - struct ResetPasswordRequest use "reset_password_request.html.j2" { - body: ResetPasswordRequestBody + struct ResetPassword use "reset_password.html.j2" { + body: ResetPasswordBody } } #[derive(Debug)] -enum ResetPasswordRequestBody { +enum ResetPasswordBody { Form(Form<'static>), Unavailable, } @@ -55,24 +55,21 @@ struct ResetPasswordRequestForm { } } -async fn route_reset_password_request( +async fn route_reset_password( State(services): State, Extension(context): Extension, PostForm(form): PostForm, ) -> Result { // Check if SMTP is configured if services.mailer.mailer().is_none() { - return response!(ResetPasswordRequest::new( - context, - ResetPasswordRequestBody::Unavailable - )); + return response!(ResetPassword::new(context, ResetPasswordBody::Unavailable)); } let Some(form) = form else { // For GET requests return the reset request form - return response!(ResetPasswordRequest::new( + return response!(ResetPassword::new( context.clone(), - ResetPasswordRequestBody::Form(ResetPasswordRequestForm::build(context)) + ResetPasswordBody::Form(ResetPasswordRequestForm::build(context)) )); }; @@ -118,21 +115,24 @@ async fn route_reset_password_request( ValidationSessions::generate_session_id() }); - response!(ResetPassword::new(context, ResetPasswordBody::ValidationPending { - client_secret, - session_id, - validation_error: false - })) + response!(ResetPasswordValidate::new( + context, + ResetPasswordValidateBody::ValidationPending { + client_secret, + session_id, + validation_error: false + } + )) } template! { - struct ResetPassword use "reset_password.html.j2" { - body: ResetPasswordBody + struct ResetPasswordValidate use "reset_password_validate.html.j2" { + body: ResetPasswordValidateBody } } #[derive(Debug)] -enum ResetPasswordBody { +enum ResetPasswordValidateBody { ValidationPending { session_id: OwnedSessionId, client_secret: OwnedClientSecret, @@ -173,7 +173,7 @@ struct ResetPasswordQuery { threepid: ThreepidQuery, } -async fn route_reset_password( +async fn route_reset_password_validate( State(services): State, Extension(context): Extension, Expect(Query(query)): Expect>, @@ -203,7 +203,7 @@ async fn route_reset_password( if let Some(form) = form { if let Err(err) = form.validate() { - ResetPasswordBody::ValidationSuccess { + ResetPasswordValidateBody::ValidationSuccess { user_card, form: ResetPasswordForm::with_errors(context.clone(), err), } @@ -214,7 +214,7 @@ async fn route_reset_password( services.users.set_password(&user_id, Some(hash)); - ResetPasswordBody::ResetSuccess { user_card } + ResetPasswordValidateBody::ResetSuccess { user_card } }, | Err(err) => { let mut errors = ValidationErrors::new(); @@ -225,7 +225,7 @@ async fn route_reset_password( .with_message(err.message().into()), ); - ResetPasswordBody::ValidationSuccess { + ResetPasswordValidateBody::ValidationSuccess { user_card, form: ResetPasswordForm::with_errors(context.clone(), errors), } @@ -233,18 +233,18 @@ async fn route_reset_password( } } } else { - ResetPasswordBody::ValidationSuccess { + ResetPasswordValidateBody::ValidationSuccess { user_card, form: ResetPasswordForm::build(context.clone()), } } }, - | Err(_) => ResetPasswordBody::ValidationPending { + | Err(_) => ResetPasswordValidateBody::ValidationPending { session_id: query.threepid.session_id, client_secret: query.threepid.client_secret, validation_error: true, }, }; - response!(ResetPassword::new(context, body)) + response!(ResetPasswordValidate::new(context, body)) } diff --git a/src/web/pages/account/register.rs b/src/web/pages/account/register.rs index c4a873b3f..5d401b508 100644 --- a/src/web/pages/account/register.rs +++ b/src/web/pages/account/register.rs @@ -31,7 +31,7 @@ pub(crate) fn build() -> Router { Router::new() .route("/", on(GET_POST, route_register)) - .route("/validate", get(get_register_confirm_email)) + .route("/validate", get(get_register_email_validate)) } template! { @@ -225,7 +225,7 @@ async fn route_register( } template! { - struct RegisterConfirmEmail use "register_confirm_email.html.j2" { + struct RegisterEmailValidate use "register_email_validate.html.j2" { session_id: OwnedSessionId, client_secret: OwnedClientSecret, validation_error: bool @@ -233,18 +233,18 @@ struct RegisterConfirmEmail use "register_confirm_email.html.j2" { } #[derive(Deserialize, Serialize)] -struct RegisterConfirmEmailQuery { +struct RegisterEmailValidateQuery { #[serde(flatten)] threepid: ThreepidQuery, } -async fn get_register_confirm_email( +async fn get_register_email_validate( State(services): State, Extension(context): Extension, session_store: Session, - Expect(Query(RegisterConfirmEmailQuery { + Expect(Query(RegisterEmailValidateQuery { threepid: ThreepidQuery { client_secret, session_id }, - })): Expect>, + })): Expect>, ) -> Result { let Some(completed_registration) = session_store .get::(COMPLETED_REGISTRATION_KEY) @@ -261,7 +261,7 @@ async fn get_register_confirm_email( .get_valid_session(&session_id, &client_secret) .await else { - return response!(RegisterConfirmEmail::new(context, session_id, client_secret, true,)); + return response!(RegisterEmailValidate::new(context, session_id, client_secret, true,)); }; let email = session.consume(); @@ -451,7 +451,9 @@ async fn begin_registration( .await .expect("should have been able to serialize completed registration"); - Ok(response!(RegisterConfirmEmail::new(context, session_id, client_secret, false,))) + Ok(response!( + RegisterEmailValidate::new(context, session_id, client_secret, false,) + )) } else { // If email isn't required we can immediately complete registration complete_registration(services, session_store, completed_registration, None).await; diff --git a/src/web/pages/templates/change_email.html.j2 b/src/web/pages/templates/change_email.html.j2 index 055e95dec..93f35dce5 100644 --- a/src/web/pages/templates/change_email.html.j2 +++ b/src/web/pages/templates/change_email.html.j2 @@ -5,29 +5,31 @@ Change your email {%- endblock -%} {%- block content -%} -
-

Change your email

+
+

Change your email Back

{{ user_card }} - {% match body %} - {% when ChangeEmailBody::ValidationPending { session_id, client_secret, validation_error } %} -

- A message has been sent to your new email address with a validation link. If you do not receive the email: -

    -
  • Check your spam filter.
  • -
-

- {% if validation_error %} - Validation failed. Have you clicked the link in the email that was sent to you? - {% endif %} -
- - - -
- {% when ChangeEmailBody::Success %} -

- Your email address has been changed successfully. Back -

- {% endmatch %} +

+ Your email address will be used for automated emails, such as password reset requests. It is also + visible to your homeserver's administrator, who may use it to contact you directly. +

+

+ {% if let Some(email) = email %} + Your account's associated email address is {{ email }}. + To change your email address, enter your new address below. + {% else %} + Your account has no associated email address. To add an email address, enter it below. + {% endif %} +

+ {{ form }} + + {% if may_remove %} +

+ You may remove your email address. Note that, if your account has no email address, + you will not be able to reset your password if you forget it. +

+
+ +
+ {% endif %}
-{%- endblock -%} +{% endblock %} diff --git a/src/web/pages/templates/change_email_request.html.j2 b/src/web/pages/templates/change_email_request.html.j2 deleted file mode 100644 index 93f35dce5..000000000 --- a/src/web/pages/templates/change_email_request.html.j2 +++ /dev/null @@ -1,35 +0,0 @@ -{% extends "_layout.html.j2" %} - -{%- block title -%} -Change your email -{%- endblock -%} - -{%- block content -%} -
-

Change your email Back

- {{ user_card }} -

- Your email address will be used for automated emails, such as password reset requests. It is also - visible to your homeserver's administrator, who may use it to contact you directly. -

-

- {% if let Some(email) = email %} - Your account's associated email address is {{ email }}. - To change your email address, enter your new address below. - {% else %} - Your account has no associated email address. To add an email address, enter it below. - {% endif %} -

- {{ form }} - - {% if may_remove %} -

- You may remove your email address. Note that, if your account has no email address, - you will not be able to reset your password if you forget it. -

-
- -
- {% endif %} -
-{% endblock %} diff --git a/src/web/pages/templates/change_email_validate.html.j2 b/src/web/pages/templates/change_email_validate.html.j2 new file mode 100644 index 000000000..3664c2fa4 --- /dev/null +++ b/src/web/pages/templates/change_email_validate.html.j2 @@ -0,0 +1,33 @@ +{% extends "_layout.html.j2" %} + +{%- block title -%} +Change your email +{%- endblock -%} + +{%- block content -%} +
+

Change your email

+ {{ user_card }} + {% match body %} + {% when ChangeEmailValidateBody::ValidationPending { session_id, client_secret, validation_error } %} +

+ A message has been sent to your new email address with a validation link. If you do not receive the email: +

    +
  • Check your spam filter.
  • +
+

+ {% if validation_error %} + Validation failed. Have you clicked the link in the email that was sent to you? + {% endif %} +
+ + + +
+ {% when ChangeEmailValidateBody::Success %} +

+ Your email address has been changed successfully. Back +

+ {% endmatch %} +
+{%- endblock -%} diff --git a/src/web/pages/templates/register.html.j2 b/src/web/pages/templates/register.html.j2 index 8b095be6c..bdd393125 100644 --- a/src/web/pages/templates/register.html.j2 +++ b/src/web/pages/templates/register.html.j2 @@ -85,6 +85,7 @@ Sign up :{{ server_name }} {{ form::errors(field_errors, std::borrow::Cow::Borrowed("username")) }} + Note: Your username cannot be changed after you create your account.

Just a few more details to finish creating your account. diff --git a/src/web/pages/templates/register_confirm_email.html.j2 b/src/web/pages/templates/register_email_validate.html.j2 similarity index 100% rename from src/web/pages/templates/register_confirm_email.html.j2 rename to src/web/pages/templates/register_email_validate.html.j2 diff --git a/src/web/pages/templates/reset_password.html.j2 b/src/web/pages/templates/reset_password.html.j2 index a03bdbf58..35634727f 100644 --- a/src/web/pages/templates/reset_password.html.j2 +++ b/src/web/pages/templates/reset_password.html.j2 @@ -5,32 +5,28 @@ Reset your password {%- endblock -%} {%- block content -%} -

+{% match body %} + {% when ResetPasswordBody::Form(_) %} +
+ {% when ResetPasswordBody::Unavailable %} +
+{% endmatch %}

Reset your password

{% match body %} - {% when ResetPasswordBody::ValidationPending { session_id, client_secret, validation_error } %} + {% when ResetPasswordBody::Form(form) %}

- Check your inbox for the validation email. If you do not receive the email: -

    -
  • Check your spam filter.
  • -
  • Your Matrix account may not be associated with an email address. Contact your homeserver's - administrator for assistance.
  • -
+ To reset your password, enter your email below. If your Matrix account has an associated email address, + you will receive an email with a link to reset your password. +

+

+ If your Matrix account does not have an associated email address, contact your homeserver's administrator + to reset your password.

- {% if validation_error %} - Validation failed. Have you clicked the link in the email that was sent to you? - {% endif %} -
- - - -
- {% when ResetPasswordBody::ValidationSuccess { user_card, form } %} - {{ user_card }} {{ form }} - {% when ResetPasswordBody::ResetSuccess { user_card } %} - {{ user_card }} -

Your password has been reset successfully.

+ {% when ResetPasswordBody::Unavailable %} +

+ To reset your password, contact your homeserver's administrator. +

{% endmatch %}
{%- endblock -%} diff --git a/src/web/pages/templates/reset_password_request.html.j2 b/src/web/pages/templates/reset_password_request.html.j2 deleted file mode 100644 index 1e71f33a7..000000000 --- a/src/web/pages/templates/reset_password_request.html.j2 +++ /dev/null @@ -1,32 +0,0 @@ -{% extends "_layout.html.j2" %} - -{%- block title -%} -Reset your password -{%- endblock -%} - -{%- block content -%} -{% match body %} - {% when ResetPasswordRequestBody::Form(_) %} -
- {% when ResetPasswordRequestBody::Unavailable %} -
-{% endmatch %} -

Reset your password

- {% match body %} - {% when ResetPasswordRequestBody::Form(form) %} -

- To reset your password, enter your email below. If your Matrix account has an associated email address, - you will receive an email with a link to reset your password. -

-

- If your Matrix account does not have an associated email address, contact your homeserver's administrator - to reset your password. -

- {{ form }} - {% when ResetPasswordRequestBody::Unavailable %} -

- To reset your password, contact your homeserver's administrator. -

- {% endmatch %} -
-{%- endblock -%} diff --git a/src/web/pages/templates/reset_password_validate.html.j2 b/src/web/pages/templates/reset_password_validate.html.j2 new file mode 100644 index 000000000..dde49fc4b --- /dev/null +++ b/src/web/pages/templates/reset_password_validate.html.j2 @@ -0,0 +1,36 @@ +{% extends "_layout.html.j2" %} + +{%- block title -%} +Reset your password +{%- endblock -%} + +{%- block content -%} +
+

Reset your password

+ {% match body %} + {% when ResetPasswordValidateBody::ValidationPending { session_id, client_secret, validation_error } %} +

+ Check your inbox for the validation email. If you do not receive the email: +

    +
  • Check your spam filter.
  • +
  • Your Matrix account may not be associated with an email address. Contact your homeserver's + administrator for assistance.
  • +
+

+ {% if validation_error %} + Validation failed. Have you clicked the link in the email that was sent to you? + {% endif %} +
+ + + +
+ {% when ResetPasswordValidateBody::ValidationSuccess { user_card, form } %} + {{ user_card }} + {{ form }} + {% when ResetPasswordValidateBody::ResetSuccess { user_card } %} + {{ user_card }} +

Your password has been reset successfully.

+ {% endmatch %} +
+{%- endblock -%}