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

DID Exchange - Create and send requests against implicit invitations #1174

Merged
merged 4 commits into from
May 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 41 additions & 30 deletions aries_cloudagent/connections/base_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,45 +289,56 @@ async def fetch_connection_targets(
in (ConnRecord.State.INVITATION, ConnRecord.State.REQUEST)
and ConnRecord.Role.get(connection.their_role) is ConnRecord.Role.RESPONDER
):
invitation = await connection.retrieve_invitation(self._session)
if isinstance(invitation, ConnectionInvitation): # conn protocol invitation
if invitation.did:
did = invitation.did
if connection.invitation_msg_id or connection.invitation_key:
invitation = await connection.retrieve_invitation(self._session)
if isinstance(
invitation, ConnectionInvitation
): # conn protocol invitation
if invitation.did:
did = invitation.did
(
endpoint,
recipient_keys,
routing_keys,
) = await self.resolve_invitation(did)

else:
endpoint = invitation.endpoint
recipient_keys = invitation.recipient_keys
routing_keys = invitation.routing_keys
else: # out-of-band invitation
if invitation.service_dids:
did = invitation.service_dids[0]
(
endpoint,
recipient_keys,
routing_keys,
) = await self.resolve_invitation(did)

else:
endpoint = invitation.service_blocks[0].service_endpoint
recipient_keys = [
DIDKey.from_did(k).public_key_b58
for k in invitation.service_blocks[0].recipient_keys
]
routing_keys = [
DIDKey.from_did(k).public_key_b58
for k in invitation.service_blocks[0].routing_keys
]
else:
if connection.their_did:
invitation = None
did = connection.their_did
(
endpoint,
recipient_keys,
routing_keys,
) = await self.resolve_invitation(did)

else:
endpoint = invitation.endpoint
recipient_keys = invitation.recipient_keys
routing_keys = invitation.routing_keys
else: # out-of-band invitation
if invitation.service_dids:
did = invitation.service_dids[0]
(
endpoint,
recipient_keys,
routing_keys,
) = await self.resolve_invitation(did)

else:
endpoint = invitation.service_blocks[0].service_endpoint
recipient_keys = [
DIDKey.from_did(k).public_key_b58
for k in invitation.service_blocks[0].recipient_keys
]
routing_keys = [
DIDKey.from_did(k).public_key_b58
for k in invitation.service_blocks[0].routing_keys
]

results = [
ConnectionTarget(
did=connection.their_did,
endpoint=endpoint,
label=invitation.label,
label=invitation.label if invitation else None,
recipient_keys=recipient_keys,
routing_keys=routing_keys,
sender_key=my_info.verkey,
Expand Down
39 changes: 39 additions & 0 deletions aries_cloudagent/protocols/connections/v1_0/tests/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2595,6 +2595,45 @@ async def test_fetch_connection_targets_conn_completed_their_did(self):
assert target.routing_keys == []
assert target.sender_key == local_did.verkey

async def test_fetch_connection_targets_conn_no_invi_with_their_did(self):
local_did = await self.session.wallet.create_local_did(
method=DIDMethod.SOV,
key_type=KeyType.ED25519,
seed=self.test_seed,
did=self.test_did,
metadata=None,
)

self.manager.resolve_invitation = async_mock.CoroutineMock()
self.manager.resolve_invitation.return_value = (
self.test_endpoint,
[self.test_verkey],
[],
)

did_doc = self.make_did_doc(did=self.test_did, verkey=self.test_verkey)
await self.manager.store_did_document(did_doc)

mock_conn = async_mock.MagicMock(
my_did=self.test_did,
their_did=self.test_did,
their_label="label",
their_role=ConnRecord.Role.RESPONDER.rfc23,
state=ConnRecord.State.REQUEST.rfc23,
invitation_key=None,
invitation_msg_id=None,
)

targets = await self.manager.fetch_connection_targets(mock_conn)
assert len(targets) == 1
target = targets[0]
assert target.did == mock_conn.their_did
assert target.endpoint == self.test_endpoint
assert target.label is None
assert target.recipient_keys == [self.test_verkey]
assert target.routing_keys == []
assert target.sender_key == local_did.verkey

async def test_diddoc_connection_targets_diddoc_underspecified(self):
with self.assertRaises(BaseConnectionManagerError):
self.manager.diddoc_connection_targets(None, self.test_verkey)
Expand Down
13 changes: 11 additions & 2 deletions aries_cloudagent/protocols/didexchange/v1_0/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ async def create_request_implicit(
my_label: str = None,
my_endpoint: str = None,
mediation_id: str = None,
send_request: bool = False,
) -> DIDXRequest:
"""
Create a request against a public DID only (no explicit invitation).
Expand All @@ -184,17 +185,25 @@ async def create_request_implicit(
their_role=ConnRecord.Role.RESPONDER.rfc23,
invitation_key=None,
invitation_msg_id=None,
state=ConnRecord.State.REQUEST.rfc23,
accept=None,
alias=my_label,
their_public_did=their_public_did,
)
return await self.create_request( # saves and updates conn_rec
request = await self.create_request( # saves and updates conn_rec
conn_rec=conn_rec,
my_label=my_label,
my_endpoint=my_endpoint,
mediation_id=mediation_id,
)
conn_rec.request_id = request._id
conn_rec.state = ConnRecord.State.REQUEST.rfc23
await conn_rec.save(self._session, reason="Created connection request")
if send_request:
responder = self._session.inject(BaseResponder, required=False)
if responder:
await responder.send(request, connection_id=conn_rec.connection_id)

return request

async def create_request(
self,
Expand Down
5 changes: 5 additions & 0 deletions aries_cloudagent/protocols/didexchange/v1_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ class DIDXCreateRequestImplicitQueryStringSchema(OpenAPISchema):
description="Identifier for active mediation record to be used",
**UUID4,
)
send_request = fields.Bool(
description="Whether to send request for implicit invitations", default=False
)


class DIDXReceiveRequestImplicitQueryStringSchema(OpenAPISchema):
Expand Down Expand Up @@ -179,6 +182,7 @@ async def didx_create_request_implicit(request: web.BaseRequest):
my_label = request.query.get("my_label") or None
my_endpoint = request.query.get("my_endpoint") or None
mediation_id = request.query.get("mediation_id") or None
send_request = request.query.get("send_request")

didx_mgr = DIDXManager(session)
try:
Expand All @@ -187,6 +191,7 @@ async def didx_create_request_implicit(request: web.BaseRequest):
my_label=my_label,
my_endpoint=my_endpoint,
mediation_id=mediation_id,
send_request=send_request,
)
except StorageNotFoundError as err:
raise web.HTTPNotFound(reason=err.roll_up) from err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from .....multitenant.manager import MultitenantManager
from .....storage.error import StorageNotFoundError
from .....transport.inbound.receipt import MessageReceipt
from .....multitenant.manager import MultitenantManager
from .....wallet.did_info import DIDInfo
from .....wallet.in_memory import InMemoryWallet
from .....wallet.did_method import DIDMethod
Expand Down Expand Up @@ -236,6 +235,35 @@ async def test_create_request_implicit(self):

assert didx_req._id

async def test_create_send_request_implicit(self):
mediation_record = MediationRecord(
role=MediationRecord.ROLE_CLIENT,
state=MediationRecord.STATE_GRANTED,
connection_id=self.test_mediator_conn_id,
routing_keys=self.test_mediator_routing_keys,
endpoint=self.test_mediator_endpoint,
)
await mediation_record.save(self.session)

with async_mock.patch.object(
self.manager, "create_did_document", async_mock.CoroutineMock()
) as mock_create_did_doc, async_mock.patch.object(
self.multitenant_mgr, "get_default_mediator"
) as mock_get_default_mediator:
mock_get_default_mediator.return_value = mediation_record
mock_create_did_doc.return_value = async_mock.MagicMock(
serialize=async_mock.MagicMock(return_value={})
)
didx_req = await self.manager.create_request_implicit(
their_public_did=TestConfig.test_target_did,
my_label=None,
my_endpoint=None,
mediation_id=mediation_record._id,
send_request=True,
)

assert didx_req._id

async def test_create_request(self):
mock_conn_rec = async_mock.MagicMock(
connection_id="dummy",
Expand Down