use std::collections::BTreeMap;
use crate::value::Value;
use super::{CoolAuthIdentity, CoolContext, PrincipalContext};
#[derive(Debug, Clone, PartialEq)]
pub struct SystemContext {
inner: CoolContext,
}
impl SystemContext {
pub fn for_service(service: impl Into<String>) -> Self {
let service = service.into();
let mut fields = BTreeMap::new();
fields.insert("service".to_owned(), Value::String(service.clone()));
fields.insert("id".to_owned(), Value::String(format!("system:{service}")));
Self {
inner: CoolContext {
auth: Some(CoolAuthIdentity {
fields: fields.clone(),
}),
principal: Some(PrincipalContext::from_claims(fields)),
extensions: BTreeMap::new(),
system: true,
},
}
}
pub fn context(&self) -> &CoolContext {
&self.inner
}
pub fn into_context(self) -> CoolContext {
self.inner
}
}
impl AsRef<CoolContext> for SystemContext {
fn as_ref(&self) -> &CoolContext {
&self.inner
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn system_context_is_system_and_authenticated() {
let ctx = SystemContext::for_service("ledger-worker");
assert!(ctx.context().is_system());
assert!(ctx.context().is_authenticated());
assert_eq!(
ctx.context().auth_field("service"),
Some(&Value::String("ledger-worker".to_owned()))
);
}
#[test]
fn request_derived_contexts_are_never_system() {
assert!(!CoolContext::anonymous().is_system());
assert!(
!CoolContext::authenticated([(
"subjectId".to_owned(),
Value::String("u-1".to_owned())
)])
.is_system()
);
}
#[test]
fn system_flag_does_not_survive_serde_round_trip() {
let system = SystemContext::for_service("ledger-worker").into_context();
assert!(system.is_system());
let json = serde_json::to_string(&system).expect("context should serialize");
let encoded: serde_json::Value =
serde_json::from_str(&json).expect("context should serialize to an object");
assert!(
encoded
.as_object()
.expect("context serializes as an object")
.get("system")
.is_none(),
"system marker must not appear on the wire: {json}"
);
let decoded: CoolContext = serde_json::from_str(&json).expect("context should deserialize");
assert!(
!decoded.is_system(),
"a deserialized context must never be a system context"
);
}
#[test]
fn forged_system_field_in_payload_is_ignored() {
let decoded: CoolContext =
serde_json::from_str(r#"{"auth":null,"principal":null,"extensions":{},"system":true}"#)
.expect("unknown/skipped field should be ignored");
assert!(!decoded.is_system());
}
}