Improve password reset token expiry.

This commit is contained in:
AndrolGenhald 2023-06-29 23:12:32 -05:00
parent ad18c0371f
commit c82f2d3bd6
2 changed files with 29 additions and 29 deletions

View file

@ -1,18 +1,12 @@
use crate::Perform;
use actix_web::web::Data;
use chrono::Duration;
use lemmy_api_common::{
context::LemmyContext,
person::{LoginResponse, PasswordChangeAfterReset},
utils::password_length_check,
};
use lemmy_db_schema::{
source::{
local_user::LocalUser,
password_reset_request::{PasswordResetRequest, PasswordResetRequestForm},
},
traits::Crud,
utils::naive_now,
source::{local_user::LocalUser, password_reset_request::PasswordResetRequest},
RegistrationMode,
};
use lemmy_db_views::structs::SiteView;
@ -41,17 +35,7 @@ impl Perform for PasswordChangeAfterReset {
// Expire reset token
// TODO do this in a transaction along with the user update (blocked by https://github.com/LemmyNet/lemmy/issues/1161)
PasswordResetRequest::update(
context.pool(),
reset_request.id,
&PasswordResetRequestForm {
local_user_id: reset_request.local_user_id,
token_encrypted: reset_request.token_encrypted,
// Subtract a few seconds in case DB is on separate server and time isn't perfectly synced
expires_at: naive_now() - Duration::seconds(5),
},
)
.await?;
PasswordResetRequest::expire(context.pool(), reset_request.id).await?;
// Update the user with the new password
let password = data.password.clone();

View file

@ -33,25 +33,16 @@ impl Crud for PasswordResetRequest {
.first::<Self>(conn)
.await
}
async fn create(pool: &DbPool, form: &PasswordResetRequestForm) -> Result<Self, Error> {
let conn = &mut get_conn(pool).await?;
// Expire old tokens
// Subtract a few seconds in case DB is on separate server and time isn't perfectly synced
let expire_time = naive_now() - Duration::seconds(5);
diesel::update(
password_reset_request
.filter(local_user_id.eq(&form.local_user_id))
.filter(expires_at.gt(expire_time)),
)
.set(expires_at.eq(expire_time))
.execute(conn)
.await?;
insert_into(password_reset_request)
.values(form)
.get_result::<Self>(conn)
.await
}
async fn update(
pool: &DbPool,
password_reset_request_id: i32,
@ -81,8 +72,12 @@ impl PasswordResetRequest {
expires_at: naive_now() + Duration::days(1),
};
// TODO do this in a transaction along with the new token creation (blocked by https://github.com/LemmyNet/lemmy/issues/1161)
Self::expire_all_for_user(pool, from_local_user_id).await?;
Self::create(pool, &form).await
}
pub async fn read_unexpired_from_token(
pool: &DbPool,
token: &str,
@ -98,6 +93,27 @@ impl PasswordResetRequest {
.await
}
pub async fn expire(pool: &DbPool, password_reset_request_id: i32) -> Result<(), Error> {
let conn = &mut get_conn(pool).await?;
diesel::update(password_reset_request.find(password_reset_request_id))
.filter(expires_at.gt(now))
.set(expires_at.eq(now))
.execute(conn)
.await?;
Ok(())
}
pub async fn expire_all_for_user(pool: &DbPool, user_id: LocalUserId) -> Result<(), Error> {
let conn = &mut get_conn(pool).await?;
diesel::update(password_reset_request)
.filter(local_user_id.eq(user_id.0))
.filter(expires_at.gt(now))
.set(expires_at.eq(now))
.execute(conn)
.await?;
Ok(())
}
pub async fn get_recent_password_resets_count(
pool: &DbPool,
user_id: LocalUserId,