From c71e2a2195cf83c832970102c73307a030af2f81 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Wed, 12 Feb 2025 07:45:25 -0500 Subject: [PATCH] When verifying email, add note about waiting for approval. (#5419) * When verifying email, add note about waiting for approval. - Fixes #5392 * Refactoring local user interface language. * Removing rosetta from api common. * Remove pointless Ok --- Cargo.lock | 1 - crates/api/src/local_user/save_settings.rs | 4 +- crates/api_common/Cargo.toml | 2 - crates/api_common/src/build_response.rs | 13 ++---- crates/api_common/src/utils.rs | 46 ++++++++----------- crates/api_crud/src/private_message/create.rs | 3 +- crates/api_crud/src/user/create.rs | 31 ++++++------- crates/db_schema/src/impls/local_user.rs | 9 +++- crates/utils/src/email.rs | 11 +++++ crates/utils/translations | 2 +- 10 files changed, 59 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d2324ad7a..2b1e01770 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2591,7 +2591,6 @@ dependencies = [ "regex", "reqwest 0.12.12", "reqwest-middleware", - "rosetta-i18n", "serde", "serde_with", "serial_test", diff --git a/crates/api/src/local_user/save_settings.rs b/crates/api/src/local_user/save_settings.rs index 8122d31cc..289012c25 100644 --- a/crates/api/src/local_user/save_settings.rs +++ b/crates/api/src/local_user/save_settings.rs @@ -54,7 +54,9 @@ pub async fn save_user_settings( if previous_email.deref() != email { LocalUser::check_is_email_taken(&mut context.pool(), email).await?; send_verification_email( - &local_user_view, + &site_view.local_site, + &local_user_view.local_user, + &local_user_view.person, email, &mut context.pool(), context.settings(), diff --git a/crates/api_common/Cargo.toml b/crates/api_common/Cargo.toml index 616b30667..366c647c4 100644 --- a/crates/api_common/Cargo.toml +++ b/crates/api_common/Cargo.toml @@ -19,7 +19,6 @@ workspace = true [features] full = [ "tracing", - "rosetta-i18n", "lemmy_db_views/full", "lemmy_utils/full", "activitypub_federation", @@ -51,7 +50,6 @@ chrono = { workspace = true } tracing = { workspace = true, optional = true } reqwest-middleware = { workspace = true, optional = true } regex = { workspace = true } -rosetta-i18n = { workspace = true, optional = true } futures = { workspace = true, optional = true } uuid = { workspace = true, optional = true } tokio = { workspace = true, optional = true } diff --git a/crates/api_common/src/build_response.rs b/crates/api_common/src/build_response.rs index ac8e299be..a7c8b7afa 100644 --- a/crates/api_common/src/build_response.rs +++ b/crates/api_common/src/build_response.rs @@ -3,12 +3,7 @@ use crate::{ community::CommunityResponse, context::LemmyContext, post::PostResponse, - utils::{ - check_person_instance_community_block, - get_interface_language, - is_mod_or_admin, - send_email_to_user, - }, + utils::{check_person_instance_community_block, is_mod_or_admin, send_email_to_user}, }; use actix_web::web::Json; use lemmy_db_schema::{ @@ -192,7 +187,7 @@ pub async fn send_local_notifs( // Send an email to those local users that have notifications on if do_send_email { - let lang = get_interface_language(&mention_user_view); + let lang = &mention_user_view.local_user.interface_i18n_language(); let content = markdown_to_html(&comment_content_or_post_body); send_email_to_user( &mention_user_view, @@ -245,7 +240,7 @@ pub async fn send_local_notifs( .ok(); if do_send_email { - let lang = get_interface_language(&parent_user_view); + let lang = &parent_user_view.local_user.interface_i18n_language(); let content = markdown_to_html(&comment.content); send_email_to_user( &parent_user_view, @@ -298,7 +293,7 @@ pub async fn send_local_notifs( .ok(); if do_send_email { - let lang = get_interface_language(&parent_user_view); + let lang = &parent_user_view.local_user.interface_i18n_language(); let content = markdown_to_html(&comment.content); send_email_to_user( &parent_user_view, diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index 1aa40863d..623386c78 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -26,6 +26,7 @@ use lemmy_db_schema::{ local_site::LocalSite, local_site_rate_limit::LocalSiteRateLimit, local_site_url_blocklist::LocalSiteUrlBlocklist, + local_user::LocalUser, mod_log::moderator::{ ModRemoveComment, ModRemoveCommentForm, @@ -60,7 +61,7 @@ use lemmy_db_views::{ }, }; use lemmy_utils::{ - email::{send_email, translations::Lang}, + email::send_email, error::{LemmyError, LemmyErrorExt, LemmyErrorExt2, LemmyErrorType, LemmyResult}, rate_limit::{ActionType, BucketConfig}, settings::{ @@ -78,7 +79,6 @@ use lemmy_utils::{ }; use moka::future::Cache; use regex::{escape, Regex, RegexSet}; -use rosetta_i18n::{Language, LanguageId}; use std::sync::LazyLock; use tracing::{warn, Instrument}; use url::{ParseError, Url}; @@ -446,7 +446,7 @@ pub async fn send_password_reset_email( .email .clone() .ok_or(LemmyErrorType::EmailRequired)?; - let lang = get_interface_language(user); + let lang = &user.local_user.interface_i18n_language(); let subject = &lang.password_reset_subject(&user.person.name); let protocol_and_hostname = settings.get_protocol_and_hostname(); let reset_link = format!("{}/password_change/{}", protocol_and_hostname, &token); @@ -462,13 +462,15 @@ pub async fn send_password_reset_email( /// Send a verification email pub async fn send_verification_email( - user: &LocalUserView, + local_site: &LocalSite, + local_user: &LocalUser, + person: &Person, new_email: &str, pool: &mut DbPool<'_>, settings: &Settings, ) -> LemmyResult<()> { let form = EmailVerificationForm { - local_user_id: user.local_user.id, + local_user_id: local_user.id, email: new_email.to_string(), verification_token: uuid::Uuid::new_v4().to_string(), }; @@ -479,29 +481,17 @@ pub async fn send_verification_email( ); EmailVerification::create(pool, &form).await?; - let lang = get_interface_language(user); + let lang = local_user.interface_i18n_language(); let subject = lang.verify_email_subject(&settings.hostname); - let body = lang.verify_email_body(&settings.hostname, &user.person.name, verify_link); - send_email(&subject, new_email, &user.person.name, &body, settings).await?; - Ok(()) -} + // If an application is required, use a translation that includes that warning. + let body = if local_site.registration_mode == RegistrationMode::RequireApplication { + lang.verify_email_body_with_application(&settings.hostname, &person.name, verify_link) + } else { + lang.verify_email_body(&settings.hostname, &person.name, verify_link) + }; -pub fn get_interface_language(user: &LocalUserView) -> Lang { - lang_str_to_lang(&user.local_user.interface_language) -} - -pub fn get_interface_language_from_settings(user: &LocalUserView) -> Lang { - lang_str_to_lang(&user.local_user.interface_language) -} - -#[allow(clippy::expect_used)] -fn lang_str_to_lang(lang: &str) -> Lang { - let lang_id = LanguageId::new(lang); - Lang::from_language_id(&lang_id).unwrap_or_else(|| { - let en = LanguageId::new("en"); - Lang::from_language_id(&en).expect("default language") - }) + send_email(&subject, new_email, &person.name, &body, settings).await } pub fn local_site_rate_limit_to_rate_limit_config( @@ -568,7 +558,7 @@ pub async fn send_application_approved_email( .email .clone() .ok_or(LemmyErrorType::EmailRequired)?; - let lang = get_interface_language(user); + let lang = &user.local_user.interface_i18n_language(); let subject = lang.registration_approved_subject(&user.person.ap_id); let body = lang.registration_approved_body(&settings.hostname); send_email(&subject, email, &user.person.name, &body, settings).await @@ -594,7 +584,7 @@ pub async fn send_new_applicant_email_to_admins( .email .clone() .ok_or(LemmyErrorType::EmailRequired)?; - let lang = get_interface_language_from_settings(admin); + let lang = &admin.local_user.interface_i18n_language(); let subject = lang.new_application_subject(&settings.hostname, applicant_username); let body = lang.new_application_body(applications_link); send_email(&subject, email, &admin.person.name, &body, settings).await?; @@ -616,7 +606,7 @@ pub async fn send_new_report_email_to_admins( for admin in &admins { if let Some(email) = &admin.local_user.email { - let lang = get_interface_language_from_settings(admin); + let lang = &admin.local_user.interface_i18n_language(); let subject = lang.new_report_subject(&settings.hostname, reported_username, reporter_username); let body = lang.new_report_body(reports_link); diff --git a/crates/api_crud/src/private_message/create.rs b/crates/api_crud/src/private_message/create.rs index fba8aedd8..ff89e5233 100644 --- a/crates/api_crud/src/private_message/create.rs +++ b/crates/api_crud/src/private_message/create.rs @@ -6,7 +6,6 @@ use lemmy_api_common::{ send_activity::{ActivityChannel, SendActivityData}, utils::{ check_private_messages_enabled, - get_interface_language, get_url_blocklist, local_site_to_slur_regex, process_markdown, @@ -72,7 +71,7 @@ pub async fn create_private_message( if view.recipient.local { let recipient_id = data.recipient_id; let local_recipient = LocalUserView::read_person(&mut context.pool(), recipient_id).await?; - let lang = get_interface_language(&local_recipient); + let lang = &local_recipient.local_user.interface_i18n_language(); let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname()); let sender_name = &local_user_view.person.name; let content = markdown_to_html(&content); diff --git a/crates/api_crud/src/user/create.rs b/crates/api_crud/src/user/create.rs index 43a854e62..a4d3c334b 100644 --- a/crates/api_crud/src/user/create.rs +++ b/crates/api_crud/src/user/create.rs @@ -18,7 +18,6 @@ use lemmy_api_common::{ }, }; use lemmy_db_schema::{ - aggregates::structs::PersonAggregates, newtypes::{InstanceId, OAuthProviderId}, source::{ actor_language::SiteLanguage, @@ -26,7 +25,6 @@ use lemmy_db_schema::{ language::Language, local_site::LocalSite, local_user::{LocalUser, LocalUserInsertForm}, - local_user_vote_display_mode::LocalUserVoteDisplayMode, oauth_account::{OAuthAccount, OAuthAccountInsertForm}, oauth_provider::OAuthProvider, person::{Person, PersonInsertForm}, @@ -476,35 +474,32 @@ async fn create_local_user( Ok(inserted_local_user) } +/// Returns true if email was sent. async fn send_verification_email_if_required( context: &Data, local_site: &LocalSite, local_user: &LocalUser, person: &Person, ) -> LemmyResult { - let mut sent = false; - if !local_user.admin && local_site.require_email_verification && !local_user.email_verified { - let local_user_view = LocalUserView { - local_user: local_user.clone(), - local_user_vote_display_mode: LocalUserVoteDisplayMode::default(), - person: person.clone(), - counts: PersonAggregates::default(), - }; + let email = &local_user + .email + .clone() + .ok_or(LemmyErrorType::EmailRequired)?; + if !local_user.admin && local_site.require_email_verification && !local_user.email_verified { send_verification_email( - &local_user_view, - &local_user - .email - .clone() - .ok_or(LemmyErrorType::EmailRequired)?, + local_site, + local_user, + person, + email, &mut context.pool(), context.settings(), ) .await?; - - sent = true; + Ok(true) + } else { + Ok(false) } - Ok(sent) } fn validate_registration_answer( diff --git a/crates/db_schema/src/impls/local_user.rs b/crates/db_schema/src/impls/local_user.rs index 4309f8d52..44978b190 100644 --- a/crates/db_schema/src/impls/local_user.rs +++ b/crates/db_schema/src/impls/local_user.rs @@ -29,7 +29,10 @@ use diesel::{ QueryDsl, }; use diesel_async::RunQueryDsl; -use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult}; +use lemmy_utils::{ + email::{lang_str_to_lang, translations::Lang}, + error::{LemmyErrorExt, LemmyErrorType, LemmyResult}, +}; impl LocalUser { pub async fn create( @@ -297,6 +300,10 @@ impl LocalUser { Err(LemmyErrorType::NotHigherMod)? } } + + pub fn interface_i18n_language(&self) -> Lang { + lang_str_to_lang(&self.interface_language) + } } // TODO diff --git a/crates/utils/src/email.rs b/crates/utils/src/email.rs index aa06ba1b9..0806f2df2 100644 --- a/crates/utils/src/email.rs +++ b/crates/utils/src/email.rs @@ -10,7 +10,9 @@ use lettre::{ AsyncTransport, Message, }; +use rosetta_i18n::{Language, LanguageId}; use std::str::FromStr; +use translations::Lang; use uuid::Uuid; pub mod translations { @@ -93,3 +95,12 @@ pub async fn send_email( Ok(()) } + +#[allow(clippy::expect_used)] +pub fn lang_str_to_lang(lang: &str) -> Lang { + let lang_id = LanguageId::new(lang); + Lang::from_language_id(&lang_id).unwrap_or_else(|| { + let en = LanguageId::new("en"); + Lang::from_language_id(&en).expect("default language") + }) +} diff --git a/crates/utils/translations b/crates/utils/translations index 0955855d9..9bf0a79cf 160000 --- a/crates/utils/translations +++ b/crates/utils/translations @@ -1 +1 @@ -Subproject commit 0955855d9635f88f30d7c2aeaa864278c08c985b +Subproject commit 9bf0a79cf87912d401534525dc9030f225e4cd4a