people: a missing person is 200 + null in Kanidm 1.11, not 404

The existence check went by status alone, so every invitee looked like
an existing account: creation was skipped and the group step failed.
Read the body; `null` means nobody there.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Bendik Aagaard Lynghaug
2026-09-23 14:33:25 +02:00
co-authored by Claude Fable 5.1
parent ef46b463e4
commit f36d88a69c
+24 -6
View File
@@ -31,6 +31,19 @@ pub struct Invited {
pub created: bool,
}
/// Whether a `GET /v1/person/<name>` answer means the person exists.
/// Kanidm 1.11 answers a missing person with 200 and the body `null`
/// rather than 404, so the status alone would report everyone as
/// existing and no account would ever get created. `None` for an
/// answer that is neither.
fn person_lookup_found(status: u16, body: &str) -> Option<bool> {
match status {
200 => Some(body.trim() != "null" && !body.trim().is_empty()),
404 => Some(false),
_ => None,
}
}
pub struct Kanidm {
base: String,
token: String,
@@ -60,12 +73,8 @@ impl Kanidm {
}
async fn person_exists(&self, username: &str) -> anyhow::Result<bool> {
let (status, _) = self.call(openidconnect::reqwest::Method::GET, &format!("/v1/person/{username}"), None).await?;
match status {
200 => Ok(true),
404 => Ok(false),
other => anyhow::bail!("kanidm: looking up {username}: http {other}"),
}
let (status, text) = self.call(openidconnect::reqwest::Method::GET, &format!("/v1/person/{username}"), None).await?;
person_lookup_found(status, &text).ok_or_else(|| anyhow::anyhow!("kanidm: looking up {username}: http {status}"))
}
/// The whole onboarding, in the order that leaves the least behind
@@ -161,4 +170,13 @@ mod tests {
assert_eq!(username_for("42@x.no"), "person");
assert_eq!(username_for("Ærlig@x.no"), "rlig");
}
#[test]
fn a_null_person_answer_means_nobody_there() {
assert_eq!(person_lookup_found(200, "null"), Some(false));
assert_eq!(person_lookup_found(200, "null\n"), Some(false));
assert_eq!(person_lookup_found(200, r#"{"attrs":{"name":["bl"]}}"#), Some(true));
assert_eq!(person_lookup_found(404, ""), Some(false));
assert_eq!(person_lookup_found(401, "unauthorized"), None);
}
}