From 257e20b97194ab33deb86d0d47b44866f9274b1b Mon Sep 17 00:00:00 2001 From: "Helmut K. C. Tessarek" Date: Mon, 30 Jun 2025 19:18:57 -0400 Subject: [PATCH] fix: clippy warnings and formatting --- src/api/core/two_factor/webauthn.rs | 88 +++++++++++++++++++---------- src/api/identity.rs | 6 +- src/db/models/two_factor.rs | 18 +++--- src/main.rs | 2 +- 4 files changed, 72 insertions(+), 42 deletions(-) diff --git a/src/api/core/two_factor/webauthn.rs b/src/api/core/two_factor/webauthn.rs index 8b33b685..26d11705 100644 --- a/src/api/core/two_factor/webauthn.rs +++ b/src/api/core/two_factor/webauthn.rs @@ -1,15 +1,3 @@ -use std::str::FromStr; -use std::sync::Arc; -use std::time::Duration; -use once_cell::sync::Lazy; -use rocket::serde::json::Json; -use rocket::Route; -use serde_json::Value; -use url::Url; -use uuid::Uuid; -use webauthn_rs::{Webauthn, WebauthnBuilder}; -use webauthn_rs::prelude::{Base64UrlSafeData, Passkey, PasskeyAuthentication, PasskeyRegistration}; -use webauthn_rs_proto::{AuthenticationExtensionsClientOutputs, AuthenticatorAssertionResponseRaw, AuthenticatorAttestationResponseRaw, PublicKeyCredential, RegisterPublicKeyCredential, RegistrationExtensionsClientOutputs, RequestAuthenticationExtensions, UserVerificationPolicy}; use crate::{ api::{ core::{log_user_event, two_factor::_generate_recover_code}, @@ -24,6 +12,22 @@ use crate::{ util::NumberOrString, CONFIG, }; +use once_cell::sync::Lazy; +use rocket::serde::json::Json; +use rocket::Route; +use serde_json::Value; +use std::str::FromStr; +use std::sync::Arc; +use std::time::Duration; +use url::Url; +use uuid::Uuid; +use webauthn_rs::prelude::{Base64UrlSafeData, Passkey, PasskeyAuthentication, PasskeyRegistration}; +use webauthn_rs::{Webauthn, WebauthnBuilder}; +use webauthn_rs_proto::{ + AuthenticationExtensionsClientOutputs, AuthenticatorAssertionResponseRaw, AuthenticatorAttestationResponseRaw, + PublicKeyCredential, RegisterPublicKeyCredential, RegistrationExtensionsClientOutputs, + RequestAuthenticationExtensions, UserVerificationPolicy, +}; pub static WEBAUTHN_2FA_CONFIG: Lazy> = Lazy::new(|| { let domain = CONFIG.domain(); @@ -31,10 +35,8 @@ pub static WEBAUTHN_2FA_CONFIG: Lazy> = Lazy::new(|| { let rp_id = Url::parse(&domain).map(|u| u.domain().map(str::to_owned)).ok().flatten().unwrap_or_default(); let rp_origin = Url::parse(&domain_origin).unwrap(); - let webauthn = WebauthnBuilder::new( - &rp_id, - &rp_origin, - ).expect("Creating WebauthnBuilder failed") + let webauthn = WebauthnBuilder::new(&rp_id, &rp_origin) + .expect("Creating WebauthnBuilder failed") .rp_name(&domain) .timeout(Duration::from_millis(60000)); @@ -110,7 +112,12 @@ async fn get_webauthn(data: Json, headers: Headers, mut conn: } #[post("/two-factor/get-webauthn-challenge", data = "")] -async fn generate_webauthn_challenge(data: Json, headers: Headers, webauthn: Webauthn2FaConfig<'_>, mut conn: DbConn) -> JsonResult { +async fn generate_webauthn_challenge( + data: Json, + headers: Headers, + webauthn: Webauthn2FaConfig<'_>, + mut conn: DbConn, +) -> JsonResult { let data: PasswordOrOtpData = data.into_inner(); let user = headers.user; @@ -233,7 +240,12 @@ impl From for PublicKeyCredential { } #[post("/two-factor/webauthn", data = "")] -async fn activate_webauthn(data: Json, headers: Headers, webauthn: Webauthn2FaConfig<'_>, mut conn: DbConn) -> JsonResult { +async fn activate_webauthn( + data: Json, + headers: Headers, + webauthn: Webauthn2FaConfig<'_>, + mut conn: DbConn, +) -> JsonResult { let data: EnableWebauthnData = data.into_inner(); let mut user = headers.user; @@ -256,8 +268,7 @@ async fn activate_webauthn(data: Json, headers: Headers, web }; // Verify the credentials with the saved state - let credential = webauthn - .finish_passkey_registration(&data.device_response.into(), &state)?; + let credential = webauthn.finish_passkey_registration(&data.device_response.into(), &state)?; let mut registrations: Vec<_> = get_webauthn_registrations(&user.uuid, &mut conn).await?.1; // TODO: Check for repeated ID's @@ -286,7 +297,12 @@ async fn activate_webauthn(data: Json, headers: Headers, web } #[put("/two-factor/webauthn", data = "")] -async fn activate_webauthn_put(data: Json, headers: Headers, webauthn: Webauthn2FaConfig<'_>, conn: DbConn) -> JsonResult { +async fn activate_webauthn_put( + data: Json, + headers: Headers, + webauthn: Webauthn2FaConfig<'_>, + conn: DbConn, +) -> JsonResult { activate_webauthn(data, headers, webauthn, conn).await } @@ -357,10 +373,13 @@ pub async fn get_webauthn_registrations( } } -pub async fn generate_webauthn_login(user_id: &UserId, webauthn: Webauthn2FaConfig<'_>, conn: &mut DbConn) -> JsonResult { +pub async fn generate_webauthn_login( + user_id: &UserId, + webauthn: Webauthn2FaConfig<'_>, + conn: &mut DbConn, +) -> JsonResult { // Load saved credentials - let creds: Vec<_> = - get_webauthn_registrations(user_id, conn).await?.1.into_iter().map(|r| r.credential).collect(); + let creds: Vec<_> = get_webauthn_registrations(user_id, conn).await?.1.into_iter().map(|r| r.credential).collect(); if creds.is_empty() { err!("No Webauthn devices registered") @@ -377,11 +396,15 @@ pub async fn generate_webauthn_login(user_id: &UserId, webauthn: Webauthn2FaConf // Add appid let app_id = format!("{}/app-id.json", &CONFIG.domain()); state["ast"]["appid"] = Value::String(app_id.clone()); - response.public_key.extensions.get_or_insert_with(|| RequestAuthenticationExtensions { - appid: None, - uvm: None, - hmac_get_secret: None, - }).appid = Some(app_id); + response + .public_key + .extensions + .get_or_insert(RequestAuthenticationExtensions { + appid: None, + uvm: None, + hmac_get_secret: None, + }) + .appid = Some(app_id); // Save the challenge state for later validation TwoFactor::new(user_id.clone(), TwoFactorType::WebauthnLoginChallenge, serde_json::to_string(&state)?) @@ -392,7 +415,12 @@ pub async fn generate_webauthn_login(user_id: &UserId, webauthn: Webauthn2FaConf Ok(Json(serde_json::to_value(response.public_key)?)) } -pub async fn validate_webauthn_login(user_id: &UserId, response: &str, webauthn: Webauthn2FaConfig<'_>, conn: &mut DbConn) -> EmptyResult { +pub async fn validate_webauthn_login( + user_id: &UserId, + response: &str, + webauthn: Webauthn2FaConfig<'_>, + conn: &mut DbConn, +) -> EmptyResult { let type_ = TwoFactorType::WebauthnLoginChallenge as i32; let state = match TwoFactor::find_by_user_and_type(user_id, type_, conn).await { Some(tf) => { diff --git a/src/api/identity.rs b/src/api/identity.rs index 761d4e9c..573210e7 100644 --- a/src/api/identity.rs +++ b/src/api/identity.rs @@ -7,6 +7,7 @@ use rocket::{ }; use serde_json::Value; +use crate::api::core::two_factor::webauthn::Webauthn2FaConfig; use crate::{ api::{ core::{ @@ -23,7 +24,6 @@ use crate::{ error::MapResult, mail, util, CONFIG, }; -use crate::api::core::two_factor::webauthn::Webauthn2FaConfig; pub fn routes() -> Vec { routes![login, prelogin, identity_register, register_verification_email, register_finish] @@ -528,7 +528,9 @@ async fn twofactor_auth( Some(TwoFactorType::Authenticator) => { authenticator::validate_totp_code_str(&user.uuid, twofactor_code, &selected_data?, ip, conn).await? } - Some(TwoFactorType::Webauthn) => webauthn::validate_webauthn_login(&user.uuid, twofactor_code, webauthn, conn).await?, + Some(TwoFactorType::Webauthn) => { + webauthn::validate_webauthn_login(&user.uuid, twofactor_code, webauthn, conn).await? + } Some(TwoFactorType::YubiKey) => yubikey::validate_yubikey_login(twofactor_code, &selected_data?).await?, Some(TwoFactorType::Duo) => { match CONFIG.duo_use_iframe() { diff --git a/src/db/models/two_factor.rs b/src/db/models/two_factor.rs index f6d646c7..b71bb1af 100644 --- a/src/db/models/two_factor.rs +++ b/src/db/models/two_factor.rs @@ -1,9 +1,9 @@ +use super::UserId; +use crate::api::core::two_factor::webauthn::WebauthnRegistration; +use crate::{api::EmptyResult, db::DbConn, error::MapResult}; use serde_json::Value; use webauthn_rs::prelude::{Credential, ParsedAttestation}; use webauthn_rs_proto::{AttestationFormat, RegisteredExtensions}; -use super::UserId; -use crate::{api::EmptyResult, db::DbConn, error::MapResult}; -use crate::api::core::two_factor::webauthn::WebauthnRegistration; db_object! { #[derive(Identifiable, Queryable, Insertable, AsChangeset)] @@ -333,7 +333,8 @@ impl TwoFactor { extensions: RegisteredExtensions::none(), attestation: ParsedAttestation::default(), attestation_format: AttestationFormat::None, - }.into(), + } + .into(), }; webauthn_regs.push(new_reg); @@ -364,19 +365,18 @@ impl TwoFactor { for webauthn_factor in webauthn_factors { // assume that a failure to parse into the old struct, means that it was already converted // alternatively this could also be checked via an extra field in the db - let Ok(regs) = serde_json::from_str::>(&webauthn_factor.data) else { + let Ok(regs) = serde_json::from_str::>(&webauthn_factor.data) + else { continue; }; - let regs = regs.into_iter() - .map(|r| r.into()) - .collect::>(); + let regs = regs.into_iter().map(|r| r.into()).collect::>(); TwoFactor::new(webauthn_factor.user_uuid.clone(), TwoFactorType::Webauthn, serde_json::to_string(®s)?) .save(conn) .await?; } - + Ok(()) } } diff --git a/src/main.rs b/src/main.rs index c9a2b4c5..b4093bc4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,6 +59,7 @@ mod ratelimit; mod util; use crate::api::core::two_factor::duo_oidc::purge_duo_contexts; +use crate::api::core::two_factor::webauthn::WEBAUTHN_2FA_CONFIG; use crate::api::purge_auth_requests; use crate::api::{WS_ANONYMOUS_SUBSCRIPTIONS, WS_USERS}; pub use config::{PathType, CONFIG}; @@ -66,7 +67,6 @@ pub use error::{Error, MapResult}; use rocket::data::{Limits, ToByteUnit}; use std::sync::{atomic::Ordering, Arc}; pub use util::is_running_in_container; -use crate::api::core::two_factor::webauthn::WEBAUTHN_2FA_CONFIG; #[rocket::main] async fn main() -> Result<(), Error> {