use super::Did;
use crate::{DidResult, Service, VerificationMethod};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DidDocument {
#[serde(rename = "@context")]
pub context: Vec<String>,
pub id: Did,
#[serde(skip_serializing_if = "Option::is_none")]
pub also_known_as: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub controller: Option<DidController>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub verification_method: Vec<VerificationMethod>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub authentication: Vec<VerificationRelationship>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub assertion_method: Vec<VerificationRelationship>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub key_agreement: Vec<VerificationRelationship>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub capability_invocation: Vec<VerificationRelationship>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub capability_delegation: Vec<VerificationRelationship>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub service: Vec<Service>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum DidController {
Single(Did),
Multiple(Vec<Did>),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum VerificationRelationship {
Reference(String),
Embedded(VerificationMethod),
}
impl DidDocument {
pub fn new(id: Did) -> Self {
Self {
context: vec![
"https://www.w3.org/ns/did/v1".to_string(),
"https://w3id.org/security/suites/ed25519-2020/v1".to_string(),
],
id,
also_known_as: None,
controller: None,
verification_method: Vec::new(),
authentication: Vec::new(),
assertion_method: Vec::new(),
key_agreement: Vec::new(),
capability_invocation: Vec::new(),
capability_delegation: Vec::new(),
service: Vec::new(),
}
}
pub fn from_key_ed25519(public_key: &[u8]) -> DidResult<Self> {
let did = Did::new_key_ed25519(public_key)?;
let key_id = did.key_id("key-1");
let verification_method = VerificationMethod::ed25519(&key_id, did.as_str(), public_key);
let mut doc = Self::new(did);
doc.verification_method.push(verification_method);
doc.authentication
.push(VerificationRelationship::Reference(key_id.clone()));
doc.assertion_method
.push(VerificationRelationship::Reference(key_id.clone()));
doc.capability_invocation
.push(VerificationRelationship::Reference(key_id.clone()));
doc.capability_delegation
.push(VerificationRelationship::Reference(key_id));
Ok(doc)
}
pub fn get_verification_method(&self, id: &str) -> Option<&VerificationMethod> {
self.verification_method.iter().find(|vm| vm.id == id)
}
pub fn get_assertion_method(&self) -> Option<&VerificationMethod> {
for rel in &self.assertion_method {
match rel {
VerificationRelationship::Reference(ref_id) => {
if let Some(vm) = self.get_verification_method(ref_id) {
return Some(vm);
}
}
VerificationRelationship::Embedded(vm) => {
return Some(vm);
}
}
}
None
}
pub fn get_authentication_method(&self) -> Option<&VerificationMethod> {
for rel in &self.authentication {
match rel {
VerificationRelationship::Reference(ref_id) => {
if let Some(vm) = self.get_verification_method(ref_id) {
return Some(vm);
}
}
VerificationRelationship::Embedded(vm) => {
return Some(vm);
}
}
}
None
}
pub fn add_service(&mut self, id: &str, service_type: &str, endpoint: &str) {
self.service.push(Service {
id: id.to_string(),
service_type: service_type.to_string(),
service_endpoint: endpoint.to_string(),
});
}
pub fn to_json(&self) -> DidResult<String> {
serde_json::to_string_pretty(self)
.map_err(|e| crate::DidError::SerializationError(e.to_string()))
}
pub fn from_json(json: &str) -> DidResult<Self> {
serde_json::from_str(json).map_err(|e| crate::DidError::SerializationError(e.to_string()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_did_document_from_key() {
let public_key = [0u8; 32];
let doc = DidDocument::from_key_ed25519(&public_key).unwrap();
assert_eq!(doc.verification_method.len(), 1);
assert!(!doc.authentication.is_empty());
assert!(!doc.assertion_method.is_empty());
}
#[test]
fn test_did_document_serialization() {
let public_key = [0u8; 32];
let doc = DidDocument::from_key_ed25519(&public_key).unwrap();
let json = doc.to_json().unwrap();
let parsed = DidDocument::from_json(&json).unwrap();
assert_eq!(doc.id, parsed.id);
assert_eq!(
doc.verification_method.len(),
parsed.verification_method.len()
);
}
#[test]
fn test_get_assertion_method() {
let public_key = [0u8; 32];
let doc = DidDocument::from_key_ed25519(&public_key).unwrap();
let am = doc.get_assertion_method();
assert!(am.is_some());
assert_eq!(am.unwrap().method_type, "Ed25519VerificationKey2020");
}
}