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},
|
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 {})
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue