Skip to content

Commit

Permalink
Author subwallet setup automation
Browse files Browse the repository at this point in the history
Signed-off-by: jamshale <jamiehalebc@gmail.com>
  • Loading branch information
jamshale committed Feb 20, 2024
1 parent 4d1f7fe commit 66194c8
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 117 deletions.
48 changes: 31 additions & 17 deletions aries_cloudagent/multitenant/admin/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,53 +18,62 @@
from ...messaging.valid import UUID4_EXAMPLE, JSONWebToken
from ...multitenant.base import BaseMultitenantManager
from ...storage.error import StorageError, StorageNotFoundError
from ...utils.endorsement_setup import attempt_auto_author_with_endorser_setup
from ...wallet.error import WalletSettingsError
from ...wallet.models.wallet_record import WalletRecord, WalletRecordSchema
from ..error import WalletKeyMissingError

ACAPY_LIFECYCLE_CONFIG_FLAG_MAP = {
"ACAPY_LOG_LEVEL": "log.level",
"ACAPY_INVITE_PUBLIC": "debug.invite_public",
"ACAPY_PUBLIC_INVITES": "public_invites",
"ACAPY_AUTO_ACCEPT_INVITES": "debug.auto_accept_invites",
"ACAPY_AUTO_ACCEPT_REQUESTS": "debug.auto_accept_requests",
"ACAPY_AUTO_PING_CONNECTION": "auto_ping_connection",
"ACAPY_MONITOR_PING": "debug.monitor_ping",
"ACAPY_AUTO_RESPOND_MESSAGES": "debug.auto_respond_messages",
"ACAPY_AUTO_PROMOTE_AUTHOR_DID": "endorser.auto_promote_author_did",
"ACAPY_AUTO_REQUEST_ENDORSEMENT": "endorser.auto_request",
"ACAPY_AUTO_RESPOND_CREDENTIAL_OFFER": "debug.auto_respond_credential_offer",
"ACAPY_AUTO_RESPOND_CREDENTIAL_REQUEST": "debug.auto_respond_credential_request",
"ACAPY_AUTO_RESPOND_MESSAGES": "debug.auto_respond_messages",
"ACAPY_AUTO_VERIFY_PRESENTATION": "debug.auto_verify_presentation",
"ACAPY_NOTIFY_REVOCATION": "revocation.notify",
"ACAPY_AUTO_REQUEST_ENDORSEMENT": "endorser.auto_request",
"ACAPY_AUTO_WRITE_TRANSACTIONS": "endorser.auto_write",
"ACAPY_CREATE_REVOCATION_TRANSACTIONS": "endorser.auto_create_rev_reg",
"ACAPY_ENDORSER_ROLE": "endorser.protocol_role",
"ACAPY_EMIT_DID_PEER_2": "emit_did_peer_2",
"ACAPY_EMIT_DID_PEER_4": "emit_did_peer_4",
"ACAPY_ENDORSER_ALIAS": "endorser.endorser_alias",
"ACAPY_ENDORSER_INVITATION": "endorser.endorser_invitation",
"ACAPY_ENDORSER_PUBLIC_DID": "endorser.endorser_public_did",
"ACAPY_ENDORSER_ROLE": "endorser.protocol_role",
"ACAPY_INVITE_PUBLIC": "debug.invite_public",
"ACAPY_LOG_LEVEL": "log.level",
"ACAPY_MONITOR_PING": "debug.monitor_ping",
"ACAPY_NOTIFY_REVOCATION": "revocation.notify",
"ACAPY_PRESERVE_EXCHANGE_RECORDS": "preserve_exchange_records",
"ACAPY_PUBLIC_INVITES": "public_invites",
"ACAPY_REQUESTS_THROUGH_PUBLIC_DID": "requests_through_public_did",
}

ACAPY_LIFECYCLE_CONFIG_FLAG_ARGS_MAP = {
"log-level": "log.level",
"invite-public": "debug.invite_public",
"public-invites": "public_invites",
"auto-accept-invites": "debug.auto_accept_invites",
"auto-accept-requests": "debug.auto_accept_requests",
"auto-create-revocation-transactions": "endorser.auto_create_rev_reg",
"auto-ping-connection": "auto_ping_connection",
"monitor-ping": "debug.monitor_ping",
"auto-respond-messages": "debug.auto_respond_messages",
"auto-promote-author-did": "endorser.auto_promote_author_did",
"auto-request-endorsement": "endorser.auto_request",
"auto-respond-credential-offer": "debug.auto_respond_credential_offer",
"auto-respond-credential-request": "debug.auto_respond_credential_request",
"auto-respond-messages": "debug.auto_respond_messages",
"auto-verify-presentation": "debug.auto_verify_presentation",
"notify-revocation": "revocation.notify",
"auto-request-endorsement": "endorser.auto_request",
"auto-write-transactions": "endorser.auto_write",
"auto-create-revocation-transactions": "endorser.auto_create_rev_reg",
"endorser-protocol-role": "endorser.protocol_role",
"emit-did-peer-2": "emit_did_peer_2",
"emit-did-peer-4": "emit_did_peer_4",
"endorser-alias": "endorser.endorser_alias",
"endorser-invitation": "endorser.endorser_invitation",
"endorser-protocol-role": "endorser.protocol_role",
"endorser-public-did": "endorser.endorser_public_did",
"invite-public": "debug.invite_public",
"log-level": "log.level",
"monitor-ping": "debug.monitor_ping",
"notify-revocation": "revocation.notify",
"preserve-exchange-records": "preserve_exchange_records",
"public-invites": "public_invites",
"requests-through-public-did": "requests_through_public_did",
}

Expand Down Expand Up @@ -459,6 +468,11 @@ async def wallet_create(request: web.BaseRequest):
)

token = await multitenant_mgr.create_auth_token(wallet_record, wallet_key)

wallet_profile = await multitenant_mgr.get_wallet_profile(
context, wallet_record, extra_settings=settings
)
await attempt_auto_author_with_endorser_setup(wallet_profile)
except BaseError as err:
raise web.HTTPBadRequest(reason=err.roll_up) from err

Expand Down
48 changes: 39 additions & 9 deletions aries_cloudagent/multitenant/admin/tests/test_routes.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from unittest import IsolatedAsyncioTestCase
from aries_cloudagent.tests import mock

import pytest
from marshmallow.exceptions import ValidationError

from ...base import BaseMultitenantManager, MultitenantManagerError
from aries_cloudagent.tests import mock

from ....admin.request_context import AdminRequestContext
from ....wallet.models.wallet_record import WalletRecord
from ....messaging.models.base import BaseModelError
from ....storage.error import StorageError, StorageNotFoundError

from ....wallet.models.wallet_record import WalletRecord
from ...base import BaseMultitenantManager, MultitenantManagerError
from .. import routes as test_module


Expand Down Expand Up @@ -139,6 +141,7 @@ async def test_wallets_list_query(self):
}
)

@pytest.mark.asyncio(scope="module")
async def test_wallet_create_tenant_settings(self):
body = {
"wallet_name": "test",
Expand All @@ -156,6 +159,8 @@ async def test_wallet_create_tenant_settings(self):
}
self.request.json = mock.CoroutineMock(return_value=body)

test_module.attempt_auto_author_with_endorser_setup = mock.CoroutineMock()

with mock.patch.object(test_module.web, "json_response") as mock_response:
wallet_mock = mock.MagicMock(
serialize=mock.MagicMock(
Expand All @@ -173,7 +178,10 @@ async def test_wallet_create_tenant_settings(self):
self.mock_multitenant_mgr.create_auth_token = mock.CoroutineMock(
return_value="test_token"
)
print(self.request["context"])
self.mock_multitenant_mgr.get_wallet_profile = mock.CoroutineMock(
return_value=mock.MagicMock()
)

await test_module.wallet_create(self.request)

self.mock_multitenant_mgr.create_wallet.assert_called_once_with(
Expand All @@ -195,6 +203,8 @@ async def test_wallet_create_tenant_settings(self):
mock_response.assert_called_once_with(
{**test_module.format_wallet_record(wallet_mock), "token": "test_token"}
)
assert self.mock_multitenant_mgr.get_wallet_profile.called
assert test_module.attempt_auto_author_with_endorser_setup.called

async def test_wallet_create(self):
body = {
Expand All @@ -207,6 +217,7 @@ async def test_wallet_create(self):
"wallet_dispatch_type": "base",
}
self.request.json = mock.CoroutineMock(return_value=body)
test_module.attempt_auto_author_with_endorser_setup = mock.CoroutineMock()

with mock.patch.object(test_module.web, "json_response") as mock_response:
wallet_mock = mock.MagicMock(
Expand All @@ -225,7 +236,10 @@ async def test_wallet_create(self):
self.mock_multitenant_mgr.create_auth_token = mock.CoroutineMock(
return_value="test_token"
)
print(self.request["context"])
self.mock_multitenant_mgr.get_wallet_profile = mock.CoroutineMock(
return_value=mock.MagicMock()
)

await test_module.wallet_create(self.request)

self.mock_multitenant_mgr.create_wallet.assert_called_once_with(
Expand All @@ -242,8 +256,13 @@ async def test_wallet_create(self):
wallet_mock, body["wallet_key"]
)
mock_response.assert_called_once_with(
{**test_module.format_wallet_record(wallet_mock), "token": "test_token"}
{
**test_module.format_wallet_record(wallet_mock),
"token": "test_token",
}
)
assert self.mock_multitenant_mgr.get_wallet_profile.called
assert test_module.attempt_auto_author_with_endorser_setup.called

async def test_wallet_create_x(self):
body = {}
Expand Down Expand Up @@ -277,6 +296,9 @@ async def test_wallet_create_optional_default_fields(self):
return_value=mock.MagicMock()
)
self.mock_multitenant_mgr.create_auth_token = mock.CoroutineMock()
self.mock_multitenant_mgr.get_wallet_profile = mock.CoroutineMock(
return_value=mock.MagicMock()
)

await test_module.wallet_create(self.request)
self.mock_multitenant_mgr.create_wallet.assert_called_once_with(
Expand All @@ -292,6 +314,7 @@ async def test_wallet_create_optional_default_fields(self):
},
WalletRecord.MODE_MANAGED,
)
assert self.mock_multitenant_mgr.get_wallet_profile.called

async def test_wallet_create_raw_key_derivation(self):
body = {
Expand All @@ -306,6 +329,9 @@ async def test_wallet_create_raw_key_derivation(self):
return_value=mock.MagicMock()
)
self.mock_multitenant_mgr.create_auth_token = mock.CoroutineMock()
self.mock_multitenant_mgr.get_wallet_profile = mock.CoroutineMock(
return_value=mock.MagicMock()
)

await test_module.wallet_create(self.request)
self.mock_multitenant_mgr.create_wallet.assert_called_once_with(
Expand All @@ -319,6 +345,7 @@ async def test_wallet_create_raw_key_derivation(self):
},
WalletRecord.MODE_MANAGED,
)
assert self.mock_multitenant_mgr.get_wallet_profile.called

async def test_wallet_update_tenant_settings(self):
self.request.match_info = {"wallet_id": "test-wallet-id"}
Expand Down Expand Up @@ -651,6 +678,7 @@ async def test_wallet_create_token_x(self):
)
await test_module.wallet_create_token(self.request)

@pytest.mark.asyncio(scope="module")
async def test_wallet_remove_managed(self):
self.request.has_body = False
self.request.match_info = {"wallet_id": "dummy"}
Expand All @@ -662,12 +690,13 @@ async def test_wallet_remove_managed(self):
):
self.mock_multitenant_mgr.remove_wallet = mock.CoroutineMock()

await test_module.wallet_remove(self.request)
result = await test_module.wallet_remove(self.request)

self.mock_multitenant_mgr.remove_wallet.assert_called_once_with(
"dummy", None
)
mock_response.assert_called_once_with({})
assert result == mock_response.return_value

async def test_wallet_remove_unmanaged(self):
self.request.match_info = {"wallet_id": "dummy"}
Expand All @@ -680,12 +709,13 @@ async def test_wallet_remove_unmanaged(self):
):
self.mock_multitenant_mgr.remove_wallet = mock.CoroutineMock()

await test_module.wallet_remove(self.request)
result = await test_module.wallet_remove(self.request)

self.mock_multitenant_mgr.remove_wallet.assert_called_once_with(
"dummy", "dummy_key"
)
mock_response.assert_called_once_with({})
assert result == mock_response.return_value

async def test_wallet_remove_managed_wallet_key_provided_throws(self):
self.request.match_info = {"wallet_id": "dummy"}
Expand Down
4 changes: 3 additions & 1 deletion aries_cloudagent/protocols/didexchange/v1_0/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from did_peer_4 import LONG_PATTERN, long_to_short

from ....admin.server import AdminResponder
from ....connections.base_manager import BaseConnectionManager
from ....connections.models.conn_record import ConnRecord
from ....connections.models.connection_target import ConnectionTarget
Expand Down Expand Up @@ -150,7 +151,8 @@ async def receive_invitation(

if conn_rec.accept == ConnRecord.ACCEPT_AUTO:
request = await self.create_request(conn_rec, mediation_id=mediation_id)
responder = self.profile.inject_or(BaseResponder)
base_responder = self.profile.inject(BaseResponder)
responder = AdminResponder(self.profile, base_responder.send_fn)
if responder:
await responder.send_reply(
request,
Expand Down
13 changes: 10 additions & 3 deletions aries_cloudagent/protocols/didexchange/v1_0/tests/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from aries_cloudagent.tests import mock

from .....admin.server import AdminResponder
from .....cache.base import BaseCache
from .....cache.in_memory import InMemoryCache
from .....connections.models.conn_record import ConnRecord
Expand Down Expand Up @@ -72,7 +73,7 @@ def make_did_doc(self, did, verkey):
class TestDidExchangeManager(IsolatedAsyncioTestCase, TestConfig):
async def asyncSetUp(self):
self.responder = MockResponder()

self.responder.send_fn = mock.CoroutineMock()
self.oob_mock = mock.MagicMock(
clean_finished_oob_record=mock.CoroutineMock(return_value=None)
)
Expand Down Expand Up @@ -181,7 +182,9 @@ async def test_receive_invitation(self):
test_module, "AttachDecorator", autospec=True
) as mock_attach_deco, mock.patch.object(
self.multitenant_mgr, "get_default_mediator"
) as mock_get_default_mediator:
) as mock_get_default_mediator, mock.patch.object(
AdminResponder, "send_reply"
) as mock_send_reply:
mock_get_default_mediator.return_value = mediation_record
invi_rec = await self.oob_manager.create_invitation(
my_endpoint="testendpoint",
Expand All @@ -195,6 +198,7 @@ async def test_receive_invitation(self):
)
invitee_record = await self.manager.receive_invitation(invi_msg)
assert invitee_record.state == ConnRecord.State.REQUEST.rfc23
assert mock_send_reply.called

async def test_receive_invitation_oob_public_did(self):
async with self.profile.session() as session:
Expand All @@ -211,7 +215,9 @@ async def test_receive_invitation_oob_public_did(self):
self.multitenant_mgr, "get_default_mediator"
) as mock_get_default_mediator, mock.patch.object(
self.manager, "resolve_connection_targets", mock.CoroutineMock()
) as mock_resolve_targets:
) as mock_resolve_targets, mock.patch.object(
AdminResponder, "send_reply"
) as mock_send_reply:
mock_resolve_targets.return_value = [
mock.MagicMock(recipient_keys=["test"])
]
Expand All @@ -231,6 +237,7 @@ async def test_receive_invitation_oob_public_did(self):
invi_msg, their_public_did=public_did_info.did
)
assert invitee_record.state == ConnRecord.State.REQUEST.rfc23
assert mock_send_reply.called

async def test_receive_invitation_no_auto_accept(self):
async with self.profile.session() as session:
Expand Down
Loading

0 comments on commit 66194c8

Please sign in to comment.