use crate::data::current_user::CurrentUser; use crate::data::session_identity::SessionIdentity; use actix_identity::Identity; use actix_web::dev::Payload; use actix_web::{web, Error, FromRequest, HttpRequest}; use std::future::Future; use std::pin::Pin; #[derive(serde::Deserialize)] pub struct Force2FAAuthQuery { #[serde(default)] force_2fa: bool, } pub struct Force2FAAuth { pub force: bool, } impl FromRequest for Force2FAAuth { type Error = Error; type Future = Pin>>>; fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { let req = req.clone(); Box::pin(async move { // It is impossible to force authentication for an unauthenticated user let identity = Identity::from_request(&req, &mut Payload::None) .into_inner() .ok(); if !SessionIdentity(identity.as_ref()).is_authenticated() { return Ok(Self { force: false }); } let query = web::Query::::from_request(&req, &mut Payload::None) .into_inner()?; let user = CurrentUser::from_request(&req, &mut Payload::None).await?; Ok(Self { force: query.force_2fa && user.has_two_factor(), }) }) } }