use serde::{Deserialize, Serialize};
use crate::{
ctap2::AuthenticatorData,
webauthn::{PublicKeyCredentialDescriptor, PublicKeyCredentialUserEntity},
Bytes,
};
pub use crate::ctap2::make_credential::Options;
#[cfg(doc)]
use {
crate::webauthn::{CollectedClientData, PublicKeyCredentialRequestOptions},
ciborium::value::Value,
};
use super::extensions::{AuthenticatorPrfGetOutputs, AuthenticatorPrfInputs, HmacGetSecretInput};
serde_workaround! {
#[derive(Debug)]
pub struct Request {
#[serde(rename = 0x01)]
pub rp_id: String,
#[serde(rename = 0x02)]
pub client_data_hash: Bytes,
#[serde(rename = 0x03, default, skip_serializing_if = Option::is_none)]
pub allow_list: Option<Vec<PublicKeyCredentialDescriptor>>,
#[serde(rename = 0x04, default, skip_serializing_if = Option::is_none)]
pub extensions: Option<ExtensionInputs>,
#[serde(rename = 0x05, default)]
pub options: Options,
#[serde(rename = 0x06, default, skip_serializing_if = Option::is_none)]
pub pin_auth: Option<Bytes>,
#[serde(rename = 0x07, default, skip_serializing_if = Option::is_none)]
pub pin_protocol: Option<u8>,
}
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ExtensionInputs {
#[serde(
rename = "hmac-secret",
default,
skip_serializing_if = "Option::is_none"
)]
pub hmac_secret: Option<HmacGetSecretInput>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub prf: Option<AuthenticatorPrfInputs>,
}
impl ExtensionInputs {
pub fn zip_contents(self) -> Option<Self> {
let Self { hmac_secret, prf } = &self;
let has_hmac_secret = hmac_secret.is_some();
let has_prf = prf.is_some();
(has_hmac_secret || has_prf).then_some(self)
}
}
serde_workaround! {
#[derive(Debug)]
pub struct Response {
#[serde(rename = 0x01, default, skip_serializing_if = Option::is_none)]
pub credential: Option<PublicKeyCredentialDescriptor>,
#[serde(rename = 0x02)]
pub auth_data: AuthenticatorData,
#[serde(rename = 0x03)]
pub signature: Bytes,
#[serde(rename = 0x04, default, skip_serializing_if = Option::is_none)]
pub user: Option<PublicKeyCredentialUserEntity>,
#[serde(rename = 0x05, default, skip_serializing_if = Option::is_none)]
pub number_of_credentials: Option<u8>,
#[serde(rename = 0x06, default, skip_serializing_if = Option::is_none)]
pub user_selected: Option<bool>,
#[serde(rename = 0x07, default, skip_serializing_if = Option::is_none)]
pub large_blob_key: Option<Bytes>,
#[serde(rename = 0x08, default, skip_serializing_if = Option::is_none)]
pub unsigned_extension_outputs: Option<UnsignedExtensionOutputs>,
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SignedExtensionOutputs {
#[serde(
rename = "hmac-secret",
default,
skip_serializing_if = "Option::is_none"
)]
pub hmac_secret: Option<Bytes>,
}
impl SignedExtensionOutputs {
pub fn zip_contents(self) -> Option<Self> {
let Self { hmac_secret } = &self;
hmac_secret.is_some().then_some(self)
}
}
#[derive(Debug, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct UnsignedExtensionOutputs {
pub prf: Option<AuthenticatorPrfGetOutputs>,
}
impl UnsignedExtensionOutputs {
pub fn zip_contents(self) -> Option<Self> {
let Self { prf } = &self;
prf.is_some().then_some(self)
}
}