xdid_core/
document.rs

1use jose_jwk::Jwk;
2use serde::{Deserialize, Serialize};
3use serde_with::{serde_as, skip_serializing_none};
4
5use crate::{
6    did::Did,
7    did_url::{DidUrl, RelativeDidUrl},
8};
9
10#[derive(Serialize, Deserialize, Debug)]
11#[serde(rename_all = "camelCase")]
12#[serde_as]
13#[skip_serializing_none]
14pub struct Document {
15    pub id: Did,
16    pub also_known_as: Option<Vec<String>>,
17    #[serde_as(as = "Option<OneOrMany<_>>")]
18    pub controller: Option<Vec<Did>>,
19    pub verification_method: Option<Vec<VerificationMethodMap>>,
20    pub authentication: Option<Vec<VerificationMethod>>,
21    pub assertion_method: Option<Vec<VerificationMethod>>,
22    pub key_agreement: Option<Vec<VerificationMethod>>,
23    pub capability_invocation: Option<Vec<VerificationMethod>>,
24    pub capability_delegation: Option<Vec<VerificationMethod>>,
25    pub service: Option<Vec<ServiceEndpoint>>,
26}
27
28impl Document {
29    /// Returns the verification method that the provided [DidUrl] is
30    /// referencing, restricted to a given [VerificationRole].
31    pub fn resolve_verification_method(
32        &self,
33        url: &DidUrl,
34        role: VerificationRole,
35    ) -> Option<VerificationMethodMap> {
36        let methods = match role {
37            VerificationRole::Assertion => self.assertion_method.as_deref(),
38            VerificationRole::Authentication => self.authentication.as_deref(),
39            VerificationRole::CapabilityDelegation => self.capability_delegation.as_deref(),
40            VerificationRole::CapabilityInvocation => self.capability_invocation.as_deref(),
41            VerificationRole::KeyAgreement => self.key_agreement.as_deref(),
42        }
43        .unwrap_or_default();
44
45        for method in methods {
46            match method {
47                VerificationMethod::Map(map) => {
48                    if map.id == *url {
49                        return Some(*map.clone());
50                    }
51                }
52                VerificationMethod::RelativeUrl(relative_url) => {
53                    return self.resolve_relative_url(relative_url);
54                }
55                VerificationMethod::Url(method_url) => {
56                    if method_url.did == url.did {
57                        if let Some(relative_url) = method_url.to_relative() {
58                            return self.resolve_relative_url(&relative_url);
59                        }
60                    } else {
61                        // TODO: Support additional DID resolution?
62                    }
63                }
64            }
65        }
66
67        None
68    }
69
70    fn resolve_relative_url(&self, url: &RelativeDidUrl) -> Option<VerificationMethodMap> {
71        for method in self.verification_method.as_deref().unwrap_or_default() {
72            if method.id.to_relative().as_ref() == Some(url) {
73                return Some(method.clone());
74            }
75        }
76
77        None
78    }
79}
80
81#[derive(Debug, Copy, Clone, PartialEq, Eq)]
82pub enum VerificationRole {
83    Assertion,
84    Authentication,
85    CapabilityDelegation,
86    CapabilityInvocation,
87    KeyAgreement,
88}
89
90#[derive(Serialize, Deserialize, Debug, Clone)]
91pub enum VerificationMethod {
92    Map(Box<VerificationMethodMap>),
93    RelativeUrl(RelativeDidUrl),
94    Url(DidUrl),
95}
96
97#[derive(Serialize, Deserialize, Debug, Clone)]
98#[skip_serializing_none]
99pub struct VerificationMethodMap {
100    pub id: DidUrl,
101    pub controller: Did,
102    #[serde(rename = "type")]
103    pub typ: String,
104    pub public_key_jwk: Option<Jwk>,
105    /// Multibase encoded public key.
106    pub public_key_multibase: Option<String>,
107}
108
109#[derive(Serialize, Deserialize, Debug, Clone)]
110#[serde_as]
111pub struct ServiceEndpoint {
112    pub id: String,
113    #[serde(rename = "type")]
114    #[serde_as(as = "OneOrMany<_>")]
115    pub typ: Vec<String>,
116}