Limit password resets (#3344)
This commit is contained in:
parent
98482b1564
commit
76a4513774
2 changed files with 30 additions and 1 deletions
|
@ -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;
|
||||
|
||||
|
@ -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 {})
|
||||
|
|
|
@ -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},
|
||||
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue