@@ 10,7 10,7 @@ use argon2::{
password_hash::{rand_core::OsRng, SaltString},
Argon2, PasswordHasher,
};
-use diesel::{PgConnection, RunQueryDsl};
+use diesel::{ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
use laurelin_shared::error::api::APIError;
use crate::{
@@ 19,6 19,17 @@ use crate::{
};
pub(crate) fn create(conn: &mut PgConnection, user: &InsertableUser) -> Result<User, APIError> {
+ // NOTE: password hashing is expensive, a query at the start is about 170 times faster,
+ // compared to hashing the password and finding out the user exists and erroring out on the insert
+ // (according to quick maths and like 5 tests)
+ if users::table
+ .filter(users::email.eq(&user.email))
+ .first::<User>(conn)
+ .is_ok()
+ {
+ return Err(APIError::UserCreationFailed);
+ }
+
let salt = SaltString::generate(&mut OsRng);
let password_hash_result = Argon2::default().hash_password(user.password.as_bytes(), &salt);