use std::{borrow::Cow, ops::Deref};
use coset::CoseKey;
use passkey_types::{
CredentialExtensions,
webauthn::{AuthenticatorTransport, PublicKeyCredentialDescriptor, PublicKeyCredentialType},
};
#[cfg(doc)]
use passkey_types::Passkey;
pub trait PasskeyAccessor {
fn key(&self) -> Cow<'_, CoseKey>;
fn credential_id(&self) -> &[u8];
fn rp_id(&self) -> &str;
fn user_handle(&self) -> Option<&[u8]>;
fn username(&self) -> Option<&str>;
fn user_display_name(&self) -> Option<&str>;
fn counter(&self) -> Option<u32>;
fn set_counter(&mut self, counter: u32);
fn extensions(&self) -> Cow<'_, CredentialExtensions>;
}
pub(crate) trait AsCredentialDescriptor: PasskeyAccessor {
fn as_credential_descriptor(
&self,
transports: Option<Vec<AuthenticatorTransport>>,
) -> PublicKeyCredentialDescriptor;
}
impl<P> AsCredentialDescriptor for P
where
P: PasskeyAccessor,
{
fn as_credential_descriptor(
&self,
transports: Option<Vec<AuthenticatorTransport>>,
) -> PublicKeyCredentialDescriptor {
PublicKeyCredentialDescriptor {
ty: PublicKeyCredentialType::PublicKey,
id: self.credential_id().into(),
transports,
}
}
}
impl PasskeyAccessor for passkey_types::Passkey {
fn key(&self) -> Cow<'_, CoseKey> {
Cow::Borrowed(&self.key)
}
fn credential_id(&self) -> &[u8] {
&self.credential_id
}
fn rp_id(&self) -> &str {
&self.rp_id
}
fn user_handle(&self) -> Option<&[u8]> {
self.user_handle.as_ref().map(|b| b.deref().deref())
}
fn username(&self) -> Option<&str> {
self.username.as_deref()
}
fn user_display_name(&self) -> Option<&str> {
self.user_display_name.as_deref()
}
fn counter(&self) -> Option<u32> {
self.counter
}
fn set_counter(&mut self, counter: u32) {
self.counter = Some(counter);
}
fn extensions(&self) -> Cow<'_, CredentialExtensions> {
Cow::Borrowed(&self.extensions)
}
}