diff --git a/vdr/src/contracts/did/did_ethr_registry.rs b/vdr/src/contracts/did/did_ethr_registry.rs index cdec330d..170b03d7 100644 --- a/vdr/src/contracts/did/did_ethr_registry.rs +++ b/vdr/src/contracts/did/did_ethr_registry.rs @@ -641,12 +641,12 @@ pub mod test { contracts::{ did::types::{ did::DID, - did_doc::test::{SERVICE_ENDPOINT, SERVICE_TYPE}, + did_doc::test::SERVICE_ENDPOINT, did_doc_attribute::{ PublicKeyAttribute, PublicKeyPurpose, PublicKeyType, ServiceAttribute, }, }, - ServiceEndpoint, + ServiceEndpoint, ServiceType, }, }; @@ -656,7 +656,7 @@ pub mod test { pub fn service() -> DidDocAttribute { DidDocAttribute::Service(ServiceAttribute { - type_: SERVICE_TYPE.to_string(), + type_: ServiceType::LinkedDomains, service_endpoint: ServiceEndpoint::String(SERVICE_ENDPOINT.to_string()), }) } @@ -826,13 +826,13 @@ pub mod test { data: vec![ 122, 212, 176, 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 226, 219, 108, 141, 198, 198, 129, 187, 93, 106, 209, 33, 161, 7, 243, 0, 233, 178, 181, 100, - 105, 100, 47, 115, 118, 99, 47, 83, 101, 114, 118, 105, 99, 101, 0, 0, 0, 0, 0, + 105, 100, 47, 115, 118, 99, 47, 76, 105, 110, 107, 101, 100, 68, 111, 109, 97, + 105, 110, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 232, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 18, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, - 46, 99, 111, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 18, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, + 112, 108, 101, 46, 99, 111, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], signature: None, hash: None, @@ -896,12 +896,12 @@ pub mod test { data: vec![ 0, 192, 35, 218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 226, 219, 108, 141, 198, 198, 129, 187, 93, 106, 209, 33, 161, 7, 243, 0, 233, 178, 181, 100, 105, - 100, 47, 115, 118, 99, 47, 83, 101, 114, 118, 105, 99, 101, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 104, 116, - 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, 109, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 100, 47, 115, 118, 99, 47, 76, 105, 110, 107, 101, 100, 68, 111, 109, 97, 105, + 110, 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, + 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, 109, 112, 108, 101, 46, 99, 111, + 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ], signature: None, hash: None, diff --git a/vdr/src/contracts/did/types/did_doc.rs b/vdr/src/contracts/did/types/did_doc.rs index cd02d825..abbbcd48 100644 --- a/vdr/src/contracts/did/types/did_doc.rs +++ b/vdr/src/contracts/did/types/did_doc.rs @@ -308,7 +308,7 @@ impl VerificationMethodOrReference { pub struct Service { pub id: String, #[serde(rename = "type")] - pub type_: String, //TODO Convert into enum + pub type_: ServiceType, pub service_endpoint: ServiceEndpoint, } @@ -321,13 +321,54 @@ impl Service { ))); } - if self.type_.is_empty() { - return Err(VdrError::InvalidDidDocument( - "Service type is not provided".to_string(), - )); + Ok(()) + } +} + +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[serde(untagged)] +pub enum ServiceType { + LinkedDomains, + DIDCommMessaging, + CredentialRegistry, + OID4VCI, + OID4VP, +} + +impl ToString for ServiceType { + fn to_string(&self) -> String { + match self { + ServiceType::LinkedDomains => "LinkedDomains".to_string(), + ServiceType::DIDCommMessaging => "DIDCommMessaging".to_string(), + ServiceType::CredentialRegistry => "CredentialRegistry".to_string(), + ServiceType::OID4VCI => "OID4VCI".to_string(), + ServiceType::OID4VP => "OID4VP".to_string(), } + } +} - Ok(()) +impl TryFrom<&str> for ServiceType { + type Error = VdrError; + + fn try_from(value: &str) -> Result { + match value { + "LinkedDomains" => Ok(ServiceType::LinkedDomains), + "DIDCommMessaging" => Ok(ServiceType::DIDCommMessaging), + "CredentialRegistry" => Ok(ServiceType::CredentialRegistry), + "OID4VCI" => Ok(ServiceType::OID4VCI), + "OID4VP" => Ok(ServiceType::OID4VP), + _type => Err({ + let vdr_error = + VdrError::CommonInvalidData(format!("Unexpected service type {}", _type)); + + warn!( + "Error: {} during converting ServiceType from String: {} ", + vdr_error, value + ); + + vdr_error + }), + } } } @@ -461,15 +502,14 @@ pub mod test { pub const TEST_ETHR_DID_WITHOUT_NETWORK: &str = "did:ethr:0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5"; pub const SERVICE_ENDPOINT: &str = "http://example.com"; - pub const SERVICE_TYPE: &str = "Service"; pub const MULTIBASE_KEY: &'static str = "zAKJP3f7BD6W4iWEQ9jwndVTCBq8ua2Utt8EEjJ6Vxsf"; pub const BASE58_KEY: &'static str = "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"; pub const KEY_1: &'static str = "KEY-1"; - pub fn _service(id: &str) -> Service { + pub fn service(id: &str) -> Service { Service { id: id.to_string(), - type_: SERVICE_TYPE.to_string(), + type_: ServiceType::LinkedDomains, service_endpoint: ServiceEndpoint::String(SERVICE_ENDPOINT.to_string()), } } @@ -489,14 +529,6 @@ pub mod test { } } - pub fn service(id: &str) -> Service { - Service { - id: id.to_string(), - type_: "LinkedDomains".to_string(), - service_endpoint: ServiceEndpoint::String("https://.example.com".to_string()), - } - } - pub fn verification_relationship(id: &str) -> VerificationMethodOrReference { VerificationMethodOrReference::String(id.to_string()) } @@ -679,23 +711,6 @@ pub mod test { assert_eq!(actual_error, expected_error); } - #[test] - fn empty_service_type() { - let mut did_document = did_doc("0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5"); - - let service_id = format!("{}#{}", TEST_INDYBESU_DID, "service"); - let mut service_with_empty_type = service(&service_id); - service_with_empty_type.type_ = "".to_string(); - did_document.service = vec![service_with_empty_type]; - - let expected_error = - VdrError::InvalidDidDocument("Service type is not provided".to_string()); - - let actual_error = did_document.validate().unwrap_err(); - - assert_eq!(actual_error, expected_error); - } - #[test] fn valid_did_document() { let mut did_document = did_doc("0xf0e2db6c8dc6c681bb5d6ad121a107f300e9b2b5"); diff --git a/vdr/src/contracts/did/types/did_doc_attribute.rs b/vdr/src/contracts/did/types/did_doc_attribute.rs index 5c28412c..c1470a3b 100644 --- a/vdr/src/contracts/did/types/did_doc_attribute.rs +++ b/vdr/src/contracts/did/types/did_doc_attribute.rs @@ -1,6 +1,9 @@ use crate::{ contracts::{ - did::types::did_events::{DidAttributeChanged, DidEvents}, + did::types::{ + did_doc::ServiceType, + did_events::{DidAttributeChanged, DidEvents}, + }, ServiceEndpoint, }, types::ContractParam, @@ -213,7 +216,7 @@ impl From for VerificationKeyType { #[serde(rename_all = "camelCase")] pub struct ServiceAttribute { #[serde(rename = "type")] - pub type_: String, + pub type_: ServiceType, pub service_endpoint: ServiceEndpoint, } @@ -237,9 +240,10 @@ impl DidDocAttribute { key_encoding ))) } - DidDocAttribute::Service(service) => { - Ok(DidDocAttributeName(format!("did/svc/{}", service.type_))) - } + DidDocAttribute::Service(service) => Ok(DidDocAttributeName(format!( + "did/svc/{}", + service.type_.to_string() + ))), } } @@ -350,7 +354,7 @@ impl TryFrom<&DidAttributeChanged> for DidDocAttribute { }; Ok(DidDocAttribute::Service(ServiceAttribute { - type_: type_.to_string(), + type_: ServiceType::try_from(*type_)?, service_endpoint, })) } diff --git a/vdr/src/contracts/did/types/did_doc_builder.rs b/vdr/src/contracts/did/types/did_doc_builder.rs index 16e30882..0498367d 100644 --- a/vdr/src/contracts/did/types/did_doc_builder.rs +++ b/vdr/src/contracts/did/types/did_doc_builder.rs @@ -5,7 +5,7 @@ use crate::{ contracts::{ did::{ types::did_doc::{ - Service, ServiceEndpoint, StringOrVector, VerificationMethod, + Service, ServiceEndpoint, ServiceType, StringOrVector, VerificationMethod, VerificationMethodOrReference, BASE_CONTEXT, }, KEYS_CONTEXT, SECPK_CONTEXT, @@ -287,7 +287,7 @@ impl DidDocumentBuilder { &mut self, key: &str, id: Option<&str>, - type_: &str, + type_: &ServiceType, endpoint: &ServiceEndpoint, ) { self.service_index += 1; @@ -296,7 +296,7 @@ impl DidDocumentBuilder { .unwrap_or_else(|| format!("{}#service-{}", self.id.as_ref(), self.service_index)); let service = Service { id, - type_: type_.to_string(), + type_: type_.clone(), service_endpoint: endpoint.clone(), }; self.service.push((key.to_string(), service)); @@ -396,11 +396,15 @@ impl DidDocumentBuilder { #[cfg(test)] pub mod test { use super::*; + use crate::{ client::client::test::TEST_ACCOUNT, - contracts::types::did_doc::test::{ - default_ethr_did_document, SERVICE_ENDPOINT, SERVICE_TYPE, TEST_ETHR_DID, - TEST_ETHR_DID_WITHOUT_NETWORK, + contracts::{ + types::did_doc::test::{ + default_ethr_did_document, SERVICE_ENDPOINT, TEST_ETHR_DID, + TEST_ETHR_DID_WITHOUT_NETWORK, + }, + ServiceType, }, }; @@ -461,7 +465,7 @@ pub mod test { builder.add_service( SERVICE_1_INDEX, None, - SERVICE_TYPE, + &ServiceType::LinkedDomains, &ServiceEndpoint::String(SERVICE_ENDPOINT.to_string()), ); let did_document = builder.build();