1use crate::{
2 did::DID,
3 document::{Document, VerificationMethod},
4 url::URL,
5};
6use anyhow::anyhow;
7use either::Either;
8use std::{
9 collections::BTreeMap,
10 ops::{Index, IndexMut},
11 path::PathBuf,
12};
13use url::Url;
14
15#[derive(Default)]
57pub struct Registry {
58 r: BTreeMap<DID, Document>,
59 remote_cache: bool,
60}
61
62impl<'a> Index<&'a DID> for Registry {
63 type Output = Document;
64
65 fn index(&self, index: &'a DID) -> &Self::Output {
66 self.r.index(index)
67 }
68}
69
70impl<'a> IndexMut<&'a DID> for Registry {
71 fn index_mut(&mut self, index: &'a DID) -> &mut Document {
72 self.r.get_mut(index).unwrap()
73 }
74}
75
76impl Index<usize> for Registry {
77 type Output = Document;
78
79 fn index(&self, index: usize) -> &Self::Output {
80 self.r
81 .iter()
82 .nth(index)
83 .expect("invalid index dereferencing document in registry")
84 .1
85 }
86}
87
88impl IndexMut<usize> for Registry {
89 fn index_mut(&mut self, index: usize) -> &mut Document {
90 self.r
91 .iter_mut()
92 .nth(index)
93 .expect("invalid index dereferencing document in registry")
94 .1
95 }
96}
97
98impl Registry {
99 pub fn new_with_remote_cache() -> Self {
102 Self {
103 r: BTreeMap::new(),
104 remote_cache: true,
105 }
106 }
107
108 pub fn load_document(&mut self, filename: PathBuf) -> Result<(), anyhow::Error> {
110 let mut file = std::fs::OpenOptions::new();
111 file.read(true);
112 let io = file.open(filename)?;
113 let doc: Document = serde_json::from_reader(io)?;
114 self.insert(doc)
115 }
116
117 pub fn load_document_cbor(&mut self, filename: PathBuf) -> Result<(), anyhow::Error> {
119 let mut file = std::fs::OpenOptions::new();
120 file.read(true);
121 let io = file.open(filename)?;
122 let doc: Document = ciborium::de::from_reader(io)?;
123 self.insert(doc)
124 }
125
126 pub fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a DID, &'a Document)> + 'a {
128 self.r.iter()
129 }
130
131 pub fn len(&self) -> usize {
133 self.r.len()
134 }
135
136 pub fn insert(&mut self, doc: Document) -> Result<(), anyhow::Error> {
139 if self.r.contains_key(&doc.id) {
140 return Err(anyhow!("DID {} already exists in registry", doc.id));
141 }
142
143 self.r.insert(doc.id.clone(), doc);
144 Ok(())
145 }
146
147 pub fn remove(&mut self, did: &DID) -> Option<Document> {
149 self.r.remove(did)
150 }
151
152 pub fn get(&self, did: &DID) -> Option<Document> {
154 self.r.get(did).cloned()
155 }
156
157 pub fn follow(&self, url: URL) -> Option<Document> {
159 self.get(&url.to_did())
160 }
161
162 pub fn verification_method_for_url(&self, did: &DID, url: URL) -> Option<VerificationMethod> {
165 if let Some(doc) = self.get(did) {
166 if let Some(vm) = doc.verification_method {
167 for method in vm {
168 if url == method.id {
169 return Some(method);
170 }
171 }
172 }
173 }
174
175 None
176 }
177
178 pub fn controls(&self, did: &DID, controller: &DID) -> Result<bool, anyhow::Error> {
182 if let Some(did_doc) = self.get(did) {
183 if did == controller {
184 return Ok(true);
185 }
186
187 if self.get(controller).is_some() {
188 if did_doc.controller.is_some() {
189 match did_doc.controller.unwrap().0 {
190 Either::Left(did) => return Ok(&did == controller),
191 Either::Right(did_list) => {
192 for did in did_list {
193 if &did == controller {
194 return Ok(true);
195 }
196 }
197 }
198 }
199 } else {
200 return Ok(false);
201 }
202 } else {
203 return Err(anyhow!("DID {} did not exist in the registry", did));
204 }
205 } else {
206 return Err(anyhow!("DID {} did not exist in the registry", did));
207 }
208
209 Ok(false)
210 }
211
212 pub fn equivalent_to_did(&mut self, did: &DID, other: &DID) -> Result<bool, anyhow::Error> {
218 if let Some(doc) = self.get(did) {
221 if let Some(other_doc) = self.get(other) {
222 if let Some(this_aka) = doc.also_known_as {
223 for this_aka_each in this_aka.0 {
224 match this_aka_each.0 {
225 Either::Left(this_did) => {
226 if self.compare_aka(did, &this_did, &other_doc)? {
227 return Ok(true);
228 }
229 }
230 Either::Right(url) => {
231 let this_doc = self.cache_document(url)?;
232 if self.compare_aka(did, &this_doc.id, &other_doc)? {
233 return Ok(true);
234 }
235 }
236 }
237 }
238 } else {
239 return Ok(false);
240 }
241 } else {
242 return Err(anyhow!("DID {} did not exist in the registry", other));
243 }
244 } else {
245 return Err(anyhow!("DID {} did not exist in the registry", did));
246 }
247
248 Ok(false)
249 }
250
251 fn compare_aka(
252 &mut self,
253 did: &DID,
254 this_did: &DID,
255 other_doc: &Document,
256 ) -> Result<bool, anyhow::Error> {
257 if let Some(other_aka) = &other_doc.also_known_as {
258 for other_aka_each in &other_aka.0 {
259 let other_did = &match &other_aka_each.0 {
260 Either::Left(other_did) => other_did.clone(),
261 Either::Right(url) => self.cache_document(url.clone())?.id,
262 };
263
264 if other_did == did && this_did == &other_doc.id {
265 return Ok(true);
266 }
267 }
268 }
269
270 Ok(false)
271 }
272
273 fn cache_document(&mut self, url: Url) -> Result<Document, anyhow::Error> {
274 if self.remote_cache {
275 let doc = reqwest::blocking::get(url)?.json::<Document>()?;
276 self.insert(doc.clone())?;
277 Ok(doc)
278 } else {
279 Err(anyhow!("Remote caching of documents is disabled"))
280 }
281 }
282}
283
284mod tests {
285 #[test]
286 fn test_basic() {
287 use super::Registry;
288 use crate::{did::DID, document::Document};
289
290 let mut reg: Registry = Default::default();
291 let did = DID::parse("did:testing:u:alice").unwrap();
292 let doc = Document {
293 id: did.clone(),
294 ..Default::default()
295 };
296
297 let did2 = DID::parse("did:testing:u:bob").unwrap();
298 let doc2 = Document {
299 id: did2.clone(),
300 ..Default::default()
301 };
302
303 let did3 = DID::parse("did:testing:u:charlie").unwrap();
304
305 assert!(reg.insert(doc.clone()).is_ok());
306 assert!(reg.insert(doc.clone()).is_err());
307 assert_eq!(reg.get(&did), Some(doc));
308 assert!(reg.insert(doc2.clone()).is_ok());
309 assert_eq!(reg.get(&did2), Some(doc2));
310 assert!(reg.get(&did3).is_none());
311 assert!(reg.remove(&did).is_some());
312 assert!(reg.get(&did).is_none());
313 }
314
315 #[test]
316 fn test_follow() {
317 use super::Registry;
318 use crate::{did::DID, document::Document, url::URL};
319
320 let mut reg: Registry = Default::default();
321 let did = DID::parse("did:testing:u:alice").unwrap();
322 let doc = Document {
323 id: did.clone(),
324 ..Default::default()
325 };
326
327 let did2 = DID::parse("did:testing:u:bob").unwrap();
328 let doc2 = Document {
329 id: did2.clone(),
330 ..Default::default()
331 };
332
333 assert!(reg.insert(doc.clone()).is_ok());
334 assert!(reg.insert(doc2.clone()).is_ok());
335
336 let url = URL::parse("did:testing:u:alice/path#fragment").unwrap();
337 let url2 = URL::parse("did:testing:u:bob/path#fragment").unwrap();
338 let url3 = URL::parse("did:testing:u:charlie/path#fragment").unwrap();
339
340 assert_eq!(reg.follow(url).unwrap(), doc);
341 assert_eq!(reg.follow(url2).unwrap(), doc2);
342 assert!(reg.follow(url3).is_none());
343 }
344
345 #[test]
346 fn test_controls() {
347 use super::Registry;
348 use crate::{
349 did::DID,
350 document::{Controller, Document},
351 };
352 use either::Either;
353 use std::collections::BTreeSet;
354
355 let mut reg: Registry = Default::default();
356 let did = DID::parse("did:testing:u:alice").unwrap();
357 let did2 = DID::parse("did:testing:u:bob").unwrap();
358 let did3 = DID::parse("did:testing:u:charlie").unwrap();
359
360 let doc = Document {
361 id: did.clone(),
362 controller: Some(Controller(Either::Left(did2.clone()))),
363 ..Default::default()
364 };
365
366 let doc2 = Document {
367 id: did2.clone(),
368 ..Default::default()
369 };
370
371 assert!(reg.insert(doc.clone()).is_ok());
372 assert!(reg.insert(doc2.clone()).is_ok());
373 assert!(reg.controls(&did, &did2).is_ok());
374 assert!(reg.controls(&did2, &did3).is_err());
375 assert!(reg.controls(&did, &did2).unwrap());
376 assert!(!reg.controls(&did2, &did).unwrap());
377
378 assert!(reg.remove(&did).is_some());
379 assert!(reg.remove(&did2).is_some());
380
381 let mut set = BTreeSet::new();
382 set.insert(did2.clone());
383
384 let doc = Document {
385 id: did.clone(),
386 controller: Some(Controller(Either::Right(set))),
387 ..Default::default()
388 };
389
390 let doc2 = Document {
391 id: did2.clone(),
392 ..Default::default()
393 };
394
395 let doc3 = Document {
396 id: did3.clone(),
397 controller: Some(Controller(Either::Left(did2.clone()))),
398 ..Default::default()
399 };
400
401 assert!(reg.insert(doc.clone()).is_ok());
402 assert!(reg.insert(doc2.clone()).is_ok());
403 assert!(reg.insert(doc3.clone()).is_ok());
404 assert!(reg.controls(&did, &did2).is_ok());
405 assert!(reg.controls(&did, &did2).unwrap());
406 assert!(!reg.controls(&did2, &did).unwrap());
407 assert!(!reg.controls(&did, &did3).unwrap());
408 }
409
410 #[test]
411 fn test_equivalent_to_did() {
412 use super::Registry;
413 use crate::{
414 did::DID,
415 document::{AlsoKnownAs, AlsoKnownAsEither, Document},
416 };
417 use either::Either;
418 use std::collections::BTreeSet;
419
420 let mut reg: Registry = Default::default();
421 let did = DID::parse("did:testing:u:alice").unwrap();
422 let did2 = DID::parse("did:testing:u:bob").unwrap();
423 let did3 = DID::parse("did:testing:u:charlie").unwrap();
424
425 let mut set = BTreeSet::new();
426 set.insert(AlsoKnownAsEither(Either::Left(did2.clone())));
427
428 let mut set2 = BTreeSet::new();
429 set2.insert(AlsoKnownAsEither(Either::Left(did.clone())));
430
431 let doc = Document {
432 id: did.clone(),
433 also_known_as: Some(AlsoKnownAs(set.clone())),
434 ..Default::default()
435 };
436
437 let doc2 = Document {
438 id: did2.clone(),
439 also_known_as: Some(AlsoKnownAs(set2)),
440 ..Default::default()
441 };
442
443 assert!(reg.insert(doc.clone()).is_ok());
444 assert!(reg.insert(doc2.clone()).is_ok());
445 assert!(reg.equivalent_to_did(&did, &did3).is_err());
446 assert!(reg.equivalent_to_did(&did, &did2).unwrap());
447 assert!(reg.equivalent_to_did(&did2, &did).unwrap());
448
449 let doc3 = Document {
450 id: did3.clone(),
451 ..Default::default()
452 };
453
454 assert!(reg.insert(doc3.clone()).is_ok());
455 assert!(!reg.equivalent_to_did(&did2, &did3).unwrap());
456 assert!(!reg.equivalent_to_did(&did, &did3).unwrap());
457
458 assert!(reg.remove(&did).is_some());
459 assert!(reg.remove(&did2).is_some());
460
461 let doc = Document {
462 id: did.clone(),
463 also_known_as: Some(AlsoKnownAs(set)),
464 ..Default::default()
465 };
466
467 let doc2 = Document {
468 id: did2.clone(),
469 ..Default::default()
470 };
471
472 assert!(reg.insert(doc).is_ok());
473 assert!(reg.insert(doc2).is_ok());
474 assert!(!reg.equivalent_to_did(&did, &did2).unwrap());
475 }
476}