Skip to content

Commit

Permalink
Extract subset of changes made in #928 (#939)
Browse files Browse the repository at this point in the history
* Extract subset of changes made in didx PR

Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>

* Address code review

Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>

---------

Signed-off-by: Miroslav Kovar <miroslav.kovar@absa.africa>
  • Loading branch information
mirgee authored Aug 16, 2023
1 parent 3321031 commit 730c1e1
Show file tree
Hide file tree
Showing 19 changed files with 259 additions and 21 deletions.
23 changes: 23 additions & 0 deletions did_doc/src/schema/did_doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,29 @@ impl<E> DidDocumentBuilder<E> {
}
}

impl<E> From<DidDocument<E>> for DidDocumentBuilder<E> {
fn from(did_document: DidDocument<E>) -> Self {
let controller = match did_document.controller {
Some(OneOrList::List(list)) => list,
_ => Vec::new(),
};

Self {
id: did_document.id,
also_known_as: did_document.also_known_as,
controller,
verification_method: did_document.verification_method,
authentication: did_document.authentication,
assertion_method: did_document.assertion_method,
key_agreement: did_document.key_agreement,
capability_invocation: did_document.capability_invocation,
capability_delegation: did_document.capability_delegation,
service: did_document.service,
extra: did_document.extra,
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
1 change: 1 addition & 0 deletions did_doc/src/schema/types/url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use url::Url as UrlDep;

use crate::error::DidDocumentBuilderError;

// TODO: This was bad idea, get rid of it
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct Url(UrlDep);

Expand Down
7 changes: 7 additions & 0 deletions did_doc/src/schema/verification_method/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ impl PublicKeyField {
),
}
}

// TODO: Other formats
pub fn base58(&self) -> Result<String, DidDocumentBuilderError> {
Ok(bs58::encode(self.key_decoded()?).into_string())
}

// TODO: This should expose a PublicKey getter
}

#[cfg(test)]
Expand Down
2 changes: 2 additions & 0 deletions did_doc_sov/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ pub enum DidDocumentSovError {
UnexpectedServiceType(String),
#[error("Index out of bounds: {0}")]
IndexOutOfBounds(usize),
#[error("JSON error")]
JsonError(#[from] serde_json::Error),
}
1 change: 1 addition & 0 deletions did_doc_sov/src/extra_fields/aip1.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
#[serde(deny_unknown_fields)]
pub struct ExtraFieldsAIP1 {}
1 change: 1 addition & 0 deletions did_doc_sov/src/extra_fields/didcommv1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::{AcceptType, KeyKind};

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct ExtraFieldsDidCommV1 {
priority: u32,
recipient_keys: Vec<KeyKind>,
Expand Down
1 change: 1 addition & 0 deletions did_doc_sov/src/extra_fields/didcommv2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::{AcceptType, KeyKind};

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct ExtraFieldsDidCommV2 {
routing_keys: Vec<KeyKind>,
#[serde(default)]
Expand Down
114 changes: 109 additions & 5 deletions did_doc_sov/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ pub mod error;
pub mod extra_fields;
pub mod service;

use std::collections::HashMap;

use did_doc::{
did_parser::{Did, DidUrl},
schema::{
did_doc::{ControllerAlias, DidDocument, DidDocumentBuilder},
service::Service,
types::uri::Uri,
utils::OneOrList,
verification_method::{VerificationMethod, VerificationMethodKind},
},
};
Expand All @@ -15,15 +19,15 @@ use serde::{de, Deserialize, Deserializer, Serialize};
use serde_json::Value;
use service::ServiceSov;

#[derive(Serialize, Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub struct DidDocumentSov {
did_doc: DidDocument<ExtraFieldsSov>,
services: Vec<ServiceSov>,
}

impl DidDocumentSov {
pub fn builder() -> DidDocumentSovBuilder {
DidDocumentSovBuilder::default()
pub fn builder(id: Did) -> DidDocumentSovBuilder {
DidDocumentSovBuilder::new(id)
}

pub fn id(&self) -> &Did {
Expand Down Expand Up @@ -75,7 +79,6 @@ impl DidDocumentSov {
}
}

#[derive(Default)]
pub struct DidDocumentSovBuilder {
ddo_builder: DidDocumentBuilder<ExtraFieldsSov>,
services: Vec<ServiceSov>,
Expand All @@ -99,8 +102,20 @@ impl DidDocumentSovBuilder {
self
}

pub fn add_key_agreement(mut self, key_agreement: VerificationMethodKind) -> Self {
match key_agreement {
VerificationMethodKind::Resolved(ka) => {
self.ddo_builder = self.ddo_builder.add_key_agreement(ka);
}
VerificationMethodKind::Resolvable(ka_ref) => {
self.ddo_builder = self.ddo_builder.add_key_agreement_reference(ka_ref);
}
}
self
}

pub fn add_service(mut self, service: ServiceSov) -> Self {
self.services.push(service);
self.services.push(service.clone());
self
}

Expand Down Expand Up @@ -139,3 +154,92 @@ impl<'de> Deserialize<'de> for DidDocumentSov {
})
}
}

impl Serialize for DidDocumentSov {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut builder: DidDocumentBuilder<ExtraFieldsSov> = self.did_doc.clone().into();

for service_sov in &self.services {
let service: Service<ExtraFieldsSov> = service_sov.clone().try_into().map_err(serde::ser::Error::custom)?;
// Not very efficient, but
// * we don't expect many services
// * does not require allowing to remove services from existing DDO or builder
if !self.did_doc.service().iter().any(|s| s.id() == service.id()) {
builder = builder.add_service(service);
}
}

builder.build().serialize(serializer)
}
}

impl From<DidDocumentSov> for DidDocument<ExtraFieldsSov> {
fn from(ddo: DidDocumentSov) -> Self {
let mut ddo_builder = DidDocument::<ExtraFieldsSov>::builder(ddo.did_doc.id().clone());
for service in ddo.service() {
ddo_builder = ddo_builder.add_service(service.clone().try_into().unwrap());
}
if let Some(controller) = ddo.did_doc.controller() {
match controller {
OneOrList::One(controller) => {
ddo_builder = ddo_builder.add_controller(controller.clone());
}
OneOrList::List(list) => {
for controller in list {
ddo_builder = ddo_builder.add_controller(controller.clone());
}
}
}
}
for vm in ddo.verification_method() {
ddo_builder = ddo_builder.add_verification_method(vm.clone());
}
for ka in ddo.key_agreement() {
match ka {
VerificationMethodKind::Resolved(ka) => {
ddo_builder = ddo_builder.add_key_agreement(ka.clone());
}
VerificationMethodKind::Resolvable(ka_ref) => {
ddo_builder = ddo_builder.add_key_agreement_reference(ka_ref.clone());
}
}
}
ddo_builder.build()
}
}

impl From<DidDocument<ExtraFieldsSov>> for DidDocumentSov {
fn from(ddo: DidDocument<ExtraFieldsSov>) -> Self {
let mut builder = DidDocumentSov::builder(ddo.id().clone());
for service in ddo.service() {
builder = builder.add_service(service.clone().try_into().unwrap());
}
for vm in ddo.verification_method() {
builder = builder.add_verification_method(vm.clone());
}
for ka in ddo.key_agreement() {
builder = builder.add_key_agreement(ka.clone());
}
// TODO: Controller
builder.build()
}
}

impl From<DidDocument<HashMap<String, Value>>> for DidDocumentSov {
fn from(ddo: DidDocument<HashMap<String, Value>>) -> Self {
let mut builder = DidDocumentSov::builder(ddo.id().clone());
for service in ddo.service() {
builder = builder.add_service(service.clone().try_into().unwrap());
}
for vm in ddo.verification_method() {
builder = builder.add_verification_method(vm.clone());
}
for ka in ddo.key_agreement() {
builder = builder.add_key_agreement(ka.clone());
}
builder.build()
}
}
12 changes: 12 additions & 0 deletions did_doc_sov/src/service/aip1.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::collections::HashMap;

use did_doc::schema::{
service::Service,
types::{uri::Uri, url::Url},
utils::OneOrList,
};
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{
error::DidDocumentSovError,
Expand Down Expand Up @@ -59,6 +62,15 @@ impl TryFrom<Service<ExtraFieldsSov>> for ServiceAIP1 {
}
}

impl TryFrom<Service<HashMap<String, Value>>> for ServiceAIP1 {
type Error = DidDocumentSovError;

fn try_from(service: Service<HashMap<String, Value>>) -> Result<Self, Self::Error> {
let extra = serde_json::from_value::<ExtraFieldsAIP1>(serde_json::to_value(service.extra())?)?;
Self::new(service.id().clone(), service.service_endpoint().clone(), extra)
}
}

impl<'de> Deserialize<'de> for ServiceAIP1 {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down
12 changes: 12 additions & 0 deletions did_doc_sov/src/service/didcommv1.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::collections::HashMap;

use did_doc::schema::{
service::Service,
types::{uri::Uri, url::Url},
utils::OneOrList,
};
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{
error::DidDocumentSovError,
Expand Down Expand Up @@ -59,6 +62,15 @@ impl TryFrom<Service<ExtraFieldsSov>> for ServiceDidCommV1 {
}
}

impl TryFrom<Service<HashMap<String, Value>>> for ServiceDidCommV1 {
type Error = DidDocumentSovError;

fn try_from(service: Service<HashMap<String, Value>>) -> Result<Self, Self::Error> {
let extra = serde_json::from_value::<ExtraFieldsDidCommV1>(serde_json::to_value(service.extra())?)?;
Self::new(service.id().clone(), service.service_endpoint().clone(), extra)
}
}

impl<'de> Deserialize<'de> for ServiceDidCommV1 {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down
12 changes: 12 additions & 0 deletions did_doc_sov/src/service/didcommv2.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::collections::HashMap;

use did_doc::schema::{
service::Service,
types::{uri::Uri, url::Url},
utils::OneOrList,
};
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{
error::DidDocumentSovError,
Expand Down Expand Up @@ -59,6 +62,15 @@ impl TryFrom<Service<ExtraFieldsSov>> for ServiceDidCommV2 {
}
}

impl TryFrom<Service<HashMap<String, Value>>> for ServiceDidCommV2 {
type Error = DidDocumentSovError;

fn try_from(service: Service<HashMap<String, Value>>) -> Result<Self, Self::Error> {
let extra = serde_json::from_value::<ExtraFieldsDidCommV2>(serde_json::to_value(service.extra())?)?;
Self::new(service.id().clone(), service.service_endpoint().clone(), extra)
}
}

impl<'de> Deserialize<'de> for ServiceDidCommV2 {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down
19 changes: 18 additions & 1 deletion did_doc_sov/src/service/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::fmt::Display;
use std::{collections::HashMap, fmt::Display};

use did_doc::schema::{
service::Service,
types::{uri::Uri, url::Url},
};
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::{error::DidDocumentSovError, extra_fields::ExtraFieldsSov};

Expand Down Expand Up @@ -83,6 +84,22 @@ impl TryFrom<Service<ExtraFieldsSov>> for ServiceSov {
}
}

impl TryFrom<Service<HashMap<String, Value>>> for ServiceSov {
type Error = DidDocumentSovError;

fn try_from(service: Service<HashMap<String, Value>>) -> Result<Self, Self::Error> {
match service.extra().get("type") {
Some(service_type) => match service_type.as_str() {
Some("AIP1") => Ok(ServiceSov::AIP1(service.try_into()?)),
Some("DIDCommV1") => Ok(ServiceSov::DIDCommV1(service.try_into()?)),
Some("DIDCommV2") => Ok(ServiceSov::DIDCommV2(service.try_into()?)),
_ => Err(DidDocumentSovError::UnexpectedServiceType(service_type.to_string())),
},
None => Ok(ServiceSov::AIP1(service.try_into()?)),
}
}
}

impl TryFrom<ServiceSov> for Service<ExtraFieldsSov> {
type Error = DidDocumentSovError;

Expand Down
8 changes: 5 additions & 3 deletions did_doc_sov/tests/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ fn test_service_build_aip1() {
ExtraFieldsAIP1::default(),
)
.unwrap();
let did_doc = DidDocumentSov::builder().add_service(ServiceSov::AIP1(service)).build();
let did_doc = DidDocumentSov::builder(Default::default())
.add_service(ServiceSov::AIP1(service))
.build();
let services = did_doc.service();
assert_eq!(services.len(), 1);
let first_service = services.get(0).unwrap();
Expand Down Expand Up @@ -44,7 +46,7 @@ fn test_service_build_didcommv1() {
extra_fields_didcommv1,
)
.unwrap();
let did_doc = DidDocumentSov::builder()
let did_doc = DidDocumentSov::builder(Default::default())
.add_service(ServiceSov::DIDCommV1(service))
.build();
let services = did_doc.service();
Expand Down Expand Up @@ -75,7 +77,7 @@ fn test_service_build_didcommv2() {
extra_fields_didcommv2,
)
.unwrap();
let did_doc = DidDocumentSov::builder()
let did_doc = DidDocumentSov::builder(Default::default())
.add_service(ServiceSov::DIDCommV2(service))
.build();
let services = did_doc.service();
Expand Down
Loading

0 comments on commit 730c1e1

Please sign in to comment.