Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor DDO service builder improvement #868

Merged
merged 2 commits into from
Jun 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions did_doc/src/schema/did_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,9 @@ mod tests {
let service_type = "test-service".to_string();
let service_endpoint = "https://example.com/service";
let service = ServiceBuilder::<()>::new(service_id, service_endpoint.try_into().unwrap())
.unwrap()
.add_service_type(service_type)
.unwrap()
.build()
.unwrap();
.build();

let document = DidDocumentBuilder::new(id.clone())
.add_also_known_as(also_known_as.clone())
Expand Down
84 changes: 57 additions & 27 deletions did_doc/src/schema/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ impl<E> Service<E>
where
E: Default,
{
pub fn builder(
id: Uri,
service_endpoint: Url,
) -> Result<ServiceBuilder<E>, DidDocumentBuilderError> {
pub fn builder(id: Uri, service_endpoint: Url) -> ServiceBuilder<E> {
ServiceBuilder::new(id, service_endpoint)
}

Expand All @@ -55,6 +52,13 @@ where

#[derive(Debug)]
pub struct ServiceBuilder<E> {
id: Uri,
service_endpoint: Url,
extra: E,
}

#[derive(Debug)]
pub struct ServiceBuilderWithServiceType<E> {
id: Uri,
service_type: HashSet<String>,
service_endpoint: Url,
Expand All @@ -65,15 +69,52 @@ impl<E> ServiceBuilder<E>
where
E: Default,
{
pub fn new(id: Uri, service_endpoint: Url) -> Result<Self, DidDocumentBuilderError> {
Ok(Self {
pub fn new(id: Uri, service_endpoint: Url) -> Self {
Self {
id,
service_endpoint,
service_type: HashSet::new(),
extra: E::default(),
}
}

pub fn add_service_type(
self,
service_type: String,
) -> Result<ServiceBuilderWithServiceType<E>, DidDocumentBuilderError> {
if service_type.is_empty() {
return Err(DidDocumentBuilderError::MissingField("type"));
}
let mut service_types = HashSet::new();
service_types.insert(service_type);
Ok(ServiceBuilderWithServiceType {
id: self.id,
service_type: service_types,
service_endpoint: self.service_endpoint,
extra: self.extra,
})
}

pub fn add_service_types(
self,
service_types: Vec<String>,
) -> Result<ServiceBuilderWithServiceType<E>, DidDocumentBuilderError> {
if service_types.is_empty() {
return Err(DidDocumentBuilderError::MissingField("type"));
}
let service_types = service_types.into_iter().collect::<HashSet<_>>();
Ok(ServiceBuilderWithServiceType {
id: self.id,
service_type: service_types,
service_endpoint: self.service_endpoint,
extra: self.extra,
})
}
}

impl<E> ServiceBuilderWithServiceType<E>
where
E: Default,
{
pub fn add_service_type(
mut self,
service_type: String,
Expand All @@ -90,16 +131,12 @@ where
self
}

pub fn build(self) -> Result<Service<E>, DidDocumentBuilderError> {
if self.service_type.is_empty() {
Err(DidDocumentBuilderError::MissingField("type"))
} else {
Ok(Service {
id: self.id,
service_type: OneOrList::List(self.service_type.into_iter().collect()),
service_endpoint: self.service_endpoint,
extra: self.extra,
})
pub fn build(self) -> Service<E> {
Service {
id: self.id,
service_type: OneOrList::List(self.service_type.into_iter().collect()),
service_endpoint: self.service_endpoint,
extra: self.extra,
}
}
}
Expand Down Expand Up @@ -128,11 +165,9 @@ mod tests {

let service =
ServiceBuilder::<ExtraSov>::new(id.clone(), service_endpoint.try_into().unwrap())
.unwrap()
.add_service_type(service_type.clone())
.unwrap()
.build()
.unwrap();
.build();

assert_eq!(service.id(), &id);
assert_eq!(service.service_endpoint().as_ref(), service_endpoint);
Expand All @@ -153,12 +188,10 @@ mod tests {
};

let service = ServiceBuilder::<ExtraSov>::new(id, service_endpoint.try_into().unwrap())
.unwrap()
.add_service_type(service_type)
.unwrap()
.add_extra(extra)
.build()
.unwrap();
.build();

assert_eq!(service.extra().recipient_keys, recipient_keys);
assert_eq!(service.extra().routing_keys, routing_keys);
Expand All @@ -171,13 +204,11 @@ mod tests {
let service_type = "DIDCommMessaging".to_string();

let service = ServiceBuilder::<ExtraSov>::new(id, service_endpoint.try_into().unwrap())
.unwrap()
.add_service_type(service_type.clone())
.unwrap()
.add_service_type(service_type.clone())
.unwrap()
.build()
.unwrap();
.build();

assert_eq!(service.service_type(), &OneOrList::List(vec![service_type]));
}
Expand All @@ -188,7 +219,6 @@ mod tests {
let service_endpoint = "http://example.com/endpoint";

let res = ServiceBuilder::<ExtraSov>::new(id, service_endpoint.try_into().unwrap())
.unwrap()
.add_service_type("".to_string());
assert!(res.is_err());
}
Expand Down
12 changes: 3 additions & 9 deletions did_resolver_sov/src/dereferencing/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,21 +117,17 @@ mod tests {
"did:example:123456789abcdefghi#agent".parse().unwrap(),
"https://agent.example.com/8377464".try_into().unwrap(),
)
.unwrap()
.add_service_type("AgentService".to_string())
.unwrap()
.build()
.unwrap();
.build();

let messaging_service = Service::builder(
"did:example:123456789abcdefghi#messages".parse().unwrap(),
"https://example.com/messages/8377464".try_into().unwrap(),
)
.unwrap()
.add_service_type("MessagingService".to_string())
.unwrap()
.build()
.unwrap();
.build();

DidDocument::builder(Default::default())
.add_verification_method(verification_method)
Expand Down Expand Up @@ -207,11 +203,9 @@ mod tests {
"did:example:123456789abcdefghi#keys-1".parse().unwrap(),
"https://example.com/duplicated/8377464".try_into().unwrap(),
)
.unwrap()
.add_service_type("DuplicatedService".to_string())
.unwrap()
.build()
.unwrap();
.build();
did_document_builder.add_service(additional_service).build()
};

Expand Down
90 changes: 90 additions & 0 deletions did_resolver_sov/src/resolution/extra_fields.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
pub struct ExtraFieldsSov {
#[serde(default)]
priority: u32,
#[serde(default)]
recipient_keys: Vec<String>,
#[serde(default)]
routing_keys: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
accept: Vec<String>,
}

impl ExtraFieldsSov {
pub fn builder() -> ExtraFieldsSovBuilder {
ExtraFieldsSovBuilder::default()
}

pub fn priority(&self) -> u32 {
self.priority
}

pub fn recipient_keys(&self) -> &[String] {
self.recipient_keys.as_ref()
}

pub fn routing_keys(&self) -> &[String] {
self.routing_keys.as_ref()
}

pub fn accept(&self) -> &[String] {
self.accept.as_ref()
}
}

#[derive(Default)]
pub struct ExtraFieldsSovBuilder {
priority: u32,
recipient_keys: Vec<String>,
routing_keys: Vec<String>,
accept: Vec<String>,
}

impl ExtraFieldsSovBuilder {
pub fn set_priority(&mut self, priority: u32) -> &mut Self {
self.priority = priority;
self
}

pub fn set_recipient_keys(&mut self, recipient_keys: Vec<String>) -> &mut Self {
self.recipient_keys = recipient_keys;
self
}

pub fn add_recipient_key(&mut self, recipient_key: String) -> &mut Self {
self.recipient_keys.push(recipient_key);
self
}

pub fn set_routing_keys(&mut self, routing_keys: Vec<String>) -> &mut Self {
self.routing_keys = routing_keys;
self
}

pub fn add_routing_key(&mut self, routing_key: String) -> &mut Self {
self.routing_keys.push(routing_key);
self
}

pub fn set_accept(&mut self, accept: Vec<String>) -> &mut Self {
self.accept = accept;
self
}

pub fn add_accept(&mut self, accept: String) -> &mut Self {
self.accept.push(accept);
self
}

pub fn build(&self) -> ExtraFieldsSov {
ExtraFieldsSov {
priority: self.priority,
recipient_keys: self.recipient_keys.clone(),
routing_keys: self.routing_keys.clone(),
accept: self.accept.clone(),
}
}
}
2 changes: 2 additions & 0 deletions did_resolver_sov/src/resolution/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
mod extra_fields;
mod resolver;
mod utils;

pub use extra_fields::ExtraFieldsSov;
pub use resolver::DidSovResolver;
5 changes: 4 additions & 1 deletion did_resolver_sov/src/resolution/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ use crate::{
reader::AttrReader,
};

use super::utils::{is_valid_sovrin_did_id, ledger_response_to_ddo};
use super::{
utils::{is_valid_sovrin_did_id, ledger_response_to_ddo},
ExtraFieldsSov,
};

pub struct DidSovResolver {
ledger: Arc<dyn AttrReader>,
Expand Down
17 changes: 9 additions & 8 deletions did_resolver_sov/src/resolution/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,15 @@ pub(super) async fn ledger_response_to_ddo<E: Default>(
let datetime = unix_to_datetime(txn_time);

let service = {
let mut service_builder =
Service::builder(service_id, endpoint.endpoint.as_str().try_into()?)?;
for t in endpoint.types {
if t != DidSovServiceType::Unknown {
service_builder = service_builder.add_service_type(t.to_string())?;
};
}
service_builder.build()?
let service_types: Vec<String> = endpoint
.types
.into_iter()
.filter(|t| *t != DidSovServiceType::Unknown)
.map(|t| t.to_string())
.collect();
Service::builder(service_id, endpoint.endpoint.as_str().try_into()?)
.add_service_types(service_types)?
.build()
};

// TODO: Use multibase instead of base58
Expand Down