From cc4a8a962bb2215fa51feeca5a077175a5ed8cc9 Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Sat, 12 Nov 2022 11:50:32 +0100 Subject: [PATCH] User can delete his own 2FA login history --- src/actors/users_actor.rs | 11 ++++ src/controllers/two_factor_api.rs | 12 +++++ src/data/user.rs | 7 +++ src/main.rs | 5 ++ templates/settings/two_factors_page.html | 65 ++++++++++++++++-------- 5 files changed, 80 insertions(+), 20 deletions(-) diff --git a/src/actors/users_actor.rs b/src/actors/users_actor.rs index 8f9c9d8..76d8eb8 100644 --- a/src/actors/users_actor.rs +++ b/src/actors/users_actor.rs @@ -55,6 +55,10 @@ pub struct ChangePasswordResult(pub bool); #[rtype(result = "bool")] pub struct AddSuccessful2FALogin(pub UserID, pub IpAddr); +#[derive(Message)] +#[rtype(result = "bool")] +pub struct Clear2FALoginHistory(pub UserID); + #[derive(Debug)] pub struct UpdateUserResult(pub bool); @@ -125,6 +129,13 @@ impl Handler for UsersActor { } } +impl Handler for UsersActor { + type Result = ::Result; + fn handle(&mut self, msg: Clear2FALoginHistory, _ctx: &mut Self::Context) -> Self::Result { + self.manager.clear_2fa_login_history(&msg.0) + } +} + impl Handler for UsersActor { type Result = MessageResult; diff --git a/src/controllers/two_factor_api.rs b/src/controllers/two_factor_api.rs index 1326d46..2703762 100644 --- a/src/controllers/two_factor_api.rs +++ b/src/controllers/two_factor_api.rs @@ -120,3 +120,15 @@ pub async fn delete_factor( HttpResponse::Ok().body("Removed factor!") } } + +pub async fn clear_login_history( + user: CurrentUser, + users: web::Data>, +) -> impl Responder { + users + .send(users_actor::Clear2FALoginHistory(user.uid.clone())) + .await + .unwrap(); + + HttpResponse::Ok().body("History successfully cleared") +} diff --git a/src/data/user.rs b/src/data/user.rs index 1394a84..4fe7c17 100644 --- a/src/data/user.rs +++ b/src/data/user.rs @@ -313,4 +313,11 @@ impl EntityManager { user }) } + + pub fn clear_2fa_login_history(&mut self, id: &UserID) -> bool { + self.update_user(id, |mut user| { + user.last_successful_2fa = Default::default(); + user + }) + } } diff --git a/src/main.rs b/src/main.rs index f642622..4243b19 100644 --- a/src/main.rs +++ b/src/main.rs @@ -192,6 +192,11 @@ async fn main() -> std::io::Result<()> { "/settings/api/two_factor/delete_factor", web::post().to(two_factor_api::delete_factor), ) + .route( + "/settings/api/two_factor/clear_login_history", + // Use POST to prevent CSRF + web::post().to(two_factor_api::clear_login_history), + ) // Admin routes .route( "/admin", diff --git a/templates/settings/two_factors_page.html b/templates/settings/two_factors_page.html index 87ea375..f7a34cc 100644 --- a/templates/settings/two_factors_page.html +++ b/templates/settings/two_factors_page.html @@ -35,26 +35,31 @@ {% if !user.last_successful_2fa.is_empty() %} -
Successful 2FA login history
- - - - - - - - - - {% for e in user.get_formatted_2fa_successful_logins() %} - - - - - - {% endfor %} - -
IP addressDateBypass 2FA
{{ e.ip }}{{ e.fmt_time() }}{% if e.can_bypass_2fa %}YES{% else %}NO{% endif %}
-{% endif %} +
+
Successful 2FA login history
+

+ Clear history +

+ + + + + + + + + + {% for e in user.get_formatted_2fa_successful_logins() %} + + + + + + {% endfor %} + +
IP addressDateBypass 2FA
{{ e.ip }}{{ e.fmt_time() }}{% if e.can_bypass_2fa %}YES{% else %}NO{% endif %}
+ {% endif %} +
{% endblock content %}