use actix::Addr; use actix_web::{HttpResponse, Responder, web}; use uuid::Uuid; use crate::actors::users_actor; use crate::actors::users_actor::UsersActor; use crate::data::current_user::CurrentUser; use crate::data::totp_key::TotpKey; use crate::data::user::{FactorID, TwoFactor, TwoFactorType, User}; #[derive(serde::Deserialize)] pub struct AddTOTPRequest { factor_name: String, secret: String, first_code: String, } pub async fn save_totp_factor(user: CurrentUser, form: web::Json, users: web::Data>) -> impl Responder { let key = TotpKey::from_encoded_secret(&form.secret); if !key.check_code(&form.first_code).unwrap_or(false) { return HttpResponse::BadRequest() .body(format!("Given code is invalid (expected {} or {})!", key.current_code().unwrap_or_default(), key.previous_code().unwrap_or_default())); } if form.factor_name.is_empty() { return HttpResponse::BadRequest().body("Please give a name to the factor!"); } let mut user = User::from(user); user.add_factor(TwoFactor { id: FactorID(Uuid::new_v4().to_string()), name: form.0.factor_name, kind: TwoFactorType::TOTP(key), }); let res = users.send(users_actor::UpdateUserRequest(user)).await.unwrap().0; if !res { HttpResponse::InternalServerError().body("Failed to update user information!") } else { HttpResponse::Ok().body("Added new factor!") } } #[derive(serde::Deserialize)] pub struct DeleteFactorRequest { id: FactorID, } pub async fn delete_factor(user: CurrentUser, form: web::Json, users: web::Data>) -> impl Responder { let mut user = User::from(user); user.remove_factor(form.0.id); let res = users.send(users_actor::UpdateUserRequest(user)).await.unwrap().0; if !res { HttpResponse::InternalServerError().body("Failed to update user information!") } else { HttpResponse::Ok().body("Removed factor!") } }