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
This commit is contained in:
Dessalines 2025-02-12 07:45:25 -05:00 committed by GitHub
parent 0af973c3a2
commit c71e2a2195
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 59 additions and 63 deletions

1
Cargo.lock generated
View file

@ -2591,7 +2591,6 @@ dependencies = [
"regex",
"reqwest 0.12.12",
"reqwest-middleware",
"rosetta-i18n",
"serde",
"serde_with",
"serial_test",

View file

@ -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(),

View file

@ -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 }

View file

@ -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,

View file

@ -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);

View file

@ -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);

View file

@ -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<LemmyContext>,
local_site: &LocalSite,
local_user: &LocalUser,
person: &Person,
) -> LemmyResult<bool> {
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(

View file

@ -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

View file

@ -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")
})
}

@ -1 +1 @@
Subproject commit 0955855d9635f88f30d7c2aeaa864278c08c985b
Subproject commit 9bf0a79cf87912d401534525dc9030f225e4cd4a