use std::future::Future; use std::ops::Deref; use std::pin::Pin; use actix::Addr; use actix_identity::Identity; use actix_web::dev::Payload; use actix_web::error::ErrorInternalServerError; use actix_web::{web, Error, FromRequest, HttpRequest}; use crate::actors::users_actor; use crate::actors::users_actor::UsersActor; use crate::constants::SECOND_FACTOR_EXPIRATION_FOR_CRITICAL_OPERATIONS; use crate::data::session_identity::SessionIdentity; use crate::data::user::User; use crate::utils::time::time; pub struct CurrentUser { user: User, pub auth_time: u64, pub last_2fa_auth: Option, } impl CurrentUser { pub fn should_request_2fa_for_critical_functions(&self) -> bool { self.user.has_two_factor() && self .last_2fa_auth .map(|t| t + SECOND_FACTOR_EXPIRATION_FOR_CRITICAL_OPERATIONS < time()) .unwrap_or(true) } } impl From for User { fn from(user: CurrentUser) -> Self { user.user } } impl Deref for CurrentUser { type Target = User; fn deref(&self) -> &Self::Target { &self.user } } impl FromRequest for CurrentUser { type Error = Error; type Future = Pin>>>; fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { let user_actor: &web::Data> = req.app_data().expect("UserActor undefined!"); let user_actor: Addr = user_actor.as_ref().clone(); let identity: Identity = Identity::from_request(req, payload) .into_inner() .expect("Failed to get identity!"); let id = SessionIdentity(Some(&identity)); let user_id = id.user_id(); let last_2fa_auth = id.last_2fa_auth(); let auth_time = id.auth_time(); Box::pin(async move { let user = match user_actor .send(users_actor::GetUserRequest(user_id)) .await .unwrap() .0 { Some(u) => u, None => { return Err(ErrorInternalServerError( "Could not extract user information!", )); } }; Ok(CurrentUser { user, auth_time, last_2fa_auth, }) }) } }