Skip to content

Commit

Permalink
Merge branch 'main' into feature/event-bus
Browse files Browse the repository at this point in the history
  • Loading branch information
dbluhm authored Apr 27, 2021
2 parents 39f2c9a + 8a60d1a commit 708f9d3
Show file tree
Hide file tree
Showing 21 changed files with 1,298 additions and 347 deletions.
68 changes: 51 additions & 17 deletions aries_cloudagent/messaging/credential_definitions/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@
from .util import CredDefQueryStringSchema, CRED_DEF_TAGS, CRED_DEF_SENT_RECORD_TYPE


from ..valid import UUIDFour
from ...connections.models.conn_record import ConnRecord
from ...storage.error import StorageNotFoundError
from ..models.base import BaseModelError


class CredentialDefinitionSendRequestSchema(OpenAPISchema):
"""Request schema for schema send request."""

Expand Down Expand Up @@ -132,21 +138,20 @@ class CredDefIdMatchInfoSchema(OpenAPISchema):
)


class AutoEndorseOptionSchema(OpenAPISchema):
"""Class for user to input whether to auto-endorse the transaction or not."""
class CreateTransactionForEndorserOptionSchema(OpenAPISchema):
"""Class for user to input whether to create a transaction for endorser or not."""

auto_endorse = fields.Boolean(
description="Auto-endorse Transaction",
create_transaction_for_endorser = fields.Boolean(
description="Create Transaction For Endorser's signature",
required=False,
)


class EndorserDIDOptionSchema(OpenAPISchema):
"""Class for user to input the DID associated with the requested endorser."""
class ConnIdMatchInfoSchema(OpenAPISchema):
"""Path parameters and validators for request taking connection id."""

endorser_did = fields.Str(
description="Endorser DID",
required=False,
conn_id = fields.Str(
description="Connection identifier", required=False, example=UUIDFour.EXAMPLE
)


Expand All @@ -155,8 +160,8 @@ class EndorserDIDOptionSchema(OpenAPISchema):
summary="Sends a credential definition to the ledger",
)
@request_schema(CredentialDefinitionSendRequestSchema())
@querystring_schema(AutoEndorseOptionSchema())
@querystring_schema(EndorserDIDOptionSchema())
@querystring_schema(CreateTransactionForEndorserOptionSchema())
@querystring_schema(ConnIdMatchInfoSchema())
@response_schema(TxnOrCredentialDefinitionSendResultSchema(), 200, description="")
async def credential_definitions_send_credential_definition(request: web.BaseRequest):
"""
Expand All @@ -170,8 +175,12 @@ async def credential_definitions_send_credential_definition(request: web.BaseReq
"""
context: AdminRequestContext = request["context"]
auto_endorse = json.loads(request.query.get("auto_endorse", "true"))
endorser_did = request.query.get("endorser_did", None)
create_transaction_for_endorser = json.loads(
request.query.get("create_transaction_for_endorser", "false")
)
write_ledger = not create_transaction_for_endorser
endorser_did = None
connection_id = request.query.get("conn_id")

body = await request.json()

Expand All @@ -180,6 +189,32 @@ async def credential_definitions_send_credential_definition(request: web.BaseReq
tag = body.get("tag")
rev_reg_size = body.get("revocation_registry_size")

if not write_ledger:

try:
async with context.session() as session:
connection_record = await ConnRecord.retrieve_by_id(
session, connection_id
)
except StorageNotFoundError as err:
raise web.HTTPNotFound(reason=err.roll_up) from err
except BaseModelError as err:
raise web.HTTPBadRequest(reason=err.roll_up) from err

session = await context.session()
endorser_info = await connection_record.metadata_get(session, "endorser_info")
if not endorser_info:
raise web.HTTPForbidden(
reason="Endorser Info is not set up in "
"connection metadata for this connection record"
)
if "endorser_did" not in endorser_info.keys():
raise web.HTTPForbidden(
reason=' "endorser_did" is not set in "endorser_info"'
" in connection metadata for this connection record"
)
endorser_did = endorser_info["endorser_did"]

ledger = context.inject(BaseLedger, required=False)
if not ledger:
reason = "No ledger available"
Expand All @@ -197,7 +232,7 @@ async def credential_definitions_send_credential_definition(request: web.BaseReq
signature_type=None,
tag=tag,
support_revocation=support_revocation,
write_ledger=auto_endorse,
write_ledger=write_ledger,
endorser_did=endorser_did,
)
)
Expand Down Expand Up @@ -258,7 +293,7 @@ async def credential_definitions_send_credential_definition(request: web.BaseReq
except RevocationError as e:
raise web.HTTPBadRequest(reason=e.message) from e

if auto_endorse:
if not create_transaction_for_endorser:
return web.json_response({"sent": {"credential_definition_id": cred_def_id}})

else:
Expand All @@ -267,8 +302,7 @@ async def credential_definitions_send_credential_definition(request: web.BaseReq
transaction_mgr = TransactionManager(session)
try:
transaction = await transaction_mgr.create_record(
messages_attach=cred_def["signed_txn"],
expires_time="1597708800",
messages_attach=cred_def["signed_txn"], connection_id=connection_id
)
except StorageError as err:
raise web.HTTPBadRequest(reason=err.roll_up) from err
Expand Down
162 changes: 151 additions & 11 deletions aries_cloudagent/messaging/credential_definitions/tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from ....tails.base import BaseTailsServer

from .. import routes as test_module
from ....connections.models.conn_record import ConnRecord


SCHEMA_ID = "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0"
Expand Down Expand Up @@ -67,7 +68,7 @@ async def test_send_credential_definition(self):
}
)

self.request.query = {"auto_endorse": "true"}
self.request.query = {"create_transaction_for_endorser": "false"}

with async_mock.patch.object(test_module.web, "json_response") as mock_response:
result = (
Expand All @@ -89,7 +90,7 @@ async def test_send_credential_definition_revoc(self):
}
)

self.request.query = {"auto_endorse": "true"}
self.request.query = {"create_transaction_for_endorser": "false"}

self.context.profile.settings.set_value(
"tails_server_base_url", "http://1.2.3.4:8222"
Expand Down Expand Up @@ -133,7 +134,7 @@ async def test_send_credential_definition_revoc_no_tails_server_x(self):
}
)

self.request.query = {"auto_endorse": "true"}
self.request.query = {"create_transaction_for_endorser": "false"}

with self.assertRaises(test_module.web.HTTPBadRequest):
await test_module.credential_definitions_send_credential_definition(
Expand All @@ -149,7 +150,7 @@ async def test_send_credential_definition_revoc_no_support_x(self):
}
)

self.request.query = {"auto_endorse": "true"}
self.request.query = {"create_transaction_for_endorser": "false"}

self.context.profile.settings.set_value(
"tails_server_base_url", "http://1.2.3.4:8222"
Expand Down Expand Up @@ -177,7 +178,7 @@ async def test_send_credential_definition_revoc_upload_x(self):
}
)

self.request.query = {"auto_endorse": "true"}
self.request.query = {"create_transaction_for_endorser": "false"}

self.context.profile.settings.set_value(
"tails_server_base_url", "http://1.2.3.4:8222"
Expand Down Expand Up @@ -218,7 +219,7 @@ async def test_send_credential_definition_revoc_init_issuer_rev_reg_x(self):
}
)

self.request.query = {"auto_endorse": "true"}
self.request.query = {"create_transaction_for_endorser": "false"}

self.context.profile.settings.set_value(
"tails_server_base_url", "http://1.2.3.4:8222"
Expand Down Expand Up @@ -250,7 +251,7 @@ async def test_send_credential_definition_revoc_init_issuer_rev_reg_x(self):
self.request
)

async def test_send_credential_definition_no_auto_endorse(self):
async def test_send_credential_definition_create_transaction_for_endorser(self):
self.request.json = async_mock.CoroutineMock(
return_value={
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
Expand All @@ -259,9 +260,14 @@ async def test_send_credential_definition_no_auto_endorse(self):
}
)

self.request.query = {"auto_endorse": "false"}
self.request.query = {
"create_transaction_for_endorser": "true",
"conn_id": "dummy",
}

with async_mock.patch.object(
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
) as mock_conn_rec_retrieve, async_mock.patch.object(
test_module, "TransactionManager", async_mock.MagicMock()
) as mock_txn_mgr, async_mock.patch.object(
test_module.web, "json_response", async_mock.MagicMock()
Expand All @@ -273,6 +279,14 @@ async def test_send_credential_definition_no_auto_endorse(self):
)
)
)
mock_conn_rec_retrieve.return_value = async_mock.MagicMock(
metadata_get=async_mock.CoroutineMock(
return_value={
"endorser_did": ("did"),
"endorser_name": ("name"),
}
)
)
result = (
await test_module.credential_definitions_send_credential_definition(
self.request
Expand All @@ -281,7 +295,9 @@ async def test_send_credential_definition_no_auto_endorse(self):
assert result == mock_response.return_value
mock_response.assert_called_once_with({"txn": {"...": "..."}})

async def test_send_credential_definition_no_auto_endorse_storage_x(self):
async def test_send_credential_definition_create_transaction_for_endorser_storage_x(
self,
):
self.request.json = async_mock.CoroutineMock(
return_value={
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
Expand All @@ -290,11 +306,25 @@ async def test_send_credential_definition_no_auto_endorse_storage_x(self):
}
)

self.request.query = {"auto_endorse": "false"}
self.request.query = {
"create_transaction_for_endorser": "true",
"conn_id": "dummy",
}

with async_mock.patch.object(
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
) as mock_conn_rec_retrieve, async_mock.patch.object(
test_module, "TransactionManager", async_mock.MagicMock()
) as mock_txn_mgr:

mock_conn_rec_retrieve.return_value = async_mock.MagicMock(
metadata_get=async_mock.CoroutineMock(
return_value={
"endorser_did": ("did"),
"endorser_name": ("name"),
}
)
)
mock_txn_mgr.return_value = async_mock.MagicMock(
create_record=async_mock.CoroutineMock(
side_effect=test_module.StorageError()
Expand All @@ -306,6 +336,116 @@ async def test_send_credential_definition_no_auto_endorse_storage_x(self):
self.request
)

async def test_send_credential_definition_create_transaction_for_endorser_not_found_x(
self,
):
self.request.json = async_mock.CoroutineMock(
return_value={
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
"support_revocation": False,
"tag": "tag",
}
)

self.request.query = {
"create_transaction_for_endorser": "true",
"conn_id": "dummy",
}

with async_mock.patch.object(
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
) as mock_conn_rec_retrieve:
mock_conn_rec_retrieve.side_effect = test_module.StorageNotFoundError()

with self.assertRaises(test_module.web.HTTPNotFound):
await test_module.credential_definitions_send_credential_definition(
self.request
)

async def test_send_credential_definition_create_transaction_for_endorser_base_model_x(
self,
):
self.request.json = async_mock.CoroutineMock(
return_value={
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
"support_revocation": False,
"tag": "tag",
}
)

self.request.query = {
"create_transaction_for_endorser": "true",
"conn_id": "dummy",
}

with async_mock.patch.object(
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
) as mock_conn_rec_retrieve:
mock_conn_rec_retrieve.side_effect = test_module.BaseModelError()

with self.assertRaises(test_module.web.HTTPBadRequest):
await test_module.credential_definitions_send_credential_definition(
self.request
)

async def test_send_credential_definition_create_transaction_for_endorser_no_endorser_info_x(
self,
):
self.request.json = async_mock.CoroutineMock(
return_value={
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
"support_revocation": False,
"tag": "tag",
}
)

self.request.query = {
"create_transaction_for_endorser": "true",
"conn_id": "dummy",
}

with async_mock.patch.object(
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
) as mock_conn_rec_retrieve:
mock_conn_rec_retrieve.return_value = async_mock.MagicMock(
metadata_get=async_mock.CoroutineMock(return_value=None)
)
with self.assertRaises(test_module.web.HTTPForbidden):
await test_module.credential_definitions_send_credential_definition(
self.request
)

async def test_send_credential_definition_create_transaction_for_endorser_no_endorser_did_x(
self,
):
self.request.json = async_mock.CoroutineMock(
return_value={
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
"support_revocation": False,
"tag": "tag",
}
)

self.request.query = {
"create_transaction_for_endorser": "true",
"conn_id": "dummy",
}

with async_mock.patch.object(
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
) as mock_conn_rec_retrieve:
mock_conn_rec_retrieve.return_value = async_mock.MagicMock(
metadata_get=async_mock.CoroutineMock(
return_value={
"endorser_name": ("name"),
}
)
)
with self.assertRaises(test_module.web.HTTPForbidden):
await test_module.credential_definitions_send_credential_definition(
self.request
)

async def test_send_credential_definition_no_ledger(self):
self.request.json = async_mock.CoroutineMock(
return_value={
Expand All @@ -331,7 +471,7 @@ async def test_send_credential_definition_ledger_x(self):
}
)

self.request.query = {"auto_endorse": "true"}
self.request.query = {"create_transaction_for_endorser": "false"}

self.ledger.__aenter__ = async_mock.CoroutineMock(
side_effect=test_module.LedgerError("oops")
Expand Down
Loading

0 comments on commit 708f9d3

Please sign in to comment.