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

Extract subset of changes made in #928 #939

Merged
merged 2 commits into from
Aug 16, 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
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 {
mirgee marked this conversation as resolved.
Show resolved Hide resolved
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
mirgee marked this conversation as resolved.
Show resolved Hide resolved
// * 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())?)?;
mirgee marked this conversation as resolved.
Show resolved Hide resolved
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
Loading