Tell the user if the reset password token is expired.
This commit is contained in:
parent
ed979719b5
commit
37f6de7a89
4 changed files with 34 additions and 25 deletions
|
|
@ -74,12 +74,18 @@ pub enum AuthenticationResult {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GetTokenResetPassword {
|
||||
pub enum GetTokenResetPasswordResult {
|
||||
PasswordAlreadyReset,
|
||||
EmailUnknown,
|
||||
Ok(String),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ResetPasswordResult {
|
||||
ResetTokenExpired,
|
||||
Ok,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Connection {
|
||||
pool: Pool<Sqlite>,
|
||||
|
|
@ -440,7 +446,7 @@ WHERE [id] = $1
|
|||
&self,
|
||||
email: &str,
|
||||
validation_time: Duration,
|
||||
) -> Result<GetTokenResetPassword> {
|
||||
) -> Result<GetTokenResetPasswordResult> {
|
||||
let mut tx = self.tx().await?;
|
||||
|
||||
if let Some(db_datetime_nullable) = sqlx::query_scalar::<_, Option<DateTime<Utc>>>(
|
||||
|
|
@ -456,11 +462,11 @@ WHERE [email] = $1
|
|||
{
|
||||
if let Some(db_datetime) = db_datetime_nullable {
|
||||
if Utc::now() - db_datetime <= validation_time {
|
||||
return Ok(GetTokenResetPassword::PasswordAlreadyReset);
|
||||
return Ok(GetTokenResetPasswordResult::PasswordAlreadyReset);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Ok(GetTokenResetPassword::EmailUnknown);
|
||||
return Ok(GetTokenResetPasswordResult::EmailUnknown);
|
||||
}
|
||||
|
||||
let token = generate_token();
|
||||
|
|
@ -480,7 +486,7 @@ WHERE [email] = $1
|
|||
|
||||
tx.commit().await?;
|
||||
|
||||
Ok(GetTokenResetPassword::Ok(token))
|
||||
Ok(GetTokenResetPasswordResult::Ok(token))
|
||||
}
|
||||
|
||||
pub async fn reset_password(
|
||||
|
|
@ -488,7 +494,7 @@ WHERE [email] = $1
|
|||
new_password: &str,
|
||||
token: &str,
|
||||
validation_time: Duration,
|
||||
) -> Result<()> {
|
||||
) -> Result<ResetPasswordResult> {
|
||||
let mut tx = self.tx().await?;
|
||||
// There is no index on [password_reset_token]. Is it useful?
|
||||
if let (user_id, Some(db_datetime)) = sqlx::query_as::<_, (i64, Option<DateTime<Utc>>)>(
|
||||
|
|
@ -503,9 +509,7 @@ WHERE [password_reset_token] = $1
|
|||
.await?
|
||||
{
|
||||
if Utc::now() - db_datetime > validation_time {
|
||||
return Err(DBError::Other(
|
||||
"Can't reset password: validation time exceeded".to_string(),
|
||||
));
|
||||
return Ok(ResetPasswordResult::ResetTokenExpired);
|
||||
}
|
||||
|
||||
// Remove all login tokens (for security reasons).
|
||||
|
|
@ -530,7 +534,7 @@ WHERE [id] = $1
|
|||
|
||||
tx.commit().await?;
|
||||
|
||||
Ok(())
|
||||
Ok(ResetPasswordResult::Ok)
|
||||
} else {
|
||||
Err(DBError::Other(
|
||||
"Can't reset password: stored token or datetime not set (NULL)".to_string(),
|
||||
|
|
@ -983,7 +987,7 @@ VALUES (
|
|||
.get_token_reset_password(email, Duration::hours(1))
|
||||
.await?
|
||||
{
|
||||
GetTokenResetPassword::EmailUnknown => Ok(()), // Nominal case.
|
||||
GetTokenResetPasswordResult::EmailUnknown => Ok(()), // Nominal case.
|
||||
other => panic!("{:?}", other),
|
||||
}
|
||||
}
|
||||
|
|
@ -1031,7 +1035,7 @@ VALUES (
|
|||
.get_token_reset_password(email, Duration::hours(1))
|
||||
.await?
|
||||
{
|
||||
GetTokenResetPassword::Ok(token) => token,
|
||||
GetTokenResetPasswordResult::Ok(token) => token,
|
||||
other => panic!("{:?}", other),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -574,15 +574,15 @@ pub async fn ask_reset_password_post(
|
|||
)
|
||||
.await
|
||||
{
|
||||
Ok(db::GetTokenResetPassword::PasswordAlreadyReset) => error_response(
|
||||
Ok(db::GetTokenResetPasswordResult::PasswordAlreadyReset) => error_response(
|
||||
AskResetPasswordError::EmailAlreadyReset,
|
||||
&form_data.email,
|
||||
user,
|
||||
),
|
||||
Ok(db::GetTokenResetPassword::EmailUnknown) => {
|
||||
Ok(db::GetTokenResetPasswordResult::EmailUnknown) => {
|
||||
error_response(AskResetPasswordError::EmailUnknown, &form_data.email, user)
|
||||
}
|
||||
Ok(db::GetTokenResetPassword::Ok(token)) => {
|
||||
Ok(db::GetTokenResetPasswordResult::Ok(token)) => {
|
||||
let url = utils::get_url_from_host(&host);
|
||||
match email::send_email(
|
||||
&form_data.email,
|
||||
|
|
@ -663,6 +663,7 @@ pub struct ResetPasswordForm {
|
|||
enum ResetPasswordError {
|
||||
PasswordsNotEqual,
|
||||
InvalidPassword,
|
||||
TokenExpired,
|
||||
DatabaseError,
|
||||
}
|
||||
|
||||
|
|
@ -691,6 +692,7 @@ pub async fn reset_password_post(
|
|||
}
|
||||
.to_string(),
|
||||
message: match error {
|
||||
ResetPasswordError::TokenExpired => "Token expired, try to reset password again",
|
||||
ResetPasswordError::DatabaseError => "Database error",
|
||||
_ => "",
|
||||
}
|
||||
|
|
@ -717,11 +719,14 @@ pub async fn reset_password_post(
|
|||
)
|
||||
.await
|
||||
{
|
||||
Ok(_) => Ok(MessageTemplate {
|
||||
Ok(db::ResetPasswordResult::Ok) => Ok(MessageTemplate {
|
||||
user,
|
||||
message: "Your password has been reset",
|
||||
}
|
||||
.into_response()),
|
||||
Ok(db::ResetPasswordResult::ResetTokenExpired) => {
|
||||
error_response(ResetPasswordError::TokenExpired, &form_data, user)
|
||||
}
|
||||
Err(_) => error_response(ResetPasswordError::DatabaseError, &form_data, user),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<label for="password_field_1">Re-enter password</label>
|
||||
<input id="password_field_2" type="password" name="password_2" />
|
||||
|
||||
|
||||
{{ message_password }}
|
||||
|
||||
<input type="hidden" name="reset_token" value="{{ reset_token }}" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue