Skip to content

Commit eeebb9d

Browse files
Merge pull request openwallet-foundation#1863 from dbluhm/fix/did-sov-resolver
fix: resolve dids following new endpoint rules
2 parents 2b4c307 + 609f2e9 commit eeebb9d

2 files changed

Lines changed: 108 additions & 15 deletions

File tree

aries_cloudagent/resolver/default/indy.py

Lines changed: 67 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
Resolution is performed using the IndyLedger class.
44
"""
55

6-
from typing import Pattern
6+
from typing import Any, Mapping, Pattern
77

88
from pydid import DID, DIDDocumentBuilder
9-
from pydid.verification_method import Ed25519VerificationKey2018
9+
from pydid.verification_method import Ed25519VerificationKey2018, VerificationMethod
1010

1111
from ...config.injection_context import InjectionContext
1212
from ...core.profile import Profile
@@ -29,7 +29,10 @@ class NoIndyLedger(ResolverError):
2929
class IndyDIDResolver(BaseDIDResolver):
3030
"""Indy DID Resolver."""
3131

32-
AGENT_SERVICE_TYPE = "did-communication"
32+
SERVICE_TYPE_DID_COMMUNICATION = "did-communication"
33+
SERVICE_TYPE_DIDCOMM = "DIDComm"
34+
SERVICE_TYPE_ENDPOINT = "endpoint"
35+
CONTEXT_DIDCOMM_V2 = "https://didcomm.org/messaging/contexts/v2"
3336

3437
def __init__(self):
3538
"""Initialize Indy Resolver."""
@@ -43,6 +46,60 @@ def supported_did_regex(self) -> Pattern:
4346
"""Return supported_did_regex of Indy DID Resolver."""
4447
return IndyDID.PATTERN
4548

49+
def _add_endpoint_as_endpoint_value_pair(
50+
self,
51+
builder: DIDDocumentBuilder,
52+
endpoint: str,
53+
recipient_key: VerificationMethod,
54+
):
55+
builder.service.add_didcomm(
56+
ident=self.SERVICE_TYPE_DID_COMMUNICATION,
57+
type_=self.SERVICE_TYPE_DID_COMMUNICATION,
58+
service_endpoint=endpoint,
59+
priority=1,
60+
recipient_keys=[recipient_key],
61+
routing_keys=[],
62+
)
63+
64+
def _add_endpoint_as_map(
65+
self,
66+
builder: DIDDocumentBuilder,
67+
endpoint: Mapping[str, Any],
68+
recipient_key: VerificationMethod,
69+
):
70+
types = endpoint.get("types", [self.SERVICE_TYPE_DID_COMMUNICATION])
71+
routing_keys = endpoint.get("routingKeys", [])
72+
endpoint_url = endpoint.get("endpoint")
73+
if not endpoint_url:
74+
raise ValueError("endpoint url not found in endpoint attrib")
75+
76+
if self.SERVICE_TYPE_DIDCOMM in types:
77+
builder.service.add(
78+
ident="#didcomm-1",
79+
type_=self.SERVICE_TYPE_DIDCOMM,
80+
service_endpoint=endpoint_url,
81+
recipient_keys=[recipient_key.id],
82+
routing_keys=routing_keys,
83+
accept=["didcomm/v2"],
84+
)
85+
builder.context.append(self.CONTEXT_DIDCOMM_V2)
86+
if self.SERVICE_TYPE_DID_COMMUNICATION in types:
87+
builder.service.add(
88+
ident="did-communication",
89+
type_=self.SERVICE_TYPE_DID_COMMUNICATION,
90+
service_endpoint=endpoint_url,
91+
priority=1,
92+
routing_keys=routing_keys,
93+
recipient_keys=[recipient_key.id],
94+
accept=["didcomm/aip2;env=rfc19"],
95+
)
96+
if self.SERVICE_TYPE_ENDPOINT in types:
97+
builder.service.add(
98+
ident="endpoint",
99+
service_endpoint=endpoint_url,
100+
type_=self.SERVICE_TYPE_ENDPOINT,
101+
)
102+
46103
async def _resolve(self, profile: Profile, did: str) -> dict:
47104
"""Resolve an indy DID."""
48105
multitenant_mgr = profile.inject_or(BaseMultitenantManager)
@@ -76,16 +133,14 @@ async def _resolve(self, profile: Profile, did: str) -> dict:
76133
if endpoints:
77134
for type_, endpoint in endpoints.items():
78135
if type_ == EndpointType.ENDPOINT.indy:
79-
builder.service.add_didcomm(
80-
ident=self.AGENT_SERVICE_TYPE,
81-
type_=self.AGENT_SERVICE_TYPE,
82-
service_endpoint=endpoint,
83-
priority=1,
84-
recipient_keys=[vmethod],
85-
routing_keys=[],
86-
)
136+
if isinstance(endpoint, dict):
137+
self._add_endpoint_as_map(builder, endpoint, vmethod)
138+
else:
139+
self._add_endpoint_as_endpoint_value_pair(
140+
builder, endpoint, vmethod
141+
)
87142
else:
88-
# Accept all service types for now
143+
# Accept all service types for now, i.e. profile, linked_domains
89144
builder.service.add(
90145
ident=type_,
91146
type_=type_,

aries_cloudagent/resolver/default/tests/test_indy.py

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from ....multitenant.manager import MultitenantManager
1717

1818
from ...base import DIDNotFound, ResolverError
19-
from .. import indy as test_module
2019
from ..indy import IndyDIDResolver
2120

2221
# pylint: disable=W0621
@@ -33,8 +32,11 @@ def resolver():
3332
def ledger():
3433
"""Ledger fixture."""
3534
ledger = async_mock.MagicMock(spec=BaseLedger)
36-
ledger.get_endpoint_for_did = async_mock.CoroutineMock(
37-
return_value="https://github.com/"
35+
ledger.get_all_endpoints_for_did = async_mock.CoroutineMock(
36+
return_value={
37+
"endpoint": "https://github.com/",
38+
"profile": "https://example.com/profile",
39+
}
3840
)
3941
ledger.get_key_for_did = async_mock.CoroutineMock(return_value="key")
4042
yield ledger
@@ -107,3 +109,39 @@ async def test_resolve_x_did_not_found(
107109
ledger.get_key_for_did.side_effect = LedgerError
108110
with pytest.raises(DIDNotFound):
109111
await resolver.resolve(profile, TEST_DID0)
112+
113+
@pytest.mark.asyncio
114+
async def test_supports_updated_did_sov_rules(
115+
self, resolver: IndyDIDResolver, ledger: BaseLedger, profile: Profile
116+
):
117+
"""Test that new attrib structure is supported."""
118+
example = {
119+
"endpoint": {
120+
"endpoint": "https://example.com/endpoint",
121+
"routingKeys": ["a-routing-key"],
122+
"types": ["DIDComm", "did-communication", "endpoint"],
123+
}
124+
}
125+
126+
ledger.get_all_endpoints_for_did = async_mock.CoroutineMock(
127+
return_value=example
128+
)
129+
assert await resolver.resolve(profile, TEST_DID0)
130+
131+
@pytest.mark.asyncio
132+
async def test_supports_updated_did_sov_rules_x_no_endpoint_url(
133+
self, resolver: IndyDIDResolver, ledger: BaseLedger, profile: Profile
134+
):
135+
"""Test that new attrib structure is supported."""
136+
example = {
137+
"endpoint": {
138+
"routingKeys": ["a-routing-key"],
139+
"types": ["DIDComm", "did-communication", "endpoint"],
140+
}
141+
}
142+
143+
ledger.get_all_endpoints_for_did = async_mock.CoroutineMock(
144+
return_value=example
145+
)
146+
with pytest.raises(ValueError):
147+
await resolver.resolve(profile, TEST_DID0)

0 commit comments

Comments
 (0)