+ data.u2f.len()
+ data.webauthn.len()
+ data.yubico.len()
- + if data.recovery().is_some() { 1 } else { 0 },
+ + if data.recovery.is_some() { 1 } else { 0 },
);
- if let Some(recovery) = data.recovery() {
+ if let Some(recovery) = &data.recovery {
out.push(TypedTfaInfo {
ty: TfaType::Recovery,
info: TfaInfo::recovery(recovery.created),
let entry = tfa_id_iter(user_data).find(|(_ty, _index, entry_id)| id == *entry_id);
entry.map(|(ty, index, _)| (ty, index))
} {
- Some((TfaType::Recovery, _)) => match user_data.recovery() {
+ Some((TfaType::Recovery, _)) => match &user_data.recovery {
Some(recovery) => TypedTfaInfo {
ty: TfaType::Recovery,
info: TfaInfo::recovery(recovery.created),
pub webauthn: Vec<TfaEntry<WebauthnCredential>>,
/// Recovery keys. (Unordered OTP values).
- #[serde(skip_serializing_if = "Recovery::option_is_empty", default)]
+ #[serde(skip_serializing_if = "Option::is_none", default)]
pub recovery: Option<Recovery>,
/// Yubico keys for a user. NOTE: This is not directly supported currently, we just need this
}
impl TfaUserData {
- /// Shortcut to get the recovery entry only if it is not empty!
- pub fn recovery(&self) -> Option<&Recovery> {
- if Recovery::option_is_empty(&self.recovery) {
- None
- } else {
- self.recovery.as_ref()
- }
- }
-
/// `true` if no second factors exist
pub fn is_empty(&self) -> bool {
self.totp.is_empty()
&& self.u2f.is_empty()
&& self.webauthn.is_empty()
&& self.yubico.is_empty()
- && self.recovery().is_none()
+ && self.recovery.is_none()
}
/// Find an entry by id, except for the "recovery" entry which we're currently treating
Ok(Some(TfaChallenge {
totp: self.totp.iter().any(|e| e.info.enable),
- recovery: RecoveryState::from(&self.recovery),
+ recovery: self.recovery_state(),
webauthn: match webauthn {
Some(webauthn) => self.webauthn_challenge(access, userid, webauthn?)?,
None => None,
}
/// Get the recovery state.
- pub fn recovery_state(&self) -> RecoveryState {
- RecoveryState::from(&self.recovery)
+ pub fn recovery_state(&self) -> Option<RecoveryState> {
+ self.recovery.as_ref().map(RecoveryState::from)
}
/// Generate an optional webauthn challenge.
pub totp: bool,
/// Whether there are recovery keys available.
- #[serde(skip_serializing_if = "RecoveryState::is_unavailable", default)]
- pub recovery: RecoveryState,
+ #[serde(skip_serializing_if = "Option::is_none", default)]
+ pub recovery: Option<RecoveryState>,
/// If the user has any u2f tokens registered, this will contain the U2F challenge data.
#[serde(skip_serializing_if = "Option::is_none")]
self.available().count()
}
- /// Convenience serde method to check if either the option is `None` or the content `is_empty`.
- pub(super) fn option_is_empty(this: &Option<Self>) -> bool {
- this.as_ref()
- .map_or(true, |this| this.count_available() == 0)
- }
-
/// Verify a key and remove it. Returns whether the key was valid. Errors on openssl errors.
pub(super) fn verify(&mut self, key: &str) -> Result<bool, Error> {
let hash = self.hash(key.as_bytes())?;
}
}
-impl From<&Option<Recovery>> for RecoveryState {
- fn from(r: &Option<Recovery>) -> Self {
- match r {
- Some(r) => Self::from(r),
- None => Self::default(),
- }
- }
-}
-
impl From<&Recovery> for RecoveryState {
fn from(r: &Recovery) -> Self {
Self(