Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix empty ServiceDecorator in OobRecord causing 422 Unprocessable Entity Error #2362

Merged
26 changes: 21 additions & 5 deletions aries_cloudagent/protocols/out_of_band/v1_0/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,29 +582,39 @@ async def _process_request_attach(self, oob_record: OobRecord):
if not oob_record.connection_id:
service = oob_record.invitation.services[0]
their_service = await self._service_decorator_from_service(service)
LOGGER.debug("Found service for oob record %s", their_service)
if their_service:
LOGGER.debug("Found service for oob record %s", their_service)
else:
LOGGER.debug("No service decorator obtained from %s", service)

await message_processor.handle_message(
self.profile, messages, oob_record=oob_record, their_service=their_service
)

async def _service_decorator_from_service(
self, service: Union[Service, str]
) -> ServiceDecorator:
) -> Optional[ServiceDecorator]:
if isinstance(service, str):
(
endpoint,
recipient_keys,
routing_keys,
) = await self.resolve_invitation(service)

if not endpoint:
return None

return ServiceDecorator(
endpoint=endpoint,
recipient_keys=recipient_keys,
routing_keys=routing_keys,
)
else:
# Create ~service decorator from the oob service
elif isinstance(service, Service):
endpoint = service.service_endpoint

if not endpoint:
return None

recipient_keys = [
DIDKey.from_did(did_key).public_key_b58
for did_key in service.recipient_keys
Expand All @@ -615,10 +625,16 @@ async def _service_decorator_from_service(
]

return ServiceDecorator(
endpoint=service.service_endpoint,
endpoint=endpoint,
recipient_keys=recipient_keys,
routing_keys=routing_keys,
)
else:
LOGGER.warning(
"Unexpected type `%s` passed to `_service_decorator_from_service`",
type(service),
)
return None

async def _wait_for_reuse_response(
self, oob_id: str, timeout: int = 15
Expand Down
65 changes: 65 additions & 0 deletions aries_cloudagent/protocols/out_of_band/v1_0/tests/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1717,6 +1717,71 @@ async def test_service_decorator_from_service_object(self):
assert service.recipient_keys == [TestConfig.test_verkey]
assert service.routing_keys == self.test_mediator_routing_keys

async def test_service_decorator_from_service_str_empty_endpoint(self):
did = "did:sov:something"

self.manager.resolve_invitation = async_mock.CoroutineMock()
self.manager.resolve_invitation.return_value = (
"", # empty endpoint
[TestConfig.test_verkey],
self.test_mediator_routing_keys,
)

service = await self.manager._service_decorator_from_service(did)

assert service is None

async def test_service_decorator_from_service_str_none_endpoint(self):
did = "did:sov:something"

self.manager.resolve_invitation = async_mock.CoroutineMock()
self.manager.resolve_invitation.return_value = (
None, # None endpoint
[TestConfig.test_verkey],
self.test_mediator_routing_keys,
)

service = await self.manager._service_decorator_from_service(did)

assert service is None

async def test_service_decorator_from_service_object_empty_endpoint(self):
oob_service = OobService(
service_endpoint="", # empty endpoint
recipient_keys=[
DIDKey.from_public_key_b58(TestConfig.test_verkey, ED25519).did
],
routing_keys=[
DIDKey.from_public_key_b58(verkey, ED25519).did
for verkey in self.test_mediator_routing_keys
],
)
service = await self.manager._service_decorator_from_service(oob_service)

assert service is None

async def test_service_decorator_from_service_object_none_endpoint(self):
oob_service = OobService(
service_endpoint=None, # None endpoint
recipient_keys=[
DIDKey.from_public_key_b58(TestConfig.test_verkey, ED25519).did
],
routing_keys=[
DIDKey.from_public_key_b58(verkey, ED25519).did
for verkey in self.test_mediator_routing_keys
],
)
service = await self.manager._service_decorator_from_service(oob_service)

assert service is None

async def test_service_decorator_from_service_invalid_type(self):
invalid_type = 123 # integer, for example

service = await self.manager._service_decorator_from_service(invalid_type)

assert service is None

async def test_delete_stale_connection_by_invitation(self):
current_datetime = datetime_now()
older_datetime = current_datetime - timedelta(hours=4)
Expand Down