From 4788507cba7a3f296184f73de9596624a6339120 Mon Sep 17 00:00:00 2001 From: Adam Burdett Date: Tue, 9 Aug 2022 13:02:15 -0600 Subject: [PATCH 1/4] Signed-off-by: Adam Burdett Co-authored-by: Daniel Bluhm --- DIDResolution.md | 8 +++--- aries_cloudagent/config/default_context.py | 6 +--- aries_cloudagent/core/tests/test_conductor.py | 4 +-- .../connections/v1_0/tests/test_manager.py | 9 ++---- .../dif/tests/test_pres_exch_handler.py | 5 +--- aries_cloudagent/resolver/__init__.py | 14 +++++----- aries_cloudagent/resolver/did_resolver.py | 13 +++++---- .../resolver/did_resolver_registry.py | 28 ------------------- .../resolver/tests/test_did_resolver.py | 19 ++++--------- .../tests/test_did_resolver_registry.py | 12 -------- aries_cloudagent/wallet/did_method.py | 9 ++++-- 11 files changed, 36 insertions(+), 91 deletions(-) delete mode 100644 aries_cloudagent/resolver/did_resolver_registry.py delete mode 100644 aries_cloudagent/resolver/tests/test_did_resolver_registry.py diff --git a/DIDResolution.md b/DIDResolution.md index c1666adab2..dbf11965ce 100644 --- a/DIDResolution.md +++ b/DIDResolution.md @@ -29,7 +29,7 @@ In practice, DIDs and DID Documents are used for a variety of purposes but espec ## `DIDResolver` -In ACA-Py, the `DIDResolver` provides the interface to resolve DIDs using registered method resolvers. Method resolver registration happens on startup through the `DIDResolverRegistry`. This registry enables additional resolvers to be loaded via plugin. +In ACA-Py, the `DIDResolver` provides the interface to resolve DIDs using registered method resolvers. Method resolver registration happens on startup in a `did_resolers` list. This registry enables additional resolvers to be loaded via plugin. #### Example usage: ```python= @@ -73,17 +73,17 @@ The following is an example method resolver implementation. In this example, we ```python= from aries_cloudagent.config.injection_context import InjectionContext -from aries_cloudagent.resolver.did_resolver_registry import DIDResolverRegistry +from ..resolver.did_resolver import DIDResolver from .example_resolver import ExampleResolver async def setup(context: InjectionContext): """Setup the plugin.""" - registry = context.inject(DIDResolverRegistry) + registry = context.inject(DIDResolver) resolver = ExampleResolver() await resolver.setup(context) - registry.register(resolver) + registry.append(resolver) ``` #### `example_resolver.py` diff --git a/aries_cloudagent/config/default_context.py b/aries_cloudagent/config/default_context.py index fb0867cddc..e3d9b24770 100644 --- a/aries_cloudagent/config/default_context.py +++ b/aries_cloudagent/config/default_context.py @@ -12,7 +12,6 @@ from ..core.protocol_registry import ProtocolRegistry from ..core.goal_code_registry import GoalCodeRegistry from ..resolver.did_resolver import DIDResolver -from ..resolver.did_resolver_registry import DIDResolverRegistry from ..tails.base import BaseTailsServer from ..protocols.actionmenu.v1_0.base_service import BaseMenuService @@ -50,12 +49,9 @@ async def build_context(self) -> InjectionContext: # Global event bus context.injector.bind_instance(EventBus, EventBus()) - # Global did resolver registry - did_resolver_registry = DIDResolverRegistry() - context.injector.bind_instance(DIDResolverRegistry, did_resolver_registry) # Global did resolver - context.injector.bind_instance(DIDResolver, DIDResolver(did_resolver_registry)) + context.injector.bind_instance(DIDResolver, DIDResolver([])) await self.bind_providers(context) await self.load_plugins(context) diff --git a/aries_cloudagent/core/tests/test_conductor.py b/aries_cloudagent/core/tests/test_conductor.py index 02fbe4ff49..203ca1b3b4 100644 --- a/aries_cloudagent/core/tests/test_conductor.py +++ b/aries_cloudagent/core/tests/test_conductor.py @@ -24,7 +24,7 @@ from ...protocols.coordinate_mediation.v1_0.models.mediation_record import ( MediationRecord, ) -from ...resolver.did_resolver import DIDResolver, DIDResolverRegistry +from ...resolver.did_resolver import DIDResolver from ...multitenant.base import BaseMultitenantManager from ...multitenant.manager import MultitenantManager from ...storage.base import BaseStorage @@ -92,7 +92,7 @@ async def build_context(self) -> InjectionContext: context.injector.bind_instance(ProfileManager, InMemoryProfileManager()) context.injector.bind_instance(ProtocolRegistry, ProtocolRegistry()) context.injector.bind_instance(BaseWireFormat, self.wire_format) - context.injector.bind_instance(DIDResolver, DIDResolver(DIDResolverRegistry())) + context.injector.bind_instance(DIDResolver, DIDResolver([])) context.injector.bind_instance(EventBus, MockEventBus()) return context diff --git a/aries_cloudagent/protocols/connections/v1_0/tests/test_manager.py b/aries_cloudagent/protocols/connections/v1_0/tests/test_manager.py index d7c3836236..80efb456bf 100644 --- a/aries_cloudagent/protocols/connections/v1_0/tests/test_manager.py +++ b/aries_cloudagent/protocols/connections/v1_0/tests/test_manager.py @@ -20,7 +20,6 @@ from .....multitenant.manager import MultitenantManager from .....protocols.routing.v1_0.manager import RoutingManager from .....resolver.did_resolver import DIDResolver -from .....resolver.did_resolver_registry import DIDResolverRegistry from .....storage.error import StorageNotFoundError from .....transport.inbound.receipt import MessageReceipt from .....wallet.base import DIDInfo @@ -2024,9 +2023,7 @@ async def test_fetch_connection_targets_no_my_did(self): async def test_fetch_connection_targets_conn_invitation_did_no_resolver(self): async with self.profile.session() as session: - self.context.injector.bind_instance( - DIDResolver, DIDResolver(DIDResolverRegistry()) - ) + self.context.injector.bind_instance(DIDResolver, DIDResolver([])) await session.wallet.create_local_did( method=DIDMethod.SOV, key_type=KeyType.ED25519, @@ -2320,9 +2317,7 @@ async def test_fetch_connection_targets_conn_invitation_unsupported_key_type(sel async def test_fetch_connection_targets_oob_invitation_svc_did_no_resolver(self): async with self.profile.session() as session: - self.context.injector.bind_instance( - DIDResolver, DIDResolver(DIDResolverRegistry()) - ) + self.context.injector.bind_instance(DIDResolver, DIDResolver([])) await session.wallet.create_local_did( method=DIDMethod.SOV, key_type=KeyType.ED25519, diff --git a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py index 509e87ba6f..87587eb674 100644 --- a/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py +++ b/aries_cloudagent/protocols/present_proof/dif/tests/test_pres_exch_handler.py @@ -8,7 +8,6 @@ from .....core.in_memory import InMemoryProfile from .....did.did_key import DIDKey -from .....resolver.did_resolver_registry import DIDResolverRegistry from .....resolver.did_resolver import DIDResolver from .....storage.vc_holder.vc_record import VCRecord from .....wallet.base import BaseWallet, DIDInfo @@ -69,9 +68,7 @@ def event_loop(request): def profile(): profile = InMemoryProfile.test_profile() context = profile.context - did_resolver_registry = DIDResolverRegistry() - context.injector.bind_instance(DIDResolverRegistry, did_resolver_registry) - context.injector.bind_instance(DIDResolver, DIDResolver(did_resolver_registry)) + context.injector.bind_instance(DIDResolver, DIDResolver([])) context.injector.bind_instance(DocumentLoader, custom_document_loader) context.settings["debug.auto_respond_presentation_request"] = True return profile diff --git a/aries_cloudagent/resolver/__init__.py b/aries_cloudagent/resolver/__init__.py index 51bef53657..e4b82549d7 100644 --- a/aries_cloudagent/resolver/__init__.py +++ b/aries_cloudagent/resolver/__init__.py @@ -5,30 +5,30 @@ from ..config.injection_context import InjectionContext from ..config.provider import ClassProvider -from .did_resolver_registry import DIDResolverRegistry +from ..resolver.did_resolver import DIDResolver LOGGER = logging.getLogger(__name__) async def setup(context: InjectionContext): """Set up default resolvers.""" - registry = context.inject_or(DIDResolverRegistry) + registry = context.inject_or(DIDResolver) if not registry: - LOGGER.warning("No DID Resolver Registry instance found in context") + LOGGER.warning("No DID Resolver instance found in context") return key_resolver = ClassProvider( "aries_cloudagent.resolver.default.key.KeyDIDResolver" ).provide(context.settings, context.injector) await key_resolver.setup(context) - registry.register(key_resolver) + registry.register_resolver(key_resolver) if not context.settings.get("ledger.disabled"): indy_resolver = ClassProvider( "aries_cloudagent.resolver.default.indy.IndyDIDResolver" ).provide(context.settings, context.injector) await indy_resolver.setup(context) - registry.register(indy_resolver) + registry.register_resolver(indy_resolver) else: LOGGER.warning("Ledger is not configured, not loading IndyDIDResolver") @@ -36,11 +36,11 @@ async def setup(context: InjectionContext): "aries_cloudagent.resolver.default.web.WebDIDResolver" ).provide(context.settings, context.injector) await web_resolver.setup(context) - registry.register(web_resolver) + registry.register_resolver(web_resolver) if context.settings.get("resolver.universal"): universal_resolver = ClassProvider( "aries_cloudagent.resolver.default.universal.UniversalResolver" ).provide(context.settings, context.injector) await universal_resolver.setup(context) - registry.register(universal_resolver) + registry.register_resolver(universal_resolver) diff --git a/aries_cloudagent/resolver/did_resolver.py b/aries_cloudagent/resolver/did_resolver.py index f57ec47fd9..bf52959043 100644 --- a/aries_cloudagent/resolver/did_resolver.py +++ b/aries_cloudagent/resolver/did_resolver.py @@ -8,7 +8,7 @@ from datetime import datetime from itertools import chain import logging -from typing import Sequence, Tuple, Type, TypeVar, Union +from typing import List, Sequence, Tuple, Type, TypeVar, Union from pydid import DID, DIDError, DIDUrl, Resource, NonconformantDocument from pydid.doc.doc import IDNotFoundError @@ -22,7 +22,6 @@ ResolutionResult, ResolverError, ) -from .did_resolver_registry import DIDResolverRegistry LOGGER = logging.getLogger(__name__) @@ -33,9 +32,13 @@ class DIDResolver: """did resolver singleton.""" - def __init__(self, registry: DIDResolverRegistry): + def __init__(self, resolvers: List[BaseDIDResolver] = None): """Create DID Resolver.""" - self.did_resolver_registry = registry + self.resolvers = resolvers or [] + + def register_resolver(self, resolver: BaseDIDResolver): + """Register a new resolver.""" + self.resolvers.append(resolver) async def _resolve( self, profile: Profile, did: Union[str, DID] @@ -90,7 +93,7 @@ async def _match_did_to_resolver( """ valid_resolvers = [ resolver - for resolver in self.did_resolver_registry.resolvers + for resolver in self.resolvers if await resolver.supports(profile, did) ] native_resolvers = filter(lambda resolver: resolver.native, valid_resolvers) diff --git a/aries_cloudagent/resolver/did_resolver_registry.py b/aries_cloudagent/resolver/did_resolver_registry.py deleted file mode 100644 index 4154454236..0000000000 --- a/aries_cloudagent/resolver/did_resolver_registry.py +++ /dev/null @@ -1,28 +0,0 @@ -"""In memmory storage for registering did resolvers.""" - -import logging -from typing import Sequence - -from .base import BaseDIDResolver - -LOGGER = logging.getLogger(__name__) - - -class DIDResolverRegistry: - """Registry for did resolvers.""" - - def __init__(self): - """Initialize list for did resolvers.""" - self._resolvers = [] - - @property - def resolvers( - self, - ) -> Sequence[BaseDIDResolver]: - """Accessor for a list of all did resolvers.""" - return self._resolvers - - def register(self, resolver) -> None: - """Register a resolver.""" - LOGGER.debug("Registering resolver %s", resolver) - self._resolvers.append(resolver) diff --git a/aries_cloudagent/resolver/tests/test_did_resolver.py b/aries_cloudagent/resolver/tests/test_did_resolver.py index b08480e805..38d7a1cf71 100644 --- a/aries_cloudagent/resolver/tests/test_did_resolver.py +++ b/aries_cloudagent/resolver/tests/test_did_resolver.py @@ -18,7 +18,6 @@ ResolverType, ) from ..did_resolver import DIDResolver -from ..did_resolver_registry import DIDResolverRegistry from . import DOC @@ -88,10 +87,10 @@ async def _resolve(self, profile, did): @pytest.fixture def resolver(): - did_resolver_registry = DIDResolverRegistry() + did_resolver_registry = [] for method in TEST_DID_METHODS: resolver = MockResolver([method], DIDDocument.deserialize(DOC)) - did_resolver_registry.register(resolver) + did_resolver_registry.append(resolver) return DIDResolver(did_resolver_registry) @@ -121,11 +120,9 @@ async def test_match_did_to_resolver_x_not_supported(resolver): @pytest.mark.asyncio async def test_match_did_to_resolver_native_priority(profile): - registry = DIDResolverRegistry() native = MockResolver(["sov"], native=True) non_native = MockResolver(["sov"], native=False) - registry.register(non_native) - registry.register(native) + registry = [non_native, native] resolver = DIDResolver(registry) assert [native, non_native] == await resolver._match_did_to_resolver( profile, TEST_DID0 @@ -134,15 +131,11 @@ async def test_match_did_to_resolver_native_priority(profile): @pytest.mark.asyncio async def test_match_did_to_resolver_registration_order(profile): - registry = DIDResolverRegistry() native1 = MockResolver(["sov"], native=True) - registry.register(native1) native2 = MockResolver(["sov"], native=True) - registry.register(native2) non_native3 = MockResolver(["sov"], native=False) - registry.register(non_native3) native4 = MockResolver(["sov"], native=True) - registry.register(native4) + registry = [native1, native2, non_native3, native4] resolver = DIDResolver(registry) assert [ native1, @@ -200,8 +193,6 @@ async def test_resolve_did_x_not_supported(resolver, profile): async def test_resolve_did_x_not_found(profile): py_did = DID("did:cowsay:EiDahaOGH-liLLdDtTxEAdc8i-cfCz-WUcQdRJheMVNn3A") cowsay_resolver_not_found = MockResolver(["cowsay"], resolved=DIDNotFound()) - registry = DIDResolverRegistry() - registry.register(cowsay_resolver_not_found) - resolver = DIDResolver(registry) + resolver = DIDResolver([cowsay_resolver_not_found]) with pytest.raises(DIDNotFound): await resolver.resolve(profile, py_did) diff --git a/aries_cloudagent/resolver/tests/test_did_resolver_registry.py b/aries_cloudagent/resolver/tests/test_did_resolver_registry.py deleted file mode 100644 index dba7afffbd..0000000000 --- a/aries_cloudagent/resolver/tests/test_did_resolver_registry.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Test did resolver registery.""" - -import pytest -import unittest -from ..did_resolver_registry import DIDResolverRegistry - - -def test_create_registry(): - did_resolver_registry = DIDResolverRegistry() - test_resolver = unittest.mock.MagicMock() - did_resolver_registry.register(test_resolver) - assert did_resolver_registry.resolvers == [test_resolver] diff --git a/aries_cloudagent/wallet/did_method.py b/aries_cloudagent/wallet/did_method.py index 82382ea39b..797c26fd20 100644 --- a/aries_cloudagent/wallet/did_method.py +++ b/aries_cloudagent/wallet/did_method.py @@ -47,7 +47,8 @@ def supports_key_type(self, key_type: KeyType) -> bool: """Check whether the current method supports the key type.""" return key_type in self.supported_key_types - def from_metadata(metadata: Mapping) -> "DIDMethod": + @classmethod + def from_metadata(cls, metadata: Mapping) -> "DIDMethod": """Get DID method instance from metadata object. Returns SOV if no metadata was found for backwards compatability. @@ -63,7 +64,8 @@ def from_metadata(metadata: Mapping) -> "DIDMethod": # return default SOV for backward compat return DIDMethod.SOV - def from_method(method: str) -> Optional["DIDMethod"]: + @classmethod + def from_method(cls, method: str) -> Optional["DIDMethod"]: """Get DID method instance from the method name.""" for did_method in DIDMethod: if method == did_method.method_name: @@ -71,7 +73,8 @@ def from_method(method: str) -> Optional["DIDMethod"]: return None - def from_did(did: str) -> "DIDMethod": + @classmethod + def from_did(cls, did: str) -> "DIDMethod": """Get DID method instance from the method name.""" if not did.startswith("did:"): # sov has no prefix From 2d15ca4e190dbcce53649c59734da2cd7d8a43f3 Mon Sep 17 00:00:00 2001 From: Adam Burdett Date: Tue, 9 Aug 2022 13:36:40 -0600 Subject: [PATCH 2/4] formatting Signed-off-by: Adam Burdett --- aries_cloudagent/config/default_context.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aries_cloudagent/config/default_context.py b/aries_cloudagent/config/default_context.py index e3d9b24770..0c5f90cac2 100644 --- a/aries_cloudagent/config/default_context.py +++ b/aries_cloudagent/config/default_context.py @@ -49,7 +49,6 @@ async def build_context(self) -> InjectionContext: # Global event bus context.injector.bind_instance(EventBus, EventBus()) - # Global did resolver context.injector.bind_instance(DIDResolver, DIDResolver([])) From 06a7a1855bb6310c609e7ef4cd949a08a539b393 Mon Sep 17 00:00:00 2001 From: Adam Burdett Date: Wed, 10 Aug 2022 10:36:42 -0600 Subject: [PATCH 3/4] test update Signed-off-by: Adam Burdett --- aries_cloudagent/resolver/tests/test_did_resolver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aries_cloudagent/resolver/tests/test_did_resolver.py b/aries_cloudagent/resolver/tests/test_did_resolver.py index 38d7a1cf71..f2c4ba9ab5 100644 --- a/aries_cloudagent/resolver/tests/test_did_resolver.py +++ b/aries_cloudagent/resolver/tests/test_did_resolver.py @@ -100,7 +100,7 @@ def profile(): def test_create_resolver(resolver): - assert len(resolver.did_resolver_registry.resolvers) == len(TEST_DID_METHODS) + assert len(resolver.resolvers) == len(TEST_DID_METHODS) @pytest.mark.asyncio From 7a006850b81a6c535d3af619d9f49ef836ecafe5 Mon Sep 17 00:00:00 2001 From: Adam Burdett Date: Mon, 29 Aug 2022 13:37:49 -0400 Subject: [PATCH 4/4] fix: typo in DIDResolution.md Co-authored-by: Andrew Whitehead Signed-off-by: Adam Burdett --- DIDResolution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DIDResolution.md b/DIDResolution.md index dbf11965ce..cbe00edc1d 100644 --- a/DIDResolution.md +++ b/DIDResolution.md @@ -29,7 +29,7 @@ In practice, DIDs and DID Documents are used for a variety of purposes but espec ## `DIDResolver` -In ACA-Py, the `DIDResolver` provides the interface to resolve DIDs using registered method resolvers. Method resolver registration happens on startup in a `did_resolers` list. This registry enables additional resolvers to be loaded via plugin. +In ACA-Py, the `DIDResolver` provides the interface to resolve DIDs using registered method resolvers. Method resolver registration happens on startup in a `did_resolvers` list. This registry enables additional resolvers to be loaded via plugin. #### Example usage: ```python=