Can request new user password on login

This commit is contained in:
2022-04-02 08:30:01 +02:00
parent 0f4a5cde57
commit 4b8c9fdfdc
7 changed files with 222 additions and 11 deletions

View File

@ -46,6 +46,17 @@ impl<E> EntityManager<E> where E: serde::Serialize + serde::de::DeserializeOwned
self.save()
}
/// Replace entries in the list that matches a criteria
pub fn replace_entries<F>(&mut self, filter: F, el: &E) -> Res where F: Fn(&E) -> bool {
for i in 0..self.list.len() {
if filter(&self.list[i]) {
self.list[i] = el.clone();
}
}
self.save()
}
/// Iterate over the entries of this entity manager
pub fn iter(&self) -> Iter<'_, E> {
self.list.iter()

View File

@ -6,18 +6,28 @@ use crate::data::user::User;
use crate::utils::time::time;
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
enum SessionStatus {
pub enum SessionStatus {
Invalid,
SignedIn,
NeedNewPassword,
NeedMFA,
}
#[derive(Debug, Serialize, Deserialize)]
impl Default for SessionStatus {
fn default() -> Self {
Self::Invalid
}
}
#[derive(Debug, Serialize, Deserialize, Default)]
struct SessionIdentityData {
pub id: String,
pub is_admin: bool,
last_access: u64,
pub status: SessionStatus,
// TODO : add session max duration (1 day)
}
pub struct SessionIdentity<'a>(pub &'a Identity);
@ -39,6 +49,13 @@ impl<'a> SessionIdentity<'a> {
.map(serde_json::from_str)
.map(|f| f.expect("Failed to deserialize session data!"));
// Check if session is valid
if let Some(sess) = &res {
if sess.id.is_empty() {
return None;
}
}
if let Some(session) = res.as_mut() {
if session.last_access + MAX_SESSION_DURATION < time() {
log::info!("Session is expired for {}", session.id);
@ -63,9 +80,27 @@ impl<'a> SessionIdentity<'a> {
self.0.remember(s);
}
pub fn set_status(&self, status: SessionStatus) {
let mut sess = self.get_session_data().unwrap_or_default();
sess.status = status;
self.set_session_data(&sess);
}
pub fn is_authenticated(&self) -> bool {
self.get_session_data()
.map(|s| s.status == SessionStatus::SignedIn)
.unwrap_or(false)
}
pub fn need_new_password(&self) -> bool {
self.get_session_data()
.map(|s| s.status == SessionStatus::NeedNewPassword)
.unwrap_or(false)
}
pub fn user_id(&self) -> String {
self.get_session_data()
.unwrap_or_default()
.id
}
}

View File

@ -2,9 +2,11 @@ use crate::data::entity_manager::EntityManager;
use crate::data::service::ServiceID;
use crate::utils::err::Res;
pub type UserID = String;
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct User {
pub uid: String,
pub uid: UserID,
pub first_name: String,
pub last_last: String,
pub username: String,
@ -67,4 +69,44 @@ impl EntityManager<User> {
}
None
}
pub fn find_by_user_id(&self, id: &UserID) -> Option<User> {
for entry in self.iter() {
if entry.uid.eq(id) {
return Some(entry.clone());
}
}
None
}
/// Update user information
fn update_user<F>(&mut self, id: &UserID, update: F) -> bool where F: FnOnce(User) -> User {
let user = match self.find_by_user_id(id) {
None => return false,
Some(user) => user
};
if let Err(e) = self.replace_entries(|u| u.uid.eq(id), &update(user)) {
log::error!("Failed to update user information! {:?}", e);
return false;
}
true
}
pub fn change_user_password(&mut self, id: &UserID, password: &str, temporary: bool) -> bool {
let new_hash = match hash_password(password) {
Ok(h) => { h }
Err(e) => {
log::error!("Failed to hash user password! {}", e);
return false;
}
};
self.update_user(id, |mut user| {
user.password = new_hash;
user.need_reset_password = temporary;
user
})
}
}