Add a page to choose second factor
This commit is contained in:
@ -11,6 +11,7 @@ use crate::controllers::base_controller::{FatalErrorPage, redirect_user, redirec
|
||||
use crate::data::login_redirect_query::LoginRedirectQuery;
|
||||
use crate::data::remote_ip::RemoteIP;
|
||||
use crate::data::session_identity::{SessionIdentity, SessionStatus};
|
||||
use crate::data::user::{TwoFactor, User};
|
||||
|
||||
struct BaseLoginPage {
|
||||
danger: Option<String>,
|
||||
@ -34,6 +35,14 @@ struct PasswordResetTemplate {
|
||||
min_pass_len: usize,
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "login/choose_second_factor.html")]
|
||||
struct ChooseSecondFactorTemplate<'a> {
|
||||
_p: BaseLoginPage,
|
||||
factors: &'a [TwoFactor],
|
||||
}
|
||||
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct LoginRequestBody {
|
||||
login: String,
|
||||
@ -87,6 +96,11 @@ pub async fn login_route(
|
||||
return redirect_user(&format!("/reset_password?redirect={}", query.redirect.get_encoded()));
|
||||
}
|
||||
|
||||
// Check if the user has to valide a second factor
|
||||
if SessionIdentity(&id).need_2fa_auth() {
|
||||
return redirect_user(&format!("/2fa_auth?redirect={}", query.redirect.get_encoded()));
|
||||
}
|
||||
|
||||
// Try to authenticate user
|
||||
if let Some(req) = &req {
|
||||
login = req.login.clone();
|
||||
@ -105,6 +119,9 @@ pub async fn login_route(
|
||||
return if user.need_reset_password {
|
||||
SessionIdentity(&id).set_status(SessionStatus::NeedNewPassword);
|
||||
redirect_user(&format!("/reset_password?redirect={}", query.redirect.get_encoded()))
|
||||
} else if user.has_two_factor() {
|
||||
SessionIdentity(&id).set_status(SessionStatus::Need2FA);
|
||||
redirect_user(&format!("/2fa_auth?redirect={}", query.redirect.get_encoded()))
|
||||
} else {
|
||||
redirect_user(query.redirect.get())
|
||||
};
|
||||
@ -159,7 +176,7 @@ pub struct PasswordResetQuery {
|
||||
/// Reset user password route
|
||||
pub async fn reset_password_route(id: Identity, query: web::Query<PasswordResetQuery>,
|
||||
req: Option<web::Form<ChangePasswordRequestBody>>,
|
||||
users: web::Data<Addr<UsersActor>>, ) -> impl Responder {
|
||||
users: web::Data<Addr<UsersActor>>) -> impl Responder {
|
||||
let mut danger = None;
|
||||
|
||||
if !SessionIdentity(&id).need_new_password() {
|
||||
@ -203,4 +220,37 @@ pub async fn reset_password_route(id: Identity, query: web::Query<PasswordResetQ
|
||||
.render()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct ChooseSecondFactorQuery {
|
||||
#[serde(default)]
|
||||
redirect: LoginRedirectQuery,
|
||||
}
|
||||
|
||||
|
||||
/// Let the user select the factor to use to authenticate
|
||||
pub async fn choose_2fa_method(id: Identity, query: web::Query<ChooseSecondFactorQuery>,
|
||||
users: web::Data<Addr<UsersActor>>) -> impl Responder {
|
||||
if !SessionIdentity(&id).need_2fa_auth() {
|
||||
return redirect_user_for_login(query.redirect.get());
|
||||
}
|
||||
|
||||
let user: User = users.send(users_actor::GetUserRequest(SessionIdentity(&id).user_id()))
|
||||
.await.unwrap().0.expect("Could not find user!");
|
||||
|
||||
HttpResponse::Ok().content_type("text/html").body(
|
||||
ChooseSecondFactorTemplate {
|
||||
_p: BaseLoginPage {
|
||||
page_title: "Two factor authentication",
|
||||
danger: None,
|
||||
success: None,
|
||||
app_name: APP_NAME,
|
||||
redirect_uri: query.redirect.get_encoded(),
|
||||
},
|
||||
factors: &user.two_factor,
|
||||
}
|
||||
.render()
|
||||
.unwrap(),
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user