Limit password resets (#3344)

This commit is contained in:
Sander Saarend 2023-06-27 12:20:53 +03:00 committed by GitHub
parent 98482b1564
commit 76a4513774
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 1 deletions

View file

@ -5,6 +5,7 @@ use lemmy_api_common::{
person::{PasswordReset, PasswordResetResponse}, person::{PasswordReset, PasswordResetResponse},
utils::send_password_reset_email, utils::send_password_reset_email,
}; };
use lemmy_db_schema::source::password_reset_request::PasswordResetRequest;
use lemmy_db_views::structs::LocalUserView; use lemmy_db_views::structs::LocalUserView;
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
@ -25,6 +26,16 @@ impl Perform for PasswordReset {
.await .await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_find_that_username_or_email"))?; .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. // Email the pure token to the user.
send_password_reset_email(&local_user_view, context.pool(), context.settings()).await?; send_password_reset_email(&local_user_view, context.pool(), context.settings()).await?;
Ok(PasswordResetResponse {}) Ok(PasswordResetResponse {})

View file

@ -1,6 +1,11 @@
use crate::{ use crate::{
newtypes::LocalUserId, 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}, source::password_reset_request::{PasswordResetRequest, PasswordResetRequestForm},
traits::Crud, traits::Crud,
utils::{get_conn, DbPool}, utils::{get_conn, DbPool},
@ -74,6 +79,19 @@ impl PasswordResetRequest {
.first::<Self>(conn) .first::<Self>(conn)
.await .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 { fn bytes_to_hex(bytes: Vec<u8>) -> String {