use trust_tasks_rs::validate::ValidatedPayload;
use crate::{HolderKey, VtcClient, VtcError};
pub use trust_tasks_rs::specs::vtc::members::{
admit::v0_1 as admit, make_membership::v0_1 as make_membership,
};
pub mod task {
use trust_tasks_rs::Payload;
pub const ADMIT: &str = <super::admit::Payload as Payload>::TYPE_URI;
pub const MAKE_MEMBERSHIP: &str = <super::make_membership::Payload as Payload>::TYPE_URI;
}
#[derive(Debug, Clone, Default)]
pub struct AdmitRequest {
pub subject: String,
pub role: String,
pub label: Option<String>,
pub reason: Option<String>,
}
impl VtcClient {
pub async fn members_admit(
&self,
req: &AdmitRequest,
key: &HolderKey,
) -> Result<admit::Response, VtcError> {
let mut body = serde_json::json!({ "subject": req.subject, "role": req.role });
if let Some(label) = &req.label {
body["label"] = serde_json::json!(label);
}
if let Some(reason) = &req.reason {
body["reason"] = serde_json::json!(reason);
}
let payload = checked::<admit::Payload>(body)?;
self.acl_task(task::ADMIT, payload, key, admit::ERROR_CODES)
.await
}
pub async fn members_make_membership(
&self,
subject: &str,
reason: Option<&str>,
key: &HolderKey,
) -> Result<make_membership::Response, VtcError> {
let mut body = serde_json::json!({ "subject": subject });
if let Some(reason) = reason {
body["reason"] = serde_json::json!(reason);
}
let payload = checked::<make_membership::Payload>(body)?;
self.acl_task(
task::MAKE_MEMBERSHIP,
payload,
key,
make_membership::ERROR_CODES,
)
.await
}
}
fn checked<P: ValidatedPayload>(payload: serde_json::Value) -> Result<serde_json::Value, VtcError> {
P::validate_value(&payload).map_err(|e| VtcError::InvalidPayload(e.to_string()))?;
Ok(payload)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn an_admission_out_of_schema_is_refused_before_sending() {
let ok = serde_json::json!({ "subject": "did:key:z6Mk", "role": "member" });
assert!(checked::<admit::Payload>(ok).is_ok());
for bad in [
serde_json::json!({ "subject": "not-a-did", "role": "member" }),
serde_json::json!({ "subject": "did:key:z6Mk", "role": "r".repeat(129) }),
serde_json::json!({ "subject": "did:key:z6Mk", "role": "member", "label": " " }),
] {
assert!(checked::<admit::Payload>(bad.clone()).is_err(), "{bad}");
}
assert!(
checked::<make_membership::Payload>(serde_json::json!({ "subject": "x" })).is_err()
);
}
}