Can clear 2FA login history from edit_user page
This commit is contained in:
@ -60,6 +60,7 @@ pub struct UpdateUserQuery {
|
||||
grant_type: String,
|
||||
granted_clients: String,
|
||||
two_factor: String,
|
||||
clear_2fa_history: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn users_route(
|
||||
@ -114,10 +115,15 @@ pub async fn users_route(
|
||||
let temp_pass = rand_str(TEMPORARY_PASSWORDS_LEN);
|
||||
user.password = hash_password(&temp_pass).expect("Failed to hash password");
|
||||
user.need_reset_password = true;
|
||||
user.last_successful_2fa = Default::default();
|
||||
Some(temp_pass)
|
||||
}
|
||||
};
|
||||
|
||||
if update.0.clear_2fa_history.is_some() {
|
||||
user.last_successful_2fa = Default::default();
|
||||
}
|
||||
|
||||
let res = users
|
||||
.send(users_actor::UpdateUserRequest(user.clone()))
|
||||
.await
|
||||
|
@ -1,3 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
use std::net::IpAddr;
|
||||
|
||||
use crate::constants::SECOND_FACTOR_EXEMPTION_AFTER_SUCCESSFUL_LOGIN;
|
||||
use crate::data::client::ClientID;
|
||||
use crate::data::entity_manager::EntityManager;
|
||||
@ -5,9 +8,7 @@ use crate::data::login_redirect::LoginRedirect;
|
||||
use crate::data::totp_key::TotpKey;
|
||||
use crate::data::webauthn_manager::WebauthnPubKey;
|
||||
use crate::utils::err::Res;
|
||||
use crate::utils::time::time;
|
||||
use std::collections::HashMap;
|
||||
use std::net::IpAddr;
|
||||
use crate::utils::time::{fmt_time, time};
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct UserID(pub String);
|
||||
@ -64,6 +65,19 @@ impl TwoFactor {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Successful2FALogin {
|
||||
pub ip: IpAddr,
|
||||
pub time: u64,
|
||||
pub can_bypass_2fa: bool,
|
||||
}
|
||||
|
||||
impl Successful2FALogin {
|
||||
pub fn fmt_time(&self) -> String {
|
||||
fmt_time(self.time)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct User {
|
||||
pub uid: UserID,
|
||||
@ -175,6 +189,17 @@ impl User {
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub fn get_formatted_2fa_successful_logins(&self) -> Vec<Successful2FALogin> {
|
||||
self.last_successful_2fa
|
||||
.iter()
|
||||
.map(|(ip, time)| Successful2FALogin {
|
||||
ip: *ip,
|
||||
time: *time,
|
||||
can_bypass_2fa: self.can_bypass_two_factors_for_ip(*ip),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for User {
|
||||
@ -268,6 +293,7 @@ impl EntityManager<User> {
|
||||
self.update_user(id, |mut user| {
|
||||
user.password = new_hash;
|
||||
user.need_reset_password = temporary;
|
||||
user.two_factor_exemption_after_successful_login = Default::default();
|
||||
user
|
||||
})
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
/// Get the current time since epoch
|
||||
@ -7,3 +8,16 @@ pub fn time() -> u64 {
|
||||
.unwrap()
|
||||
.as_secs()
|
||||
}
|
||||
|
||||
/// Format unix timestamp to a human-readable string
|
||||
pub fn fmt_time(timestamp: u64) -> String {
|
||||
// Create a NaiveDateTime from the timestamp
|
||||
let naive =
|
||||
NaiveDateTime::from_timestamp_opt(timestamp as i64, 0).expect("Failed to parse timestamp!");
|
||||
|
||||
// Create a normal DateTime from the NaiveDateTime
|
||||
let datetime: DateTime<Utc> = DateTime::from_utc(naive, Utc);
|
||||
|
||||
// Format the datetime how you want
|
||||
datetime.format("%Y-%m-%d %H:%M:%S").to_string()
|
||||
}
|
||||
|
Reference in New Issue
Block a user