use crate::domain::error::DomainError;
const REFERENCE: &str = "reference";
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Namespaced<'a> {
Under(&'a str),
None,
}
pub fn namespace_of<'a>(
family: Option<&str>,
payload: Option<&'a serde_json::Value>,
) -> Result<Namespaced<'a>, DomainError> {
if family != Some(REFERENCE) {
return Ok(Namespaced::None);
}
let system = payload
.and_then(|p| p.pointer("/source/system"))
.and_then(serde_json::Value::as_str)
.map(str::trim)
.filter(|system| !system.is_empty());
match system {
Some(system) if system.chars().any(char::is_control) => Err(DomainError::invalid(
"`payload.source.system` cannot carry control characters: it is the namespace the \
write is authorized against, and it is written to the operator log",
)),
Some(system) => Ok(Namespaced::Under(system)),
None => Err(DomainError::invalid(
"a reference node must carry `payload.source.system`: it is the namespace the write \
is authorized against",
)),
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Claim {
Take,
Allowed,
Forbidden,
}
#[must_use]
pub fn decide(current_owner: Option<&str>, writer: &str) -> Claim {
match current_owner {
None => Claim::Take,
Some(owner) if owner == writer => Claim::Allowed,
Some(_) => Claim::Forbidden,
}
}
#[must_use]
pub fn is_canonical_principal(principal: &str) -> bool {
principal.trim() == principal && !principal.chars().any(char::is_control)
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn an_owned_node_has_no_namespace_to_authorize() {
let payload = json!({ "source": { "system": "github" } });
assert_eq!(
namespace_of(Some("owned"), Some(&payload)).expect("owned nodes are not namespaced"),
Namespaced::None,
"a `source` in an owned node's payload is a payload field, not a boundary"
);
}
#[test]
fn a_reference_node_writes_under_its_declared_system() {
let payload =
json!({ "source": { "system": "github", "kind": "commit", "native_id": "a1" } });
assert_eq!(
namespace_of(Some("reference"), Some(&payload)).expect("the system is there"),
Namespaced::Under("github")
);
}
#[test]
fn a_reference_node_without_a_system_is_malformed_rather_than_unowned() {
for payload in [
json!({}),
json!({ "source": {} }),
json!({ "source": { "system": " " } }),
] {
let error = namespace_of(Some("reference"), Some(&payload))
.expect_err("an unnamed namespace cannot be authorized");
assert!(error.to_string().contains("source.system"), "{error}");
}
assert!(namespace_of(Some("reference"), None).is_err());
}
#[test]
fn an_unclaimed_namespace_is_claimed_by_its_first_writer() {
assert_eq!(decide(None, "producer-a"), Claim::Take);
assert_eq!(decide(Some("producer-a"), "producer-a"), Claim::Allowed);
assert_eq!(decide(Some("producer-a"), "producer-b"), Claim::Forbidden);
}
#[test]
fn a_namespace_that_could_forge_a_log_line_is_malformed() {
for system in [
"github\nlevel=error msg=\"fake alert\"",
"github\rlevel=error",
"git\u{0}hub",
] {
let payload = json!({
"source": { "system": system, "kind": "commit", "native_id": "a1" }
});
assert!(
namespace_of(Some("reference"), Some(&payload)).is_err(),
"{system:?} must be refused rather than logged"
);
}
}
#[test]
fn a_padded_namespace_is_still_read_as_its_trimmed_self() {
let payload = json!({
"source": { "system": " github ", "kind": "commit", "native_id": "a1" }
});
assert_eq!(
namespace_of(Some("reference"), Some(&payload)).expect("padding is not a control char"),
Namespaced::Under("github")
);
}
#[test]
fn a_principal_no_writer_could_equal_is_not_canonical() {
for principal in [
"mirror-gear ",
" mirror-gear",
"mirror-gear\n",
"mirror\tgear",
"mirror-gear\u{0}",
] {
assert!(
!is_canonical_principal(principal),
"{principal:?} must not pass as a principal"
);
}
}
#[test]
fn the_shapes_a_security_context_produces_are_canonical() {
for principal in [
"mirror-gear",
"0191f0a4-1b2c-7def-8a90-0123456789ab",
"service:mirror-gear",
] {
assert!(
is_canonical_principal(principal),
"{principal:?} must pass as a principal"
);
}
}
}