affinidi_did_common/
lib.rs1use std::collections::HashMap;
6
7use affinidi_encoding::EncodingError;
8use serde::{Deserialize, Serialize};
9use serde_json::Value;
10use thiserror::Error;
11use url::Url;
12
13use crate::{
14 service::Service,
15 verification_method::{VerificationMethod, VerificationRelationship},
16};
17
18pub mod builder;
19pub mod did;
20pub mod did_method;
21pub mod document;
22pub mod one_or_many;
23pub mod service;
24pub mod verification_method;
25
26pub use builder::{DocumentBuilder, ServiceBuilder, VerificationMethodBuilder};
27pub use did::{DID, DIDError};
28pub use did_method::DIDMethod;
29pub use did_method::key::{KeyError, KeyMaterial, KeyMaterialFormat, KeyMaterialType};
30pub use did_method::peer::{
31 PeerCreateKey, PeerCreatedKey, PeerError, PeerKeyPurpose, PeerKeyType, PeerNumAlgo,
32 PeerPurpose, PeerService, PeerServiceEndpoint, PeerServiceEndpointLong,
33 PeerServiceEndpointShort,
34};
35pub use document::DocumentExt;
36
37#[derive(Error, Debug)]
38pub enum DocumentError {
39 #[error("URL Error")]
40 URL(#[from] url::ParseError),
41
42 #[error("VerificationMethod Error: {0}")]
43 VM(String),
44
45 #[error("Encoding Error: {0}")]
46 Encoding(#[from] EncodingError),
47
48 #[error("Key expansion error: {0}")]
49 KeyExpansionError(String),
50}
51
52#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
56#[serde(rename_all = "camelCase")]
57pub struct Document {
58 pub id: Url,
61
62 #[serde(skip_serializing_if = "Vec::is_empty", default)]
64 pub verification_method: Vec<VerificationMethod>,
65
66 #[serde(skip_serializing_if = "Vec::is_empty", default)]
68 pub authentication: Vec<VerificationRelationship>,
69
70 #[serde(skip_serializing_if = "Vec::is_empty", default)]
72 pub assertion_method: Vec<VerificationRelationship>,
73
74 #[serde(skip_serializing_if = "Vec::is_empty", default)]
76 pub key_agreement: Vec<VerificationRelationship>,
77
78 #[serde(skip_serializing_if = "Vec::is_empty", default)]
80 pub capability_invocation: Vec<VerificationRelationship>,
81
82 #[serde(skip_serializing_if = "Vec::is_empty", default)]
84 pub capability_delegation: Vec<VerificationRelationship>,
85
86 #[serde(skip_serializing_if = "Vec::is_empty", default)]
88 pub service: Vec<Service>,
89
90 #[serde(flatten)]
92 pub parameters_set: HashMap<String, Value>,
93}
94
95impl Default for Document {
96 fn default() -> Self {
98 Self {
99 id: Url::parse("did:example:123456789abcdefghi").unwrap(),
100 verification_method: Vec::new(),
101 authentication: Vec::new(),
102 assertion_method: Vec::new(),
103 key_agreement: Vec::new(),
104 capability_invocation: Vec::new(),
105 capability_delegation: Vec::new(),
106 service: Vec::new(),
107 parameters_set: HashMap::new(),
108 }
109 }
110}
111
112impl Document {
113 pub fn new(id: &str) -> Result<Self, DocumentError> {
116 Ok(Document {
117 id: Url::parse(id)?,
118 ..Default::default()
119 })
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126 use url::Url;
127
128 #[test]
129 fn valid_id() {
130 assert!(Url::parse("did:example:123456789abcdefghi").is_ok());
131 assert!(Url::parse("did:webvh:Qmd1FCL9Vj2vJ433UDfC9MBstK6W6QWSQvYyeNn8va2fai:identity.foundation:didwebvh-implementations:implementations:affinidi-didwebvh-rs").is_ok());
132 }
133
134 #[test]
135 fn document_new_valid() {
136 let doc = Document::new("did:example:123").unwrap();
137 assert_eq!(doc.id.as_str(), "did:example:123");
138 assert!(doc.verification_method.is_empty());
139 assert!(doc.service.is_empty());
140 }
141
142 #[test]
143 fn document_new_invalid() {
144 assert!(Document::new("not a url").is_err());
145 }
146
147 #[test]
148 fn document_default_has_example_id() {
149 let doc = Document::default();
150 assert_eq!(doc.id.as_str(), "did:example:123456789abcdefghi");
151 }
152
153 #[test]
154 fn document_serde_roundtrip_minimal() {
155 let doc = Document::new("did:example:456").unwrap();
156 let json = serde_json::to_string(&doc).unwrap();
157 let back: Document = serde_json::from_str(&json).unwrap();
158 assert_eq!(doc, back);
159 }
160}