Skip to content

Commit

Permalink
Merge branch 'main' into patch-2
Browse files Browse the repository at this point in the history
  • Loading branch information
swcurran authored Sep 10, 2022
2 parents bf7b8bd + 981cc6d commit 09db6e1
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 111 deletions.
10 changes: 4 additions & 6 deletions aries_cloudagent/ledger/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,15 @@ async def _construct_attr_json(
if not routing_keys:
routing_keys = []

endpoint_dict = {"endpoint": endpoint}

if all_exist_endpoints:
all_exist_endpoints[endpoint_type.indy] = endpoint_dict
endpoint_dict["routingKeys"] = routing_keys
all_exist_endpoints[endpoint_type.indy] = endpoint
all_exist_endpoints["routingKeys"] = routing_keys
attr_json = json.dumps({"endpoint": all_exist_endpoints})

else:
endpoint_val = {endpoint_type.indy: endpoint_dict}
endpoint_dict = {endpoint_type.indy: endpoint}
endpoint_dict["routingKeys"] = routing_keys
attr_json = json.dumps({"endpoint": endpoint_val})
attr_json = json.dumps({"endpoint": endpoint_dict})

return attr_json

Expand Down
32 changes: 26 additions & 6 deletions aries_cloudagent/ledger/tests/test_indy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2308,17 +2308,37 @@ async def test_construct_attr_json_with_routing_keys(self, mock_close, mock_open
attr_json = await ledger._construct_attr_json(
"https://url",
EndpointType.ENDPOINT,
all_exist_endpoints={"Endpoint": "https://endpoint"},
routing_keys=["3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"],
)
assert attr_json == json.dumps(
{
"endpoint": {
"Endpoint": "https://endpoint",
"endpoint": {
"endpoint": "https://url",
"routingKeys": ["3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"],
},
"endpoint": "https://url",
"routingKeys": ["3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"],
}
}
)

@async_mock.patch("aries_cloudagent.ledger.indy.IndySdkLedgerPool.context_open")
@async_mock.patch("aries_cloudagent.ledger.indy.IndySdkLedgerPool.context_close")
@pytest.mark.asyncio
async def test_construct_attr_json_with_routing_keys_all_exist_endpoints(
self, mock_close, mock_open
):
ledger = IndySdkLedger(IndySdkLedgerPool("name", checked=True), self.profile)
async with ledger:
attr_json = await ledger._construct_attr_json(
"https://url",
EndpointType.ENDPOINT,
all_exist_endpoints={"profile": "https://endpoint/profile"},
routing_keys=["3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"],
)
assert attr_json == json.dumps(
{
"endpoint": {
"profile": "https://endpoint/profile",
"endpoint": "https://url",
"routingKeys": ["3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"],
}
}
)
Expand Down
40 changes: 20 additions & 20 deletions aries_cloudagent/ledger/tests/test_indy_vdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,27 +612,24 @@ async def test_update_endpoint_for_did(
"all_exist_endpoints, routing_keys, result",
[
(
{"Endpoint": "https://endpoint"},
{"profile": "https://endpoint/profile"},
["3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"],
{
"endpoint": {
"Endpoint": "https://endpoint",
"endpoint": {
"endpoint": "https://url",
"routingKeys": [
"3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"
],
},
"profile": "https://endpoint/profile",
"endpoint": "https://url",
"routingKeys": ["3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"],
}
},
),
(
{"Endpoint": "https://endpoint"},
{"profile": "https://endpoint/profile"},
None,
{
"endpoint": {
"Endpoint": "https://endpoint",
"endpoint": {"endpoint": "https://url", "routingKeys": []},
"profile": "https://endpoint/profile",
"endpoint": "https://url",
"routingKeys": [],
}
},
),
Expand All @@ -641,21 +638,24 @@ async def test_update_endpoint_for_did(
["3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"],
{
"endpoint": {
"endpoint": {
"endpoint": "https://url",
"routingKeys": [
"3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"
],
}
"endpoint": "https://url",
"routingKeys": ["3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"],
}
},
),
(None, None, {"endpoint": {"endpoint": "https://url", "routingKeys": []}}),
(
None,
None,
{
"profile": "https://endpoint/profile",
"spec_divergent_endpoint": "https://endpoint",
},
["3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"],
{
"endpoint": {
"endpoint": {"endpoint": "https://url", "routingKeys": []}
"profile": "https://endpoint/profile",
"spec_divergent_endpoint": "https://endpoint",
"endpoint": "https://url",
"routingKeys": ["3YJCx3TqotDWFGv7JMR5erEvrmgu5y4FDqjR7sKWxgXn"],
}
},
),
Expand Down
147 changes: 80 additions & 67 deletions aries_cloudagent/resolver/default/indy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
Resolution is performed using the IndyLedger class.
"""

from typing import Any, Mapping, Pattern
import logging
from typing import Optional, Pattern

from pydid import DID, DIDDocumentBuilder
from pydid.verification_method import Ed25519VerificationKey2018, VerificationMethod
Expand All @@ -21,6 +22,8 @@

from ..base import BaseDIDResolver, DIDNotFound, ResolverError, ResolverType

LOGGER = logging.getLogger(__name__)


class NoIndyLedger(ResolverError):
"""Raised when there is no Indy ledger instance configured."""
Expand All @@ -46,60 +49,85 @@ def supported_did_regex(self) -> Pattern:
"""Return supported_did_regex of Indy DID Resolver."""
return IndyDID.PATTERN

def _add_endpoint_as_endpoint_value_pair(
self,
builder: DIDDocumentBuilder,
endpoint: str,
recipient_key: VerificationMethod,
):
builder.service.add_didcomm(
ident=self.SERVICE_TYPE_DID_COMMUNICATION,
type_=self.SERVICE_TYPE_DID_COMMUNICATION,
service_endpoint=endpoint,
priority=1,
recipient_keys=[recipient_key],
routing_keys=[],
)

def _add_endpoint_as_map(
def process_endpoint_types(self, types):
"""Process endpoint types.
Returns expected types, subset of expected types,
or default types.
"""
expected_types = ["endpoint", "did-communication", "DIDComm"]
default_types = ["endpoint", "did-communication"]
if len(types) <= 0:
return default_types
for type in types:
if type not in expected_types:
return default_types
return types

def add_services(
self,
builder: DIDDocumentBuilder,
endpoint: Mapping[str, Any],
recipient_key: VerificationMethod,
endpoints: Optional[dict],
recipient_key: VerificationMethod = None,
):
types = endpoint.get("types", [self.SERVICE_TYPE_DID_COMMUNICATION])
routing_keys = endpoint.get("routingKeys", [])
endpoint_url = endpoint.get("endpoint")
if not endpoint_url:
raise ValueError("endpoint url not found in endpoint attrib")

if self.SERVICE_TYPE_DIDCOMM in types:
builder.service.add(
ident="#didcomm-1",
type_=self.SERVICE_TYPE_DIDCOMM,
service_endpoint=endpoint_url,
recipient_keys=[recipient_key.id],
routing_keys=routing_keys,
accept=["didcomm/v2"],
)
builder.context.append(self.CONTEXT_DIDCOMM_V2)
if self.SERVICE_TYPE_DID_COMMUNICATION in types:
builder.service.add(
ident="did-communication",
type_=self.SERVICE_TYPE_DID_COMMUNICATION,
service_endpoint=endpoint_url,
priority=1,
routing_keys=routing_keys,
recipient_keys=[recipient_key.id],
accept=["didcomm/aip2;env=rfc19"],
)
if self.SERVICE_TYPE_ENDPOINT in types:
builder.service.add(
ident="endpoint",
service_endpoint=endpoint_url,
type_=self.SERVICE_TYPE_ENDPOINT,
"""Add services."""
if not endpoints:
return

endpoint = endpoints.get("endpoint")
routing_keys = endpoints.get("routingKeys", [])
types = endpoints.get("types", [self.SERVICE_TYPE_DID_COMMUNICATION])

other_endpoints = {
key: endpoints[key]
for key in ("profile", "linked_domains")
if key in endpoints
}

if endpoint:
processed_types = self.process_endpoint_types(types)

if self.SERVICE_TYPE_ENDPOINT in processed_types:
builder.service.add(
ident="endpoint",
service_endpoint=endpoint,
type_=self.SERVICE_TYPE_ENDPOINT,
)

if self.SERVICE_TYPE_DID_COMMUNICATION in processed_types:
builder.service.add(
ident="did-communication",
type_=self.SERVICE_TYPE_DID_COMMUNICATION,
service_endpoint=endpoint,
priority=1,
routing_keys=routing_keys,
recipient_keys=[recipient_key.id],
accept=["didcomm/aip2;env=rfc19"],
)

if self.SERVICE_TYPE_DIDCOMM in types:
builder.service.add(
ident="#didcomm-1",
type_=self.SERVICE_TYPE_DIDCOMM,
service_endpoint=endpoint,
recipient_keys=[recipient_key.id],
routing_keys=routing_keys,
accept=["didcomm/v2"],
)
builder.context.append(self.CONTEXT_DIDCOMM_V2)
else:
LOGGER.warning(
"No endpoint for DID although endpoint attrib was resolvable"
)

if other_endpoints:
for type_, endpoint in other_endpoints.items():
builder.service.add(
ident=type_,
type_=EndpointType.get(type_).w3c,
service_endpoint=endpoint,
)

async def _resolve(self, profile: Profile, did: str) -> dict:
"""Resolve an indy DID."""
multitenant_mgr = profile.inject_or(BaseMultitenantManager)
Expand All @@ -119,7 +147,7 @@ async def _resolve(self, profile: Profile, did: str) -> dict:
try:
async with ledger:
recipient_key = await ledger.get_key_for_did(did)
endpoints = await ledger.get_all_endpoints_for_did(did)
endpoints: Optional[dict] = await ledger.get_all_endpoints_for_did(did)
except LedgerError as err:
raise DIDNotFound(f"DID {did} could not be resolved") from err

Expand All @@ -130,22 +158,7 @@ async def _resolve(self, profile: Profile, did: str) -> dict:
)
builder.authentication.reference(vmethod.id)
builder.assertion_method.reference(vmethod.id)
if endpoints:
for type_, endpoint in endpoints.items():
if type_ == EndpointType.ENDPOINT.indy:
if isinstance(endpoint, dict):
self._add_endpoint_as_map(builder, endpoint, vmethod)
else:
self._add_endpoint_as_endpoint_value_pair(
builder, endpoint, vmethod
)
else:
# Accept all service types for now, i.e. profile, linked_domains
builder.service.add(
ident=type_,
type_=type_,
service_endpoint=endpoint,
)
self.add_services(builder, endpoints, vmethod)

result = builder.build()
return result.serialize()
47 changes: 35 additions & 12 deletions aries_cloudagent/resolver/default/tests/test_indy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest

from asynctest import mock as async_mock
from pydid.verification_method import VerificationMethod

from ....core.in_memory import InMemoryProfile
from ....core.profile import Profile
Expand Down Expand Up @@ -116,11 +117,11 @@ async def test_supports_updated_did_sov_rules(
):
"""Test that new attrib structure is supported."""
example = {
"endpoint": {
"endpoint": "https://example.com/endpoint",
"routingKeys": ["a-routing-key"],
"types": ["DIDComm", "did-communication", "endpoint"],
}
"endpoint": "https://example.com/endpoint",
"routingKeys": ["a-routing-key"],
"types": ["DIDComm", "did-communication", "endpoint"],
"profile": "https://example.com",
"linked_domains": "https://example.com",
}

ledger.get_all_endpoints_for_did = async_mock.CoroutineMock(
Expand All @@ -129,19 +130,41 @@ async def test_supports_updated_did_sov_rules(
assert await resolver.resolve(profile, TEST_DID0)

@pytest.mark.asyncio
async def test_supports_updated_did_sov_rules_x_no_endpoint_url(
async def test_supports_updated_did_sov_rules_no_endpoint_url(
self, resolver: IndyDIDResolver, ledger: BaseLedger, profile: Profile
):
"""Test that new attrib structure is supported."""
example = {
"endpoint": {
"routingKeys": ["a-routing-key"],
"types": ["DIDComm", "did-communication", "endpoint"],
}
"routingKeys": ["a-routing-key"],
"types": ["DIDComm", "did-communication", "endpoint"],
}

ledger.get_all_endpoints_for_did = async_mock.CoroutineMock(
return_value=example
)
with pytest.raises(ValueError):
await resolver.resolve(profile, TEST_DID0)
result = await resolver.resolve(profile, TEST_DID0)
assert "service" not in result

@pytest.mark.parametrize(
"types, result",
[
(
[],
["endpoint", "did-communication"],
),
(
["did-communication"],
["did-communication"],
),
(
["endpoint", "did-communication", "DIDComm", "other-endpoint-type"],
["endpoint", "did-communication"],
),
(
["endpoint", "did-communication", "DIDComm"],
["endpoint", "did-communication", "DIDComm"],
),
],
)
def test_process_endpoint_types(self, resolver: IndyDIDResolver, types, result):
assert resolver.process_endpoint_types(types) == result

0 comments on commit 09db6e1

Please sign in to comment.