use serde::{Deserialize, Serialize};
use crate::capability::{Capability, SignedCapability};
use crate::error::{AccessError, AccessResult};
use crate::identity::{Did, Identity};
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct CapabilityChain {
links: Vec<SignedCapability>,
}
impl CapabilityChain {
pub fn single(root: SignedCapability) -> Self {
Self { links: vec![root] }
}
pub fn links(&self) -> &[SignedCapability] {
&self.links
}
pub fn len(&self) -> usize {
self.links.len()
}
pub fn is_empty(&self) -> bool {
self.links.is_empty()
}
pub fn bearer(&self) -> Option<&Did> {
self.links.last().map(|l| &l.capability.bearer)
}
pub fn encode(&self) -> AccessResult<Vec<u8>> {
postcard::to_allocvec(self).map_err(|e| AccessError::Canonical(e.to_string()))
}
pub fn decode(bytes: &[u8]) -> AccessResult<Self> {
postcard::from_bytes(bytes).map_err(|e| AccessError::Canonical(e.to_string()))
}
}
impl From<SignedCapability> for CapabilityChain {
fn from(root: SignedCapability) -> Self {
Self::single(root)
}
}
pub fn delegate(
parent: &CapabilityChain,
sub: Capability,
delegator: &Identity,
) -> AccessResult<CapabilityChain> {
let signed = SignedCapability::sign(sub, delegator)?;
let mut links = parent.links.clone();
links.push(signed);
Ok(CapabilityChain { links })
}