tfa: entry access/iteration cleanup
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
d831846706
commit
f58e5132aa
@ -107,6 +107,31 @@ fn to_data(data: TfaUserData) -> Vec<TypedTfaInfo> {
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterate through tuples of `(type, index, id)`.
|
||||||
|
fn tfa_id_iter(data: &TfaUserData) -> impl Iterator<Item = (TfaType, usize, &str)> {
|
||||||
|
data.totp
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, entry)| (TfaType::Totp, i, entry.info.id.as_str()))
|
||||||
|
.chain(
|
||||||
|
data.webauthn
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, entry)| (TfaType::Webauthn, i, entry.info.id.as_str())),
|
||||||
|
)
|
||||||
|
.chain(
|
||||||
|
data.u2f
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, entry)| (TfaType::U2f, i, entry.info.id.as_str())),
|
||||||
|
)
|
||||||
|
.chain(
|
||||||
|
data.recovery
|
||||||
|
.iter()
|
||||||
|
.map(|_| (TfaType::Recovery, 0, "recovery")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[api(
|
#[api(
|
||||||
protected: true,
|
protected: true,
|
||||||
input: {
|
input: {
|
||||||
@ -149,40 +174,37 @@ pub fn get_tfa_entry(userid: Userid, id: String) -> Result<TypedTfaInfo, Error>
|
|||||||
let _lock = crate::config::tfa::read_lock()?;
|
let _lock = crate::config::tfa::read_lock()?;
|
||||||
|
|
||||||
if let Some(user_data) = crate::config::tfa::read()?.users.remove(&userid) {
|
if let Some(user_data) = crate::config::tfa::read()?.users.remove(&userid) {
|
||||||
if id == "recovery" {
|
match {
|
||||||
if user_data.has_recovery() {
|
// scope to prevent the temprary iter from borrowing across the whole match
|
||||||
|
let entry = tfa_id_iter(&user_data).find(|(_ty, _index, entry_id)| id == *entry_id);
|
||||||
|
entry.map(|(ty, index, _)| (ty, index))
|
||||||
|
} {
|
||||||
|
Some((TfaType::Recovery, _)) => {
|
||||||
return Ok(TypedTfaInfo {
|
return Ok(TypedTfaInfo {
|
||||||
ty: TfaType::Recovery,
|
ty: TfaType::Recovery,
|
||||||
info: TfaInfo::recovery(),
|
info: TfaInfo::recovery(),
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
} else {
|
Some((TfaType::Totp, index)) => {
|
||||||
for tfa in user_data.totp {
|
|
||||||
if tfa.info.id == id {
|
|
||||||
return Ok(TypedTfaInfo {
|
return Ok(TypedTfaInfo {
|
||||||
ty: TfaType::Totp,
|
ty: TfaType::Totp,
|
||||||
info: tfa.info,
|
// `into_iter().nth()` to *move* out of it
|
||||||
|
info: user_data.totp.into_iter().nth(index).unwrap().info,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
Some((TfaType::Webauthn, index)) => {
|
||||||
|
|
||||||
for tfa in user_data.webauthn {
|
|
||||||
if tfa.info.id == id {
|
|
||||||
return Ok(TypedTfaInfo {
|
return Ok(TypedTfaInfo {
|
||||||
ty: TfaType::Webauthn,
|
ty: TfaType::Webauthn,
|
||||||
info: tfa.info,
|
info: user_data.webauthn.into_iter().nth(index).unwrap().info,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
Some((TfaType::U2f, index)) => {
|
||||||
|
|
||||||
for tfa in user_data.u2f {
|
|
||||||
if tfa.info.id == id {
|
|
||||||
return Ok(TypedTfaInfo {
|
return Ok(TypedTfaInfo {
|
||||||
ty: TfaType::U2f,
|
ty: TfaType::U2f,
|
||||||
info: tfa.info,
|
info: user_data.u2f.into_iter().nth(index).unwrap().info,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
None => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,29 +250,16 @@ pub fn delete_tfa(
|
|||||||
.get_mut(&userid)
|
.get_mut(&userid)
|
||||||
.ok_or_else(|| http_err!(NOT_FOUND, "no such entry: {}/{}", userid, id))?;
|
.ok_or_else(|| http_err!(NOT_FOUND, "no such entry: {}/{}", userid, id))?;
|
||||||
|
|
||||||
let found = if id == "recovery" {
|
match {
|
||||||
let found = user_data.has_recovery();
|
// scope to prevent the temprary iter from borrowing across the whole match
|
||||||
user_data.recovery = None;
|
let entry = tfa_id_iter(&user_data).find(|(_, _, entry_id)| id == *entry_id);
|
||||||
found
|
entry.map(|(ty, index, _)| (ty, index))
|
||||||
} else if let Some(i) = user_data.totp.iter().position(|entry| entry.info.id == id) {
|
} {
|
||||||
user_data.totp.remove(i);
|
Some((TfaType::Recovery, _)) => user_data.recovery = None,
|
||||||
true
|
Some((TfaType::Totp, index)) => drop(user_data.totp.remove(index)),
|
||||||
} else if let Some(i) = user_data
|
Some((TfaType::Webauthn, index)) => drop(user_data.webauthn.remove(index)),
|
||||||
.webauthn
|
Some((TfaType::U2f, index)) => drop(user_data.u2f.remove(index)),
|
||||||
.iter()
|
None => http_bail!(NOT_FOUND, "no such tfa entry: {}/{}", userid, id),
|
||||||
.position(|entry| entry.info.id == id)
|
|
||||||
{
|
|
||||||
user_data.webauthn.remove(i);
|
|
||||||
true
|
|
||||||
} else if let Some(i) = user_data.u2f.iter().position(|entry| entry.info.id == id) {
|
|
||||||
user_data.u2f.remove(i);
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
http_bail!(NOT_FOUND, "no such tfa entry: {}/{}", userid, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if user_data.is_empty() {
|
if user_data.is_empty() {
|
||||||
|
Loading…
Reference in New Issue
Block a user