Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger-ui

src/first_import.rs

//! **The admin's first-import authorization** (lanes HOL-CDS, HOL-NCSC): holger's
//! `POST /-/bundle/first-import?vendor=&product=&sequence=`, as the Admin → Sync pane asks it.
//! A Holger with no anti-rollback floor refuses every bundle until an admin on the secure side
//! names the one that sets it (`holger-import-9`). The console builds the door's path and says
//! holger's answer; holger checks the admin, audits and keeps the grant (used once).

fn query_safe(v: &str) -> String {
    v.chars().map(|c| if c.is_ascii_alphanumeric() || matches!(c, '.' | '_' | '-') { c.to_string() } else { c.to_string().bytes().map(|b| format!("%{b:02X}")).collect() }).collect()
}

/// Pure: the door for `vendor`, `product` at `sequence` (as typed), or why the form is not
/// one yet. holger judges the rest (an admin, a floor that does not stand yet).
pub fn path(vendor: &str, product: &str, sequence: &str) -> Result<String, String> {
    let (v, p, s) = (vendor.trim(), product.trim(), sequence.trim());
    if v.is_empty() || p.is_empty() {
        return Err("name the bundle's vendor and product".to_string());
    }
    let n: u64 = s.parse().map_err(|_| format!("the sequence is a whole number, not {s:?}"))?;
    if n == 0 {
        return Err("the sequence starts at 1".to_string());
    }
    Ok(format!("/-/bundle/first-import?vendor={}&product={}&sequence={n}", query_safe(v), query_safe(p)))
}

/// Pure: what the page says once holger answered: `Ok` with holger's record of the grant, or
/// `Err` with holger's refusal verbatim and its status. The console adds no judgement.
pub fn granted(status: u16, body: &str) -> Result<String, String> {
    if status != 200 {
        let why = if body.trim().is_empty() { "holger gave no reason" } else { body.trim() };
        return Err(format!("holger refused the authorization ({status}): {why}"));
    }
    let v: serde_json::Value = serde_json::from_str(body).map_err(|e| format!("holger answered something unreadable: {e}"))?;
    Ok(format!(
        "{} {} sequence {} may set the floor once (authorized by {})",
        v["vendor"].as_str().unwrap_or("?"),
        v["product"].as_str().unwrap_or("?"),
        v["sequence"].as_u64().unwrap_or(0),
        v["by"].as_str().unwrap_or("?")
    ))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn the_form_names_holgers_door_or_says_what_is_missing() {
        assert_eq!(path(" online ", "pypi", "7").unwrap(), "/-/bundle/first-import?vendor=online&product=pypi&sequence=7");
        assert_eq!(path("a b", "p&q", "1").unwrap(), "/-/bundle/first-import?vendor=a%20b&product=p%26q&sequence=1");
        assert!(path("", "pypi", "1").unwrap_err().contains("vendor and product"));
        assert!(path("v", "p", "x").unwrap_err().contains("whole number"));
        assert!(path("v", "p", "0").unwrap_err().contains("starts at 1"));
    }

    #[test]
    fn holgers_answer_is_said_as_it_came() {
        let ok = granted(200, r#"{"vendor":"online","product":"pypi","sequence":7,"by":"anna","at":1}"#).unwrap();
        assert_eq!(ok, "online pypi sequence 7 may set the floor once (authorized by anna)");
        let refused = granted(403, "[holger-import-11] not an admin").unwrap_err();
        assert!(refused.contains("403") && refused.contains("[holger-import-11]"), "{refused}");
        assert!(granted(500, "").unwrap_err().contains("no reason"));
    }
}