Files
BasicOIDC/src/data/current_user.rs

87 lines
2.4 KiB
Rust

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<u64>,
}
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<CurrentUser> 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<Box<dyn Future<Output = Result<Self, Self::Error>>>>;
fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
let user_actor: &web::Data<Addr<UsersActor>> =
req.app_data().expect("UserActor undefined!");
let user_actor: Addr<UsersActor> = 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,
})
})
}
}