Skip to content

Commit 2332e32

Browse files
authored
Merge branch 'main' into fix/conn-id-in-keylist-webhook
2 parents 43d08f3 + a16347d commit 2332e32

58 files changed

Lines changed: 1774 additions & 200 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Endorser.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Endorsement:
5656
For Authors, specify whether to automatically create transactions for a cred def's revocation registry. (If not specified, the controller must invoke the endpoints required to create
5757
the revocation registry and assign to the cred def.) [env var: ACAPY_CREATE_REVOCATION_TRANSACTIONS]
5858
--auto-promote-author-did
59-
For Authors, specify whether to automatically promote a DID to the wallet public DID after writing to the ledger.
59+
For Authors, specify whether to automatically promote a DID to the wallet public DID after writing to the ledger. [env var: ACAPY_AUTO_PROMOTE_AUTHOR_DID]
6060
```
6161

6262
## How Aca-py Handles Endorsements

aries_cloudagent/config/argparse.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1837,7 +1837,7 @@ def add_arguments(self, parser: ArgumentParser):
18371837
parser.add_argument(
18381838
"--auto-promote-author-did",
18391839
action="store_true",
1840-
env_var="ACAPY_PROMOTE-AUTHOR-DID",
1840+
env_var="ACAPY_AUTO_PROMOTE_AUTHOR_DID",
18411841
help="For Authors, specify whether to automatically promote"
18421842
" a DID to the wallet public DID after writing to the ledger.",
18431843
)

aries_cloudagent/connections/base_manager.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"""
66

77
import logging
8-
from typing import List, Sequence, Tuple
8+
from typing import Optional, List, Sequence, Tuple, Text
99

1010
from pydid import (
1111
BaseDIDDocument as ResolvedDocument,
@@ -227,7 +227,9 @@ async def remove_keys_for_did(self, did: str):
227227
storage: BaseStorage = session.inject(BaseStorage)
228228
await storage.delete_all_records(self.RECORD_TYPE_DID_KEY, {"did": did})
229229

230-
async def resolve_invitation(self, did: str):
230+
async def resolve_invitation(
231+
self, did: str, service_accept: Optional[Sequence[Text]] = None
232+
):
231233
"""
232234
Resolve invitation with the DID Resolver.
233235
@@ -241,7 +243,7 @@ async def resolve_invitation(self, did: str):
241243

242244
resolver = self._profile.inject(DIDResolver)
243245
try:
244-
doc_dict: dict = await resolver.resolve(self._profile, did)
246+
doc_dict: dict = await resolver.resolve(self._profile, did, service_accept)
245247
doc: ResolvedDocument = pydid.deserialize_document(doc_dict, strict=True)
246248
except ResolverError as error:
247249
raise BaseConnectionManagerError(

aries_cloudagent/core/conductor.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -450,8 +450,7 @@ async def start(self) -> None:
450450
if mediation_connections_invite
451451
else OutOfBandManager(self.root_profile)
452452
)
453-
454-
conn_record = await mgr.receive_invitation(
453+
record = await mgr.receive_invitation(
455454
invitation=invitation_handler.from_url(
456455
mediation_invite_record.invite
457456
),
@@ -464,10 +463,10 @@ async def start(self) -> None:
464463
).mark_default_invite_as_used()
465464
)
466465

467-
await conn_record.metadata_set(
466+
await record.metadata_set(
468467
session, MediationManager.SEND_REQ_AFTER_CONNECTION, True
469468
)
470-
await conn_record.metadata_set(
469+
await record.metadata_set(
471470
session, MediationManager.SET_TO_DEFAULT_ON_GRANTED, True
472471
)
473472

@@ -482,7 +481,8 @@ async def start(self) -> None:
482481
async def stop(self, timeout=1.0):
483482
"""Stop the agent."""
484483
# notify protcols that we are shutting down
485-
await self.root_profile.notify(SHUTDOWN_EVENT_TOPIC, {})
484+
if self.root_profile:
485+
await self.root_profile.notify(SHUTDOWN_EVENT_TOPIC, {})
486486

487487
shutdown = TaskQueue()
488488
if self.dispatcher:
@@ -494,13 +494,13 @@ async def stop(self, timeout=1.0):
494494
if self.outbound_transport_manager:
495495
shutdown.run(self.outbound_transport_manager.stop())
496496

497-
# close multitenant profiles
498-
multitenant_mgr = self.context.inject_or(BaseMultitenantManager)
499-
if multitenant_mgr:
500-
for profile in multitenant_mgr.open_profiles:
501-
shutdown.run(profile.close())
502-
503497
if self.root_profile:
498+
# close multitenant profiles
499+
multitenant_mgr = self.context.inject_or(BaseMultitenantManager)
500+
if multitenant_mgr:
501+
for profile in multitenant_mgr.open_profiles:
502+
shutdown.run(profile.close())
503+
504504
shutdown.run(self.root_profile.close())
505505

506506
await shutdown.complete(timeout)

aries_cloudagent/core/dispatcher.py

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import os
1111
import warnings
1212

13-
from typing import Callable, Coroutine, Union
13+
from typing import Callable, Coroutine, Optional, Union, Tuple
1414
import weakref
1515

1616
from aiohttp.web import HTTPException
@@ -36,6 +36,13 @@
3636

3737
from .error import ProtocolMinorVersionNotSupported
3838
from .protocol_registry import ProtocolRegistry
39+
from .util import (
40+
get_version_from_message_type,
41+
validate_get_response_version,
42+
# WARNING_DEGRADED_FEATURES,
43+
# WARNING_VERSION_MISMATCH,
44+
# WARNING_VERSION_NOT_SUPPORTED,
45+
)
3946

4047
LOGGER = logging.getLogger(__name__)
4148

@@ -133,16 +140,22 @@ async def handle_message(
133140
inbound_message: The inbound message instance
134141
send_outbound: Async function to send outbound messages
135142
143+
# Raises:
144+
# MessageParseError: If the message type version is not supported
145+
136146
Returns:
137147
The response from the handler
138148
139149
"""
140150
r_time = get_timer()
141151

142152
error_result = None
153+
version_warning = None
143154
message = None
144155
try:
145-
message = await self.make_message(inbound_message.payload)
156+
(message, warning) = await self.make_message(
157+
profile, inbound_message.payload
158+
)
146159
except ProblemReportParseError:
147160
pass # avoid problem report recursion
148161
except MessageParseError as e:
@@ -155,6 +168,47 @@ async def handle_message(
155168
)
156169
if inbound_message.receipt.thread_id:
157170
error_result.assign_thread_id(inbound_message.receipt.thread_id)
171+
# if warning:
172+
# warning_message_type = inbound_message.payload.get("@type")
173+
# if warning == WARNING_DEGRADED_FEATURES:
174+
# LOGGER.error(
175+
# f"Sending {WARNING_DEGRADED_FEATURES} problem report, "
176+
# "message type received with a minor version at or higher"
177+
# " than protocol minimum supported and current minor version "
178+
# f"for message_type {warning_message_type}"
179+
# )
180+
# version_warning = ProblemReport(
181+
# description={
182+
# "en": (
183+
# "message type received with a minor version at or "
184+
# "higher than protocol minimum supported and current"
185+
# f" minor version for message_type {warning_message_type}"
186+
# ),
187+
# "code": WARNING_DEGRADED_FEATURES,
188+
# }
189+
# )
190+
# elif warning == WARNING_VERSION_MISMATCH:
191+
# LOGGER.error(
192+
# f"Sending {WARNING_VERSION_MISMATCH} problem report, message "
193+
# "type received with a minor version higher than current minor "
194+
# f"version for message_type {warning_message_type}"
195+
# )
196+
# version_warning = ProblemReport(
197+
# description={
198+
# "en": (
199+
# "message type received with a minor version higher"
200+
# " than current minor version for message_type"
201+
# f" {warning_message_type}"
202+
# ),
203+
# "code": WARNING_VERSION_MISMATCH,
204+
# }
205+
# )
206+
# elif warning == WARNING_VERSION_NOT_SUPPORTED:
207+
# raise MessageParseError(
208+
# f"Message type version not supported for {warning_message_type}"
209+
# )
210+
# if version_warning and inbound_message.receipt.thread_id:
211+
# version_warning.assign_thread_id(inbound_message.receipt.thread_id)
158212

159213
trace_event(
160214
self.profile.settings,
@@ -199,6 +253,8 @@ async def handle_message(
199253

200254
if error_result:
201255
await responder.send_reply(error_result)
256+
elif version_warning:
257+
await responder.send_reply(version_warning)
202258
elif context.message:
203259
context.injector.bind_instance(BaseResponder, responder)
204260

@@ -215,7 +271,9 @@ async def handle_message(
215271
perf_counter=r_time,
216272
)
217273

218-
async def make_message(self, parsed_msg: dict) -> BaseMessage:
274+
async def make_message(
275+
self, profile: Profile, parsed_msg: dict
276+
) -> Tuple[BaseMessage, Optional[str]]:
219277
"""
220278
Deserialize a message dict into the appropriate message instance.
221279
@@ -224,6 +282,7 @@ async def make_message(self, parsed_msg: dict) -> BaseMessage:
224282
225283
Args:
226284
parsed_msg: The parsed message
285+
profile: Profile
227286
228287
Returns:
229288
An instance of the corresponding message class for this message
@@ -240,6 +299,7 @@ async def make_message(self, parsed_msg: dict) -> BaseMessage:
240299

241300
if not message_type:
242301
raise MessageParseError("Message does not contain '@type' parameter")
302+
message_type_rec_version = get_version_from_message_type(message_type)
243303

244304
registry: ProtocolRegistry = self.profile.inject(ProtocolRegistry)
245305
try:
@@ -256,8 +316,10 @@ async def make_message(self, parsed_msg: dict) -> BaseMessage:
256316
if "/problem-report" in message_type:
257317
raise ProblemReportParseError("Error parsing problem report message")
258318
raise MessageParseError(f"Error deserializing message: {e}") from e
259-
260-
return instance
319+
_, warning = await validate_get_response_version(
320+
profile, message_type_rec_version, message_cls
321+
)
322+
return (instance, warning)
261323

262324
async def complete(self, timeout: float = 0.1):
263325
"""Wait for pending tasks to complete."""

aries_cloudagent/core/protocol_registry.py

Lines changed: 91 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
"""Handle registration and publication of supported protocols."""
22

33
import logging
4+
import re
45

56
from typing import Mapping, Sequence
67

78
from ..config.injection_context import InjectionContext
89
from ..utils.classloader import ClassLoader
910

10-
from .error import ProtocolMinorVersionNotSupported
11+
from .error import ProtocolMinorVersionNotSupported, ProtocolDefinitionValidationError
1112

1213
LOGGER = logging.getLogger(__name__)
1314

@@ -74,6 +75,79 @@ def parse_type_string(self, message_type):
7475
"minor_version": int(version_string_tokens[1]),
7576
}
7677

78+
def create_msg_types_for_minor_version(self, typesets, version_definition):
79+
"""
80+
Return mapping of message type to module path for minor versions.
81+
82+
Args:
83+
typesets: Mappings of message types to register
84+
version_definition: Optional version definition dict
85+
86+
Returns:
87+
Typesets mapping
88+
89+
"""
90+
updated_typeset = {}
91+
curr_minor_version = version_definition["current_minor_version"]
92+
min_minor_version = version_definition["minimum_minor_version"]
93+
major_version = version_definition["major_version"]
94+
if curr_minor_version >= min_minor_version:
95+
for version_index in range(min_minor_version, curr_minor_version + 1):
96+
to_check = f"{str(major_version)}.{str(version_index)}"
97+
updated_typeset.update(
98+
self._get_updated_typeset_dict(typesets, to_check, updated_typeset)
99+
)
100+
else:
101+
raise ProtocolDefinitionValidationError(
102+
"min_minor_version is greater than curr_minor_version for the"
103+
f" following typeset: {str(typesets)}"
104+
)
105+
return (updated_typeset,)
106+
107+
def _get_updated_typeset_dict(self, typesets, to_check, updated_typeset) -> dict:
108+
for typeset in typesets:
109+
for msg_type_string, module_path in typeset.items():
110+
updated_msg_type_string = re.sub(
111+
r"(\d+\.)?(\*|\d+)", to_check, msg_type_string
112+
)
113+
updated_typeset[updated_msg_type_string] = module_path
114+
return updated_typeset
115+
116+
def _message_type_check_for_minor_verssion(self, version_definition) -> bool:
117+
if not version_definition:
118+
return False
119+
curr_minor_version = version_definition["current_minor_version"]
120+
min_minor_version = version_definition["minimum_minor_version"]
121+
return bool(curr_minor_version >= 1 and curr_minor_version >= min_minor_version)
122+
123+
def _create_and_register_updated_typesets(self, typesets, version_definition):
124+
updated_typesets = self.create_msg_types_for_minor_version(
125+
typesets, version_definition
126+
)
127+
update_flag = False
128+
for typeset in updated_typesets:
129+
if typeset:
130+
self._typemap.update(typeset)
131+
update_flag = True
132+
if update_flag:
133+
return updated_typesets
134+
else:
135+
return None
136+
137+
def _update_version_map(self, message_type_string, module_path, version_definition):
138+
parsed_type_string = self.parse_type_string(message_type_string)
139+
140+
if version_definition["major_version"] not in self._versionmap:
141+
self._versionmap[version_definition["major_version"]] = []
142+
143+
self._versionmap[version_definition["major_version"]].append(
144+
{
145+
"parsed_type_string": parsed_type_string,
146+
"version_definition": version_definition,
147+
"message_module": module_path,
148+
}
149+
)
150+
77151
def register_message_types(self, *typesets, version_definition=None):
78152
"""
79153
Add new supported message types.
@@ -85,24 +159,27 @@ def register_message_types(self, *typesets, version_definition=None):
85159
"""
86160

87161
# Maintain support for versionless protocol modules
88-
for typeset in typesets:
89-
self._typemap.update(typeset)
162+
updated_typesets = None
163+
minor_versions_supported = self._message_type_check_for_minor_verssion(
164+
version_definition
165+
)
166+
if not minor_versions_supported:
167+
for typeset in typesets:
168+
self._typemap.update(typeset)
90169

91170
# Track versioned modules for version routing
92171
if version_definition:
172+
# create updated typesets for minor versions and register them
173+
if minor_versions_supported:
174+
updated_typesets = self._create_and_register_updated_typesets(
175+
typesets, version_definition
176+
)
177+
if updated_typesets:
178+
typesets = updated_typesets
93179
for typeset in typesets:
94180
for message_type_string, module_path in typeset.items():
95-
parsed_type_string = self.parse_type_string(message_type_string)
96-
97-
if version_definition["major_version"] not in self._versionmap:
98-
self._versionmap[version_definition["major_version"]] = []
99-
100-
self._versionmap[version_definition["major_version"]].append(
101-
{
102-
"parsed_type_string": parsed_type_string,
103-
"version_definition": version_definition,
104-
"message_module": module_path,
105-
}
181+
self._update_version_map(
182+
message_type_string, module_path, version_definition
106183
)
107184

108185
def register_controllers(self, *controller_sets, version_definition=None):

0 commit comments

Comments
 (0)