Correct error messages if user registers with taken user/email (#3093)

* Correct error messages if user registers with taken user/email (fixes #2955)

* exists
This commit is contained in:
Nutomic 2023-06-21 11:26:07 +02:00 committed by GitHub
parent 1ef095dd96
commit e3eda68147
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 23 deletions

View file

@ -83,6 +83,12 @@ impl PerformCrud for Register {
&context.settings().get_protocol_and_hostname(), &context.settings().get_protocol_and_hostname(),
)?; )?;
if let Some(email) = &data.email {
if LocalUser::is_email_taken(context.pool(), email).await? {
return Err(LemmyError::from_message("email_already_exists"));
}
}
// We have to create both a person, and local_user // We have to create both a person, and local_user
// Register the new person // Register the new person
@ -116,23 +122,7 @@ impl PerformCrud for Register {
.accepted_application(accepted_application) .accepted_application(accepted_application)
.build(); .build();
let inserted_local_user = match LocalUser::create(context.pool(), &local_user_form).await { let inserted_local_user = LocalUser::create(context.pool(), &local_user_form).await?;
Ok(lu) => lu,
Err(e) => {
let err_type = if e.to_string()
== "duplicate key value violates unique constraint \"local_user_email_key\""
{
"email_already_exists"
} else {
"user_already_exists"
};
// If the local user creation errored, then delete that person
Person::delete(context.pool(), inserted_person.id).await?;
return Err(LemmyError::from_error_message(e, err_type));
}
};
if local_site.site_setup && require_registration_application { if local_site.site_setup && require_registration_application {
// Create the registration application // Create the registration application

View file

@ -171,7 +171,7 @@ impl Object for ApubPerson {
matrix_user_id: person.matrix_user_id, matrix_user_id: person.matrix_user_id,
instance_id, instance_id,
}; };
let person = DbPerson::create(context.pool(), &person_form).await?; let person = DbPerson::upsert(context.pool(), &person_form).await?;
Ok(person.into()) Ok(person.into())
} }

View file

@ -2,6 +2,7 @@ use crate::{
newtypes::LocalUserId, newtypes::LocalUserId,
schema::local_user::dsl::{ schema::local_user::dsl::{
accepted_application, accepted_application,
email,
email_verified, email_verified,
local_user, local_user,
password_encrypted, password_encrypted,
@ -53,6 +54,14 @@ impl LocalUser {
.get_results::<Self>(conn) .get_results::<Self>(conn)
.await .await
} }
pub async fn is_email_taken(pool: &DbPool, email_: &str) -> Result<bool, Error> {
use diesel::dsl::{exists, select};
let conn = &mut get_conn(pool).await?;
select(exists(local_user.filter(email.eq(email_))))
.get_result(conn)
.await
}
} }
#[async_trait] #[async_trait]
@ -80,8 +89,7 @@ impl Crud for LocalUser {
let local_user_ = insert_into(local_user) let local_user_ = insert_into(local_user)
.values(form_with_encrypted_password) .values(form_with_encrypted_password)
.get_result::<Self>(conn) .get_result::<Self>(conn)
.await .await?;
.expect("couldnt create local user");
let site_languages = SiteLanguage::read_local_raw(pool).await; let site_languages = SiteLanguage::read_local_raw(pool).await;
if let Ok(langs) = site_languages { if let Ok(langs) = site_languages {

View file

@ -37,9 +37,6 @@ impl Crud for Person {
let conn = &mut get_conn(pool).await?; let conn = &mut get_conn(pool).await?;
insert_into(person::table) insert_into(person::table)
.values(form) .values(form)
.on_conflict(person::actor_id)
.do_update()
.set(form)
.get_result::<Self>(conn) .get_result::<Self>(conn)
.await .await
} }
@ -57,6 +54,19 @@ impl Crud for Person {
} }
impl Person { impl Person {
/// Update or insert the person.
///
/// This is necessary for federation, because Activitypub doesnt distinguish between these actions.
pub async fn upsert(pool: &DbPool, form: &PersonInsertForm) -> Result<Self, Error> {
let conn = &mut get_conn(pool).await?;
insert_into(person::table)
.values(form)
.on_conflict(person::actor_id)
.do_update()
.set(form)
.get_result::<Self>(conn)
.await
}
pub async fn delete_account(pool: &DbPool, person_id: PersonId) -> Result<Person, Error> { pub async fn delete_account(pool: &DbPool, person_id: PersonId) -> Result<Person, Error> {
let conn = &mut get_conn(pool).await?; let conn = &mut get_conn(pool).await?;