Skip to content

Commit 04327cf

Browse files
authored
Merge pull request openwallet-foundation#1851 from sicpa-dlab/feature/manual-keylist-update
Enable manually triggering keylist updates during connection
2 parents cb584c0 + 9b870be commit 04327cf

28 files changed

Lines changed: 2055 additions & 1563 deletions

aries_cloudagent/config/wallet.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77
from ..core.profile import Profile, ProfileManager, ProfileSession
88
from ..storage.base import BaseStorage
99
from ..storage.error import StorageNotFoundError
10-
from ..version import __version__, RECORD_TYPE_ACAPY_VERSION
10+
from ..version import RECORD_TYPE_ACAPY_VERSION, __version__
1111
from ..wallet.base import BaseWallet
12-
from ..wallet.did_info import DIDInfo
1312
from ..wallet.crypto import seed_to_did
14-
from ..wallet.key_type import KeyType
13+
from ..wallet.did_info import DIDInfo
1514
from ..wallet.did_method import DIDMethod
16-
15+
from ..wallet.key_type import KeyType
1716
from .base import ConfigError
1817
from .injection_context import InjectionContext
1918

aries_cloudagent/connections/base_manager.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
from ..protocols.coordinate_mediation.v1_0.models.mediation_record import (
2525
MediationRecord,
2626
)
27+
from ..protocols.coordinate_mediation.v1_0.route_manager import (
28+
RouteManager,
29+
)
2730
from ..resolver.base import ResolverError
2831
from ..resolver.did_resolver import DIDResolver
2932
from ..storage.base import BaseStorage
@@ -56,6 +59,7 @@ def __init__(self, profile: Profile):
5659
"""
5760
self._logger = logging.getLogger(__name__)
5861
self._profile = profile
62+
self._route_manager = profile.inject(RouteManager)
5963

6064
async def create_did_document(
6165
self,

aries_cloudagent/connections/util.py

Lines changed: 0 additions & 36 deletions
This file was deleted.

aries_cloudagent/core/conductor.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,20 @@
1111
import hashlib
1212
import json
1313
import logging
14+
1415
from qrcode import QRCode
1516

1617
from ..admin.base_server import BaseAdminServer
1718
from ..admin.server import AdminResponder, AdminServer
1819
from ..config.default_context import ContextBuilder
1920
from ..config.injection_context import InjectionContext
20-
from ..config.provider import ClassProvider
2121
from ..config.ledger import (
2222
get_genesis_transactions,
2323
ledger_config,
2424
load_multiple_genesis_transactions_from_config,
2525
)
2626
from ..config.logging import LoggingConfigurator
27+
from ..config.provider import ClassProvider
2728
from ..config.wallet import wallet_config
2829
from ..core.profile import Profile
2930
from ..indy.verifier import IndyVerifier
@@ -33,8 +34,8 @@
3334
BaseMultipleLedgerManager,
3435
MultipleLedgerManagerError,
3536
)
36-
from ..ledger.multiple_ledger.manager_provider import MultiIndyLedgerManagerProvider
3737
from ..ledger.multiple_ledger.ledger_requests_executor import IndyLedgerRequestsExecutor
38+
from ..ledger.multiple_ledger.manager_provider import MultiIndyLedgerManagerProvider
3839
from ..messaging.responder import BaseResponder
3940
from ..multitenant.base import BaseMultitenantManager
4041
from ..multitenant.manager_provider import MultitenantManagerProvider
@@ -45,8 +46,12 @@
4546
from ..protocols.connections.v1_0.messages.connection_invitation import (
4647
ConnectionInvitation,
4748
)
48-
from ..protocols.coordinate_mediation.v1_0.manager import MediationManager
4949
from ..protocols.coordinate_mediation.mediation_invite_store import MediationInviteStore
50+
from ..protocols.coordinate_mediation.v1_0.manager import MediationManager
51+
from ..protocols.coordinate_mediation.v1_0.route_manager import RouteManager
52+
from ..protocols.coordinate_mediation.v1_0.route_manager_provider import (
53+
RouteManagerProvider,
54+
)
5055
from ..protocols.out_of_band.v1_0.manager import OutOfBandManager
5156
from ..protocols.out_of_band.v1_0.messages.invitation import HSProto, InvitationMessage
5257
from ..storage.base import BaseStorage
@@ -61,12 +66,11 @@
6166
from ..utils.stats import Collector
6267
from ..utils.task_queue import CompletedTask, TaskQueue
6368
from ..vc.ld_proofs.document_loader import DocumentLoader
64-
from ..version import __version__, RECORD_TYPE_ACAPY_VERSION
69+
from ..version import RECORD_TYPE_ACAPY_VERSION, __version__
6570
from ..wallet.did_info import DIDInfo
66-
from .oob_processor import OobMessageProcessor
67-
6871
from .dispatcher import Dispatcher
69-
from .util import STARTUP_EVENT_TOPIC, SHUTDOWN_EVENT_TOPIC
72+
from .oob_processor import OobMessageProcessor
73+
from .util import SHUTDOWN_EVENT_TOPIC, STARTUP_EVENT_TOPIC
7074

7175
LOGGER = logging.getLogger(__name__)
7276

@@ -204,6 +208,11 @@ async def setup(self):
204208
BaseMultitenantManager, MultitenantManagerProvider(self.root_profile)
205209
)
206210

211+
# Bind route manager provider
212+
context.injector.bind_provider(
213+
RouteManager, RouteManagerProvider(self.root_profile)
214+
)
215+
207216
# Bind oob message processor to be able to receive and process un-encrypted
208217
# messages
209218
context.injector.bind_instance(

aries_cloudagent/core/tests/test_dispatcher.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
V20CredProblemReport,
1919
)
2020
from ...protocols.problem_report.v1_0.message import ProblemReport
21+
from ...protocols.coordinate_mediation.v1_0.route_manager import RouteManager
2122
from ...transport.inbound.message import InboundMessage
2223
from ...transport.inbound.receipt import MessageReceipt
2324
from ...transport.outbound.message import OutboundMessage
@@ -31,6 +32,7 @@ def make_profile() -> Profile:
3132
profile.context.injector.bind_instance(ProtocolRegistry, ProtocolRegistry())
3233
profile.context.injector.bind_instance(Collector, Collector())
3334
profile.context.injector.bind_instance(EventBus, EventBus())
35+
profile.context.injector.bind_instance(RouteManager, async_mock.MagicMock())
3436
return profile
3537

3638

aries_cloudagent/multitenant/base.py

Lines changed: 12 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,26 @@
11
"""Manager for multitenancy."""
22

3+
from abc import ABC, abstractmethod
34
from datetime import datetime
45
import logging
5-
from abc import abstractmethod, ABC
6+
from typing import Iterable, List, Optional, cast
67

78
import jwt
8-
from typing import Iterable, List, Optional, cast
99

10-
from ..core.profile import (
11-
Profile,
12-
ProfileSession,
13-
)
14-
from ..messaging.responder import BaseResponder
1510
from ..config.injection_context import InjectionContext
16-
from ..wallet.models.wallet_record import WalletRecord
17-
from ..wallet.base import BaseWallet
1811
from ..core.error import BaseError
19-
from ..protocols.routing.v1_0.manager import RouteNotFoundError, RoutingManager
20-
from ..protocols.routing.v1_0.models.route_record import RouteRecord
21-
from ..transport.wire_format import BaseWireFormat
22-
from ..storage.base import BaseStorage
23-
from ..storage.error import StorageNotFoundError
12+
from ..core.profile import Profile, ProfileSession
2413
from ..protocols.coordinate_mediation.v1_0.manager import (
2514
MediationManager,
2615
MediationRecord,
2716
)
28-
17+
from ..protocols.coordinate_mediation.v1_0.route_manager import RouteManager
18+
from ..protocols.routing.v1_0.manager import RouteNotFoundError, RoutingManager
19+
from ..protocols.routing.v1_0.models.route_record import RouteRecord
20+
from ..storage.base import BaseStorage
21+
from ..transport.wire_format import BaseWireFormat
22+
from ..wallet.base import BaseWallet
23+
from ..wallet.models.wallet_record import WalletRecord
2924
from .error import WalletKeyMissingError
3025

3126
LOGGER = logging.getLogger(__name__)
@@ -204,8 +199,8 @@ async def create_wallet(
204199
public_did_info = await wallet.get_public_did()
205200

206201
if public_did_info:
207-
await self.add_key(
208-
wallet_record.wallet_id, public_did_info.verkey, skip_if_exists=True
202+
await profile.inject(RouteManager).route_public_did(
203+
profile, public_did_info.verkey
209204
)
210205
except Exception:
211206
await wallet_record.delete_record(session)
@@ -285,49 +280,6 @@ async def remove_wallet_profile(self, profile: Profile):
285280
286281
"""
287282

288-
async def add_key(
289-
self, wallet_id: str, recipient_key: str, *, skip_if_exists: bool = False
290-
):
291-
"""
292-
Add a wallet key to map incoming messages to specific subwallets.
293-
294-
Args:
295-
wallet_id: The wallet id the key corresponds to
296-
recipient_key: The recipient key belonging to the wallet
297-
skip_if_exists: Whether to skip the action if the key is already registered
298-
for relaying / mediation
299-
"""
300-
301-
LOGGER.info(
302-
f"Add route record for recipient {recipient_key} to wallet {wallet_id}"
303-
)
304-
routing_mgr = RoutingManager(self._profile)
305-
mediation_mgr = MediationManager(self._profile)
306-
mediation_record = await mediation_mgr.get_default_mediator()
307-
308-
if skip_if_exists:
309-
try:
310-
async with self._profile.session() as session:
311-
await RouteRecord.retrieve_by_recipient_key(session, recipient_key)
312-
313-
# If no error is thrown, it means there is already a record
314-
return
315-
except (StorageNotFoundError):
316-
pass
317-
318-
await routing_mgr.create_route_record(
319-
recipient_key=recipient_key, internal_wallet_id=wallet_id
320-
)
321-
322-
# External mediation
323-
if mediation_record:
324-
keylist_updates = await mediation_mgr.add_key(recipient_key)
325-
326-
responder = self._profile.inject(BaseResponder)
327-
await responder.send(
328-
keylist_updates, connection_id=mediation_record.connection_id
329-
)
330-
331283
async def create_auth_token(
332284
self, wallet_record: WalletRecord, wallet_key: str = None
333285
) -> str:
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"""Multitenancy route manager."""
2+
3+
4+
import logging
5+
from typing import List, Optional, Tuple
6+
7+
from ..core.profile import Profile
8+
from ..messaging.responder import BaseResponder
9+
from ..protocols.coordinate_mediation.v1_0.manager import MediationManager
10+
from ..protocols.coordinate_mediation.v1_0.models.mediation_record import (
11+
MediationRecord,
12+
)
13+
from ..protocols.coordinate_mediation.v1_0.route_manager import RouteManager
14+
from ..protocols.routing.v1_0.manager import RoutingManager
15+
from ..protocols.routing.v1_0.models.route_record import RouteRecord
16+
from ..storage.error import StorageNotFoundError
17+
18+
19+
LOGGER = logging.getLogger(__name__)
20+
21+
22+
class MultitenantRouteManager(RouteManager):
23+
"""Multitenancy route manager."""
24+
25+
def __init__(
26+
self,
27+
root_profile: Profile,
28+
):
29+
"""Initialize multitenant route manager."""
30+
self.root_profile = root_profile
31+
32+
async def get_base_wallet_mediator(self) -> Optional[MediationRecord]:
33+
"""Get base wallet's default mediator."""
34+
return await MediationManager(self.root_profile).get_default_mediator()
35+
36+
async def _route_for_key(
37+
self,
38+
profile: Profile,
39+
recipient_key: str,
40+
mediation_record: Optional[MediationRecord] = None,
41+
*,
42+
skip_if_exists: bool = False,
43+
replace_key: Optional[str] = None,
44+
):
45+
wallet_id = profile.settings["wallet.id"]
46+
LOGGER.info(
47+
f"Add route record for recipient {recipient_key} to wallet {wallet_id}"
48+
)
49+
routing_mgr = RoutingManager(self.root_profile)
50+
mediation_mgr = MediationManager(self.root_profile)
51+
# If base wallet had mediator, only notify that mediator.
52+
# Else, if subwallet has mediator, notify that mediator.
53+
base_mediation_record = await self.get_base_wallet_mediator()
54+
mediation_record = base_mediation_record or mediation_record
55+
56+
if skip_if_exists:
57+
try:
58+
async with self.root_profile.session() as session:
59+
await RouteRecord.retrieve_by_recipient_key(session, recipient_key)
60+
61+
# If no error is thrown, it means there is already a record
62+
return None
63+
except (StorageNotFoundError):
64+
pass
65+
66+
await routing_mgr.create_route_record(
67+
recipient_key=recipient_key, internal_wallet_id=wallet_id
68+
)
69+
70+
# External mediation
71+
keylist_updates = None
72+
if mediation_record:
73+
keylist_updates = await mediation_mgr.add_key(recipient_key)
74+
if replace_key:
75+
keylist_updates = await mediation_mgr.remove_key(
76+
replace_key, keylist_updates
77+
)
78+
79+
responder = self.root_profile.inject(BaseResponder)
80+
await responder.send(
81+
keylist_updates, connection_id=mediation_record.connection_id
82+
)
83+
84+
return keylist_updates
85+
86+
async def routing_info(
87+
self,
88+
profile: Profile,
89+
my_endpoint: str,
90+
mediation_record: Optional[MediationRecord] = None,
91+
) -> Tuple[List[str], str]:
92+
"""Return routing info."""
93+
routing_keys = []
94+
95+
base_mediation_record = await self.get_base_wallet_mediator()
96+
97+
if base_mediation_record:
98+
routing_keys = base_mediation_record.routing_keys
99+
my_endpoint = base_mediation_record.endpoint
100+
101+
if mediation_record:
102+
routing_keys = [*routing_keys, *mediation_record.routing_keys]
103+
my_endpoint = mediation_record.endpoint
104+
105+
return routing_keys, my_endpoint

0 commit comments

Comments
 (0)