indy_data_types/identifiers/
rev_reg.rs

1use once_cell::sync::Lazy;
2
3use regex::Regex;
4
5use super::cred_def::CredentialDefinitionId;
6use super::DELIMITER;
7use crate::did::DidValue;
8use crate::qualifiable::{self, qualifiable_type, Qualifiable};
9use crate::{Validatable, ValidationError};
10
11static QUALIFIED_REV_REG_ID: Lazy<Regex> = Lazy::new(|| {
12    Regex::new("(^revreg:(?P<method>[a-z0-9]+):)?(?P<did>.+):4:(?P<cred_def_id>.+):(?P<rev_reg_type>.+):(?P<tag>.+)$").unwrap()
13});
14
15qualifiable_type!(RevocationRegistryId, "A revocation registry identifier");
16
17impl RevocationRegistryId {
18    pub const PREFIX: &'static str = "revreg";
19    pub const MARKER: &'static str = "4";
20
21    pub fn new(
22        did: &DidValue,
23        cred_def_id: &CredentialDefinitionId,
24        rev_reg_type: &str,
25        tag: &str,
26    ) -> RevocationRegistryId {
27        let id = format!(
28            "{}{}{}{}{}{}{}{}{}",
29            did.0,
30            DELIMITER,
31            Self::MARKER,
32            DELIMITER,
33            cred_def_id.0,
34            DELIMITER,
35            rev_reg_type,
36            DELIMITER,
37            tag
38        );
39        Self::from(qualifiable::combine(
40            Self::PREFIX,
41            did.get_method(),
42            id.as_str(),
43        ))
44    }
45
46    pub fn parts(&self) -> Option<(DidValue, CredentialDefinitionId, String, String)> {
47        QUALIFIED_REV_REG_ID.captures(&self.0).map(|caps| {
48            (
49                DidValue(caps["did"].to_string()),
50                CredentialDefinitionId(caps["cred_def_id"].to_string()),
51                caps["rev_reg_type"].to_string(),
52                caps["tag"].to_string(),
53            )
54        })
55    }
56}
57
58impl Qualifiable for RevocationRegistryId {
59    fn prefix() -> &'static str {
60        Self::PREFIX
61    }
62
63    fn combine(method: Option<&str>, entity: &str) -> Self {
64        let sid = Self(entity.to_owned());
65        match sid.parts() {
66            Some((did, cred_def_id, rev_reg_type, tag)) => Self::new(
67                &did.default_method(method),
68                &cred_def_id.default_method(method),
69                &rev_reg_type,
70                &tag,
71            ),
72            None => sid,
73        }
74    }
75
76    fn to_unqualified(&self) -> Self {
77        match self.parts() {
78            Some((did, cred_def_id, rev_reg_type, tag)) => Self::new(
79                &did.to_unqualified(),
80                &cred_def_id.to_unqualified(),
81                &rev_reg_type,
82                &tag,
83            ),
84            None => self.clone(),
85        }
86    }
87}
88
89impl Validatable for RevocationRegistryId {
90    fn validate(&self) -> Result<(), ValidationError> {
91        self.parts().ok_or(format!(
92            "Revocation Registry Id validation failed: {:?}, doesn't match pattern",
93            self.0
94        ))?;
95        Ok(())
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    fn _did() -> DidValue {
104        DidValue("NcYxiDXkpYi6ov5FcYDi1e".to_string())
105    }
106
107    fn _rev_reg_type() -> String {
108        "CL_ACCUM".to_string()
109    }
110
111    fn _tag() -> String {
112        "TAG_1".to_string()
113    }
114
115    fn _did_qualified() -> DidValue {
116        DidValue("did:sov:NcYxiDXkpYi6ov5FcYDi1e".to_string())
117    }
118
119    fn _cred_def_id_unqualified() -> CredentialDefinitionId {
120        CredentialDefinitionId(
121            "NcYxiDXkpYi6ov5FcYDi1e:3:CL:NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0:tag".to_string(),
122        )
123    }
124
125    fn _cred_def_id_qualified() -> CredentialDefinitionId {
126        CredentialDefinitionId("creddef:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:3:CL:schema:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0:tag".to_string())
127    }
128
129    fn _rev_reg_id_unqualified() -> RevocationRegistryId {
130        RevocationRegistryId("NcYxiDXkpYi6ov5FcYDi1e:4:NcYxiDXkpYi6ov5FcYDi1e:3:CL:NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0:tag:CL_ACCUM:TAG_1".to_string())
131    }
132
133    fn _rev_reg_id_qualified() -> RevocationRegistryId {
134        RevocationRegistryId("revreg:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:4:creddef:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:3:CL:schema:sov:did:sov:NcYxiDXkpYi6ov5FcYDi1e:2:gvt:1.0:tag:CL_ACCUM:TAG_1".to_string())
135    }
136
137    mod to_unqualified {
138        use super::*;
139
140        #[test]
141        fn test_rev_reg_id_parts_for_id_as_unqualified() {
142            assert_eq!(
143                _rev_reg_id_unqualified(),
144                _rev_reg_id_unqualified().to_unqualified()
145            );
146        }
147
148        #[test]
149        fn test_rev_reg_id_parts_for_id_as_qualified() {
150            assert_eq!(
151                _rev_reg_id_unqualified(),
152                _rev_reg_id_qualified().to_unqualified()
153            );
154        }
155    }
156
157    mod parts {
158        use super::*;
159
160        #[test]
161        fn test_rev_reg_id_parts_for_id_as_unqualified() {
162            let (did, cred_def_id, rev_reg_type, tag) = _rev_reg_id_unqualified().parts().unwrap();
163            assert_eq!(_did(), did);
164            assert_eq!(_cred_def_id_unqualified(), cred_def_id);
165            assert_eq!(_rev_reg_type(), rev_reg_type);
166            assert_eq!(_tag(), tag);
167        }
168
169        #[test]
170        fn test_rev_reg_id_parts_for_id_as_qualified() {
171            let (did, cred_def_id, rev_reg_type, tag) = _rev_reg_id_qualified().parts().unwrap();
172            assert_eq!(_did_qualified(), did);
173            assert_eq!(_cred_def_id_qualified(), cred_def_id);
174            assert_eq!(_rev_reg_type(), rev_reg_type);
175            assert_eq!(_tag(), tag);
176        }
177    }
178
179    mod validate {
180        use super::*;
181
182        #[test]
183        fn test_validate_rev_reg_id_as_unqualified() {
184            _rev_reg_id_unqualified().validate().unwrap();
185        }
186
187        #[test]
188        fn test_validate_rev_reg_id_as_fully_qualified() {
189            _rev_reg_id_qualified().validate().unwrap();
190        }
191    }
192
193    mod to_qualified {
194        use super::*;
195
196        #[test]
197        fn test_red_def_to_qualified() {
198            assert_eq!(
199                _rev_reg_id_unqualified().to_qualified("sov").unwrap(),
200                _rev_reg_id_qualified()
201            )
202        }
203    }
204}