From f8afea4e709543ec13406f84ca89afde095f373e Mon Sep 17 00:00:00 2001
From: Philippe Loctaux
Date: Wed, 3 May 2023 23:46:40 +0200
Subject: [PATCH] admin/users: force password reset (now lasts for 24 hours),
send email, show expiration
---
Cargo.lock | 10 +
.../email/templates/password-reset.mjml.tera | 2 +-
crates/ezidam/Cargo.toml | 1 +
crates/ezidam/src/routes/admin.rs | 2 +
crates/ezidam/src/routes/admin/users.rs | 195 +++++++++++++++++-
.../ezidam/src/routes/root/forgot_password.rs | 12 +-
.../ezidam/src/routes/root/reset_password.rs | 2 +-
.../pages/admin/users/view.html.tera | 55 ++++-
crates/users/src/password_reset.rs | 21 +-
9 files changed, 288 insertions(+), 12 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 43756a0..22fc676 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -273,6 +273,15 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "chrono-humanize"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32dce1ea1988dbdf9f9815ff11425828523bd2a134ec0805d2ac8af26ee6096e"
+dependencies = [
+ "chrono",
+]
+
[[package]]
name = "chrono-tz"
version = "0.6.1"
@@ -771,6 +780,7 @@ dependencies = [
"apps",
"authorization_codes",
"base64 0.21.0",
+ "chrono-humanize",
"chrono-tz 0.8.2",
"database_pool",
"email",
diff --git a/crates/email/templates/password-reset.mjml.tera b/crates/email/templates/password-reset.mjml.tera
index 4d743bc..d5c0aa4 100644
--- a/crates/email/templates/password-reset.mjml.tera
+++ b/crates/email/templates/password-reset.mjml.tera
@@ -18,7 +18,7 @@
Reset password
You recently requested to reset the password of your ezidam account.
- Use the button below to reset it. This message will expire in {{ token_duration }} minutes.
+ Use the button below to reset it. This message will expire in {{ token_duration }} hours.
Reset your password
diff --git a/crates/ezidam/Cargo.toml b/crates/ezidam/Cargo.toml
index 9e49214..1507ac0 100644
--- a/crates/ezidam/Cargo.toml
+++ b/crates/ezidam/Cargo.toml
@@ -15,6 +15,7 @@ base64 = "0.21.0"
rocket_cors = "0.6.0-alpha2"
email_address = { workspace = true }
chrono-tz = "0.8.2"
+chrono-humanize = "0.2.2"
# local crates
database_pool = { path = "../database_pool" }
diff --git a/crates/ezidam/src/routes/admin.rs b/crates/ezidam/src/routes/admin.rs
index 5fc13f8..db06a8e 100644
--- a/crates/ezidam/src/routes/admin.rs
+++ b/crates/ezidam/src/routes/admin.rs
@@ -26,6 +26,7 @@ pub fn routes() -> Vec {
admin_users_list,
admin_users_view,
admin_users_archive,
+ admin_users_password_reset,
]
}
@@ -96,5 +97,6 @@ pub mod content {
pub user: JwtClaims,
pub jwt_duration: i64,
pub local: User,
+ pub password_recover_expiration: Option,
}
}
diff --git a/crates/ezidam/src/routes/admin/users.rs b/crates/ezidam/src/routes/admin/users.rs
index c1c79c9..eb85549 100644
--- a/crates/ezidam/src/routes/admin/users.rs
+++ b/crates/ezidam/src/routes/admin/users.rs
@@ -1,10 +1,14 @@
use crate::routes::prelude::*;
+use crate::routes::root::forgot_password::ResetPasswordEmail;
use crate::tokens::JWT_DURATION_MINUTES;
use authorization_codes::AuthorizationCode;
+use chrono_humanize::Humanize;
+use rocket::State;
use rocket::{get, post};
use settings::Settings;
+use url::Url;
use users::totp_login_request::TotpLoginRequest;
-use users::User;
+use users::{password_reset::PasswordResetToken, User};
#[get("/admin/users")]
pub async fn admin_users_list(
@@ -36,10 +40,17 @@ pub async fn admin_users_view(
.await?
.ok_or_else(|| Error::not_found(user_id.to_string()))?;
+ // If user has password reset token
+ let password_recover_expiration = user
+ .password_recover()
+ .map_err(|e| Error::internal_server_error(format!("Password recover: {e}")))?
+ .map(|token| token.expires_at().humanize());
+
let page = Page::AdminUsersView(super::content::AdminUsersView {
user: admin_not_current.0,
jwt_duration: JWT_DURATION_MINUTES,
local: user,
+ password_recover_expiration,
});
Ok(flash
@@ -136,3 +147,185 @@ pub async fn admin_users_archive(
Ok(Flash::new(redirect, flash_kind, flash_message))
}
+
+#[derive(Debug, FromForm)]
+pub struct PasswordResetForm<'r> {
+ pub send_email: Option<&'r str>,
+ pub start_process: Option,
+}
+
+#[post("/admin/users//password_reset", data = "