104 lines
3.4 KiB
Rust
104 lines
3.4 KiB
Rust
use actix::Addr;
|
|
use actix_web::{HttpResponse, Responder, web};
|
|
use uuid::Uuid;
|
|
use webauthn_rs::proto::RegisterPublicKeyCredential;
|
|
|
|
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};
|
|
use crate::data::webauthn_manager::WebAuthManagerReq;
|
|
|
|
#[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<AddTOTPRequest>,
|
|
users: web::Data<Addr<UsersActor>>) -> 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 AddWebauthnRequest {
|
|
opaque_state: String,
|
|
factor_name: String,
|
|
credential: RegisterPublicKeyCredential,
|
|
}
|
|
|
|
pub async fn save_webauthn_factor(user: CurrentUser, form: web::Json<AddWebauthnRequest>,
|
|
users: web::Data<Addr<UsersActor>>,
|
|
manager: WebAuthManagerReq) -> impl Responder {
|
|
let key = match manager.finish_registration(
|
|
&user,
|
|
&form.0.opaque_state,
|
|
form.0.credential,
|
|
) {
|
|
Ok(k) => k,
|
|
Err(e) => {
|
|
log::error!("Failed to register security key! {:?}", e);
|
|
return HttpResponse::InternalServerError().body("Failed to register key!");
|
|
}
|
|
};
|
|
|
|
let mut user = User::from(user);
|
|
user.add_factor(TwoFactor {
|
|
id: FactorID(Uuid::new_v4().to_string()),
|
|
name: form.0.factor_name,
|
|
kind: TwoFactorType::WEBAUTHN(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<DeleteFactorRequest>,
|
|
users: web::Data<Addr<UsersActor>>) -> 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!")
|
|
}
|
|
} |