wot_network/
edge.rs

1#[cfg(doc)]
2use crate::Network;
3use crate::{Binding, Certificate, Identity, Regex, TrustDepth};
4
5/// An edge in the WoT network (either a [Certification] or a [Delegation])
6#[derive(Debug, Clone, Eq, Hash, PartialEq)]
7pub enum Edge {
8    Certification(Certification),
9    Delegation(Delegation),
10}
11
12impl Edge {
13    pub fn issuer(&self) -> &Certificate {
14        match self {
15            Self::Certification(certification) => certification.issuer(),
16            Self::Delegation(delegation) => delegation.issuer(),
17        }
18    }
19
20    pub fn target(&self) -> &Certificate {
21        match self {
22            Self::Certification(certification) => certification.target_cert(),
23            Self::Delegation(delegation) => delegation.target(),
24        }
25    }
26
27    pub fn is_delegation(&self) -> bool {
28        matches!(self, Edge::Delegation(..))
29    }
30
31    pub fn trust_amount(&self) -> u8 {
32        match self {
33            Self::Certification(_) => 120,
34            Self::Delegation(delegation) => delegation.trust_amount,
35        }
36    }
37
38    pub fn trust_depth(&self) -> TrustDepth {
39        match self {
40            Self::Certification(_) => TrustDepth::None,
41            Self::Delegation(delegation) => delegation.trust_depth,
42        }
43    }
44}
45
46/// A type of [Edge] that represents a certification over a [`Binding`].
47///
48/// `Certification`s can only be created by using [`Network::add_binding`].
49///
50/// ```
51/// use wot_network::Network;
52///
53/// let mut network = Network::new();
54/// network.add_binding(
55///     "issuer_cert_id".into(),
56///     "target_cert_id".into(),
57///     "target@user_id.com".into(),
58///     120,
59/// );
60/// ```
61// TODO: There's currently no way to programatically create a Certification outside of add_binding.
62//       I assume there should be another way?
63#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
64#[derive(Debug, Clone, Eq, Hash, PartialEq)]
65pub struct Certification {
66    pub issuer: Certificate,
67    pub target: Binding, // FIXME: drop? - redundant with network hashmap key
68}
69
70impl Certification {
71    pub fn issuer(&self) -> &Certificate {
72        &self.issuer
73    }
74
75    pub fn target_cert(&self) -> &Certificate {
76        &self.target.cert
77    }
78    pub fn target_id(&self) -> &Identity {
79        &self.target.identity
80    }
81}
82
83/// A type of [Edge] that represents a delegation to a second certificate
84#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
85#[derive(Debug, Clone, Eq, Hash, PartialEq)]
86pub struct Delegation {
87    pub issuer: Certificate,
88    pub target: Certificate, // FIXME: drop? - redundant with network hashmap key
89    pub trust_amount: u8,
90    pub trust_depth: TrustDepth,
91    /// If any regex exists in a delegation, then at least one of the regexes must match the
92    /// target User ID for a delegation edge to be usable in a path.
93    pub regexes: Vec<Regex>,
94}
95
96impl Delegation {
97    pub fn new(
98        issuer: Certificate,
99        target: Certificate,
100        trust_amount: u8,
101        trust_depth: TrustDepth,
102        regexes: Vec<Regex>,
103    ) -> Self {
104        Delegation {
105            issuer,
106            target,
107            trust_amount,
108            trust_depth,
109            regexes,
110        }
111    }
112
113    pub fn issuer(&self) -> &Certificate {
114        &self.issuer
115    }
116
117    pub fn target(&self) -> &Certificate {
118        &self.target
119    }
120
121    pub fn trust_amount(&self) -> u8 {
122        self.trust_amount
123    }
124
125    pub fn trust_depth(&self) -> TrustDepth {
126        self.trust_depth
127    }
128
129    fn regexes(&self) -> &[Regex] {
130        &self.regexes
131    }
132
133    pub fn regex_match(&self, target_user_id: &Identity) -> bool {
134        if self.regexes().is_empty() {
135            return true;
136        }
137
138        self.regexes()
139            .iter()
140            .any(|regex| regex.matches(target_user_id))
141    }
142}