use actix::Addr; use actix_identity::Identity; use actix_web::{HttpResponse, Responder, web}; use askama::Template; use crate::actors::users_actor::{LoginResult, UsersActor}; use crate::actors::users_actor; use crate::constants::APP_NAME; use crate::controllers::base_controller::redirect_user; use crate::data::session_identity::SessionIdentity; #[derive(Template)] #[template(path = "base_login_page.html")] struct BaseLoginPage { danger: String, success: String, page_title: &'static str, app_name: &'static str, } #[derive(Template)] #[template(path = "login.html")] struct LoginTemplate { _parent: BaseLoginPage, login: String, } #[derive(serde::Deserialize)] pub struct LoginRequestBody { login: String, password: String, } #[derive(serde::Deserialize)] pub struct LoginRequestQuery { logout: Option, } /// Authenticate user pub async fn login_route(users: web::Data>, query: web::Query, req: Option>, id: Identity) -> impl Responder { let mut danger = String::new(); let mut success = String::new(); let mut login = String::new(); // Check if user session must be closed if let Some(true) = query.logout { id.forget(); success = "Goodbye!".to_string(); } // Check if user is already authenticated if SessionIdentity::is_authenticated(&id) { return redirect_user("/"); } // Try to authenticate user if let Some(req) = &req { // TODO : check request origin login = req.login.clone(); let response: LoginResult = users.send(users_actor::LoginRequest { login: login.clone(), password: req.password.clone(), }).await.unwrap(); match response { LoginResult::Success(user) => { id.remember(SessionIdentity::from_user(&user).serialize()); return redirect_user("/"); } c => { // TODO : add bruteforce detection log::warn!("Failed login for username {} : {:?}", login, c); danger = "Login failed.".to_string(); } } } HttpResponse::Ok() .content_type("text/html") .body(LoginTemplate { _parent: BaseLoginPage { page_title: "Login", danger, success, app_name: APP_NAME, }, login, }.render().unwrap()) } /// Sign out user pub async fn logout_route() -> impl Responder { redirect_user("/login?logout=true") }