Skip to content

Commit

Permalink
Limit password resets
Browse files Browse the repository at this point in the history
  • Loading branch information
sunaurus committed Jun 26, 2023
1 parent c588640 commit 2ddd77a
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
11 changes: 11 additions & 0 deletions crates/api/src/local_user/reset_password.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use lemmy_api_common::{
person::{PasswordReset, PasswordResetResponse},
utils::send_password_reset_email,
};
use lemmy_db_schema::source::password_reset_request::PasswordResetRequest;
use lemmy_db_views::structs::LocalUserView;
use lemmy_utils::error::LemmyError;

Expand All @@ -25,6 +26,16 @@ impl Perform for PasswordReset {
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_that_username_or_email"))?;

// Check for too many attempts (to limit potential abuse)
let recent_resets_count = PasswordResetRequest::get_recent_password_resets_count(
context.pool(),
local_user_view.local_user.id,
)
.await?;
if recent_resets_count >= 3 {
return Err(LemmyError::from_message("password_reset_limit_reached"));
}

// Email the pure token to the user.
send_password_reset_email(&local_user_view, context.pool(), context.settings()).await?;
Ok(PasswordResetResponse {})
Expand Down
20 changes: 19 additions & 1 deletion crates/db_schema/src/impls/password_reset_request.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use crate::{
newtypes::LocalUserId,
schema::password_reset_request::dsl::{password_reset_request, published, token_encrypted},
schema::password_reset_request::dsl::{
local_user_id,
password_reset_request,
published,
token_encrypted,
},
source::password_reset_request::{PasswordResetRequest, PasswordResetRequestForm},
traits::Crud,
utils::{get_conn, DbPool},
Expand Down Expand Up @@ -74,6 +79,19 @@ impl PasswordResetRequest {
.first::<Self>(conn)
.await
}

pub async fn get_recent_password_resets_count(
pool: &DbPool,
user_id: LocalUserId,
) -> Result<i64, Error> {
let conn = &mut get_conn(pool).await?;
password_reset_request
.filter(local_user_id.eq(user_id))
.filter(published.gt(now - 1.days()))
.count()
.get_result(conn)
.await
}
}

fn bytes_to_hex(bytes: Vec<u8>) -> String {
Expand Down

0 comments on commit 2ddd77a

Please sign in to comment.