use serde::{Deserialize, Serialize};
use crate::server::domain::DomainScope;
pub const WEBVH_EXT_KEY: &str = "vnd.affinidi.webvh";
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct WebvhAclEntryExt {
#[serde(default, skip_serializing_if = "WebvhQuota::is_empty")]
pub quota: WebvhQuota,
pub domains: DomainScope,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct WebvhQuota {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_total_size: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max_did_count: Option<u64>,
}
impl WebvhQuota {
pub fn is_empty(&self) -> bool {
self.max_total_size.is_none() && self.max_did_count.is_none()
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn round_trips_full_shape() {
let ext = WebvhAclEntryExt {
quota: WebvhQuota {
max_total_size: Some(1_048_576),
max_did_count: Some(50),
},
domains: DomainScope::AllowedWithDefault {
domains: vec!["a.example".into()],
default: "a.example".into(),
},
};
let value = serde_json::to_value(&ext).unwrap();
assert_eq!(
value,
json!({
"quota": { "maxTotalSize": 1_048_576, "maxDidCount": 50 },
"domains": {
"kind": "allowed_with_default",
"domains": ["a.example"],
"default": "a.example"
}
})
);
let back: WebvhAclEntryExt = serde_json::from_value(value).unwrap();
assert_eq!(back, ext);
}
#[test]
fn empty_quota_is_omitted_on_serialise() {
let ext = WebvhAclEntryExt {
quota: WebvhQuota::default(),
domains: DomainScope::All,
};
let value = serde_json::to_value(&ext).unwrap();
assert!(value.get("quota").is_none());
assert_eq!(value["domains"]["kind"], "all");
}
#[test]
fn deserialise_rejects_unknown_member_at_top_level() {
let bad = json!({
"qouta": {},
"domains": { "kind": "all" }
});
assert!(serde_json::from_value::<WebvhAclEntryExt>(bad).is_err());
}
#[test]
fn deserialise_requires_domains() {
let bad = json!({ "quota": {} });
assert!(serde_json::from_value::<WebvhAclEntryExt>(bad).is_err());
}
#[test]
fn quota_round_trips_partial() {
let q = WebvhQuota {
max_total_size: Some(500_000),
max_did_count: None,
};
let value = serde_json::to_value(&q).unwrap();
assert_eq!(value, json!({ "maxTotalSize": 500_000 }));
let back: WebvhQuota = serde_json::from_value(value).unwrap();
assert_eq!(back, q);
}
}