From 664712594948a1cd8646dec713510e788328ad40 Mon Sep 17 00:00:00 2001 From: sklump Date: Thu, 9 Jul 2020 15:10:06 +0000 Subject: [PATCH] preview from offer now contains attribute values - take them out of issue request body Signed-off-by: sklump --- .../v1_0/handlers/credential_issue_handler.py | 6 +- .../v1_0/handlers/credential_offer_handler.py | 4 +- .../handlers/credential_proposal_handler.py | 8 +- .../handlers/credential_request_handler.py | 19 ++--- .../tests/test_credential_request_handler.py | 23 +----- .../issue_credential/v1_0/manager.py | 10 +-- .../protocols/issue_credential/v1_0/routes.py | 12 +-- .../v1_0/tests/test_manager.py | 49 ++++++++---- .../v1_0/tests/test_routes.py | 79 +++---------------- 9 files changed, 70 insertions(+), 140 deletions(-) diff --git a/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_issue_handler.py b/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_issue_handler.py index 8f818069cf..5a6bf65ab6 100644 --- a/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_issue_handler.py +++ b/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_issue_handler.py @@ -38,7 +38,7 @@ async def handle(self, context: RequestContext, responder: BaseResponder): credential_manager = CredentialManager(context) - credential_exchange_record = await credential_manager.receive_credential() + cred_ex_record = await credential_manager.receive_credential() r_time = trace_event( context.settings, @@ -50,9 +50,9 @@ async def handle(self, context: RequestContext, responder: BaseResponder): # Automatically move to next state if flag is set if context.settings.get("debug.auto_store_credential"): ( - credential_exchange_record, + cred_ex_record, credential_ack_message, - ) = await credential_manager.store_credential(credential_exchange_record) + ) = await credential_manager.store_credential(cred_ex_record) # Ack issuer that holder stored credential await responder.send_reply(credential_ack_message) diff --git a/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_offer_handler.py b/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_offer_handler.py index 2670e83b89..3d6caa0dea 100644 --- a/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_offer_handler.py +++ b/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_offer_handler.py @@ -39,7 +39,7 @@ async def handle(self, context: RequestContext, responder: BaseResponder): credential_manager = CredentialManager(context) - credential_exchange_record = await credential_manager.receive_offer() + cred_ex_record = await credential_manager.receive_offer() r_time = trace_event( context.settings, @@ -51,7 +51,7 @@ async def handle(self, context: RequestContext, responder: BaseResponder): # If auto respond is turned on, automatically reply with credential request if context.settings.get("debug.auto_respond_credential_offer"): (_, credential_request_message) = await credential_manager.create_request( - cred_ex_record=credential_exchange_record, + cred_ex_record=cred_ex_record, holder_did=context.connection_record.my_did, ) await responder.send_reply(credential_request_message) diff --git a/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_proposal_handler.py b/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_proposal_handler.py index d5566935b0..6682cb0209 100644 --- a/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_proposal_handler.py +++ b/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_proposal_handler.py @@ -38,7 +38,7 @@ async def handle(self, context: RequestContext, responder: BaseResponder): raise HandlerException("No connection established for credential proposal") credential_manager = CredentialManager(context) - credential_exchange_record = await credential_manager.receive_proposal() + cred_ex_record = await credential_manager.receive_proposal() r_time = trace_event( context.settings, @@ -48,12 +48,12 @@ async def handle(self, context: RequestContext, responder: BaseResponder): ) # If auto_offer is enabled, respond immediately with offer - if credential_exchange_record.auto_offer: + if cred_ex_record.auto_offer: ( - credential_exchange_record, + cred_ex_record, credential_offer_message, ) = await credential_manager.create_offer( - credential_exchange_record, comment=context.message.comment + cred_ex_record, comment=context.message.comment ) await responder.send_reply(credential_offer_message) diff --git a/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_request_handler.py b/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_request_handler.py index 2cdeb763b4..a3ba0803ab 100644 --- a/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_request_handler.py +++ b/aries_cloudagent/protocols/issue_credential/v1_0/handlers/credential_request_handler.py @@ -9,7 +9,6 @@ from ..manager import CredentialManager from ..messages.credential_request import CredentialRequest -from ..messages.credential_proposal import CredentialProposal from .....utils.tracing import trace_event, get_timer @@ -39,7 +38,7 @@ async def handle(self, context: RequestContext, responder: BaseResponder): raise HandlerException("No connection established for credential request") credential_manager = CredentialManager(context) - cred_exchange_rec = await credential_manager.receive_request() + cred_ex_record = await credential_manager.receive_request() r_time = trace_event( context.settings, @@ -49,20 +48,16 @@ async def handle(self, context: RequestContext, responder: BaseResponder): ) # If auto_issue is enabled, respond immediately - if cred_exchange_rec.auto_issue: + if cred_ex_record.auto_issue: if ( - cred_exchange_rec.credential_proposal_dict - and "credential_proposal" in cred_exchange_rec.credential_proposal_dict + cred_ex_record.credential_proposal_dict + and "credential_proposal" in cred_ex_record.credential_proposal_dict ): ( - cred_exchange_rec, + cred_ex_record, credential_issue_message, ) = await credential_manager.issue_credential( - cred_ex_record=cred_exchange_rec, - comment=context.message.comment, - credential_values=CredentialProposal.deserialize( - cred_exchange_rec.credential_proposal_dict - ).credential_proposal.attr_dict(), + cred_ex_record=cred_ex_record, comment=context.message.comment ) await responder.send_reply(credential_issue_message) @@ -76,6 +71,6 @@ async def handle(self, context: RequestContext, responder: BaseResponder): else: self._logger.warning( "Operation set for auto-issue but credential exchange record " - f"{cred_exchange_rec.credential_exchange_id} " + f"{cred_ex_record.credential_exchange_id} " "has no attribute values" ) diff --git a/aries_cloudagent/protocols/issue_credential/v1_0/handlers/tests/test_credential_request_handler.py b/aries_cloudagent/protocols/issue_credential/v1_0/handlers/tests/test_credential_request_handler.py index 778e963dae..81baf6b486 100644 --- a/aries_cloudagent/protocols/issue_credential/v1_0/handlers/tests/test_credential_request_handler.py +++ b/aries_cloudagent/protocols/issue_credential/v1_0/handlers/tests/test_credential_request_handler.py @@ -51,14 +51,12 @@ async def test_called_auto_issue(self): attributes=(CredAttrSpec.list_plain(ATTR_DICT)) ).serialize(), "cred_def_id": CD_ID, - } + }, ) with async_mock.patch.object( handler, "CredentialManager", autospec=True - ) as mock_cred_mgr, async_mock.patch.object( - handler, "CredentialProposal", autospec=True - ) as mock_cred_proposal: + ) as mock_cred_mgr: mock_cred_mgr.return_value.receive_request = async_mock.CoroutineMock( return_value=cred_ex_rec ) @@ -66,20 +64,13 @@ async def test_called_auto_issue(self): mock_cred_mgr.return_value.issue_credential = async_mock.CoroutineMock( return_value=(None, "credential_issue_message") ) - mock_cred_proposal.deserialize = async_mock.MagicMock( - return_value=mock_cred_proposal - ) - mock_cred_proposal.credential_proposal = async_mock.MagicMock() - mock_cred_proposal.credential_proposal.attr_dict = async_mock.MagicMock( - return_value=ATTR_DICT - ) request_context.message = CredentialRequest() request_context.connection_ready = True handler_inst = handler.CredentialRequestHandler() responder = MockResponder() await handler_inst.handle(request_context, responder) mock_cred_mgr.return_value.issue_credential.assert_called_once_with( - cred_ex_record=cred_ex_rec, comment=None, credential_values=ATTR_DICT, + cred_ex_record=cred_ex_rec, comment=None ) mock_cred_mgr.assert_called_once_with(request_context) @@ -101,9 +92,7 @@ async def test_called_auto_issue_no_preview(self): with async_mock.patch.object( handler, "CredentialManager", autospec=True - ) as mock_cred_mgr, async_mock.patch.object( - handler, "CredentialProposal", autospec=True - ) as mock_cred_proposal: + ) as mock_cred_mgr: mock_cred_mgr.return_value.receive_request = async_mock.CoroutineMock( return_value=cred_ex_rec ) @@ -111,10 +100,6 @@ async def test_called_auto_issue_no_preview(self): mock_cred_mgr.return_value.issue_credential = async_mock.CoroutineMock( return_value=(None, "credential_issue_message") ) - mock_cred_proposal.deserialize = async_mock.MagicMock( - return_value=mock_cred_proposal - ) - mock_cred_proposal.credential_proposal = async_mock.MagicMock() request_context.message = CredentialRequest() request_context.connection_ready = True diff --git a/aries_cloudagent/protocols/issue_credential/v1_0/manager.py b/aries_cloudagent/protocols/issue_credential/v1_0/manager.py index a4e80a3d2b..94ebbf5599 100644 --- a/aries_cloudagent/protocols/issue_credential/v1_0/manager.py +++ b/aries_cloudagent/protocols/issue_credential/v1_0/manager.py @@ -453,11 +453,7 @@ async def receive_request(self): return cred_ex_record async def issue_credential( - self, - cred_ex_record: V10CredentialExchange, - *, - comment: str = None, - credential_values: dict, + self, cred_ex_record: V10CredentialExchange, *, comment: str = None, ) -> Tuple[V10CredentialExchange, CredentialIssue]: """ Issue a credential. @@ -466,7 +462,6 @@ async def issue_credential( cred_ex_record: The credential exchange record for which to issue a credential comment: optional human-readable comment pertaining to credential issue - credential_values: dict of credential attribute {name: value} pairs Returns: Tuple: (Updated credential exchange record, credential message) @@ -518,6 +513,9 @@ async def issue_credential( else: tails_path = None + credential_values = CredentialProposal.deserialize( + cred_ex_record.credential_proposal_dict + ).credential_proposal.attr_dict(decode=False) issuer: BaseIssuer = await self.context.inject(BaseIssuer) try: ( diff --git a/aries_cloudagent/protocols/issue_credential/v1_0/routes.py b/aries_cloudagent/protocols/issue_credential/v1_0/routes.py index 80b45b3541..7c1e140139 100644 --- a/aries_cloudagent/protocols/issue_credential/v1_0/routes.py +++ b/aries_cloudagent/protocols/issue_credential/v1_0/routes.py @@ -243,7 +243,6 @@ class V10CredentialIssueRequestSchema(Schema): """Request schema for sending credential issue admin message.""" comment = fields.Str(description="Human-readable comment", required=False) - credential_preview = fields.Nested(CredentialPreviewSchema, required=True) class V10CredentialProblemReportRequestSchema(Schema): @@ -1042,9 +1041,6 @@ async def credential_exchange_issue(request: web.BaseRequest): body = await request.json() comment = body.get("comment") - preview_spec = body.get("credential_preview") - if not preview_spec: - raise web.HTTPBadRequest(reason="credential_preview must be provided") credential_exchange_id = request.match_info["cred_ex_id"] try: @@ -1063,17 +1059,11 @@ async def credential_exchange_issue(request: web.BaseRequest): if not connection_record.is_ready: raise web.HTTPForbidden(reason=f"Connection {connection_id} not ready") - credential_preview = CredentialPreview.deserialize(preview_spec) - credential_manager = CredentialManager(context) ( cred_ex_record, credential_issue_message, - ) = await credential_manager.issue_credential( - cred_ex_record, - comment=comment, - credential_values=credential_preview.attr_dict(decode=False), - ) + ) = await credential_manager.issue_credential(cred_ex_record, comment=comment) result = cred_ex_record.serialize() except (StorageError, IssuerError, BaseModelError, CredentialManagerError) as err: diff --git a/aries_cloudagent/protocols/issue_credential/v1_0/tests/test_manager.py b/aries_cloudagent/protocols/issue_credential/v1_0/tests/test_manager.py index cada3f7a8b..32ab7dfd4c 100644 --- a/aries_cloudagent/protocols/issue_credential/v1_0/tests/test_manager.py +++ b/aries_cloudagent/protocols/issue_credential/v1_0/tests/test_manager.py @@ -861,6 +861,13 @@ async def test_issue_credential(self): credential_definition_id=CRED_DEF_ID, credential_offer=indy_offer, credential_request=indy_cred_req, + credential_proposal_dict=CredentialProposal( + credential_proposal=CredentialPreview.deserialize( + {"attributes": [{"name": "attr", "value": "value"}]} + ), + cred_def_id=CRED_DEF_ID, + schema_id=SCHEMA_ID, + ).serialize(), initiator=V10CredentialExchange.INITIATOR_SELF, role=V10CredentialExchange.ROLE_ISSUER, state=V10CredentialExchange.STATE_REQUEST_RECEIVED, @@ -894,7 +901,7 @@ async def test_issue_credential(self): ] ) (ret_exchange, ret_cred_issue) = await self.manager.issue_credential( - stored_exchange, comment=comment, credential_values=cred_values + stored_exchange, comment=comment ) save_ex.assert_called_once() @@ -914,9 +921,7 @@ async def test_issue_credential(self): ( ret_existing_exchange, ret_existing_cred, - ) = await self.manager.issue_credential( - stored_exchange, comment=comment, credential_values=cred_values - ) + ) = await self.manager.issue_credential(stored_exchange, comment=comment) assert ret_existing_exchange == ret_exchange assert ret_existing_cred._thread_id == thread_id @@ -936,6 +941,13 @@ async def test_issue_credential_non_revocable(self): credential_definition_id=CRED_DEF_ID, credential_offer=indy_offer, credential_request=indy_cred_req, + credential_proposal_dict=CredentialProposal( + credential_proposal=CredentialPreview.deserialize( + {"attributes": [{"name": "attr", "value": "value"}]} + ), + cred_def_id=CRED_DEF_ID, + schema_id=SCHEMA_ID, + ).serialize(), initiator=V10CredentialExchange.INITIATOR_SELF, role=V10CredentialExchange.ROLE_ISSUER, state=V10CredentialExchange.STATE_REQUEST_RECEIVED, @@ -963,7 +975,7 @@ async def test_issue_credential_non_revocable(self): V10CredentialExchange, "save", autospec=True ) as save_ex: (ret_exchange, ret_cred_issue) = await self.manager.issue_credential( - stored_exchange, comment=comment, credential_values=cred_values + stored_exchange, comment=comment ) save_ex.assert_called_once() @@ -981,7 +993,6 @@ async def test_issue_credential_request_bad_state(self): connection_id = "test_conn_id" indy_offer = {"schema_id": SCHEMA_ID, "cred_def_id": CRED_DEF_ID} thread_id = "thread-id" - cred_values = {"attr": "value"} stored_exchange = V10CredentialExchange( credential_exchange_id="dummy-cxid", @@ -996,9 +1007,7 @@ async def test_issue_credential_request_bad_state(self): ) with self.assertRaises(CredentialManagerError): - await self.manager.issue_credential( - stored_exchange, credential_values=cred_values - ) + await self.manager.issue_credential(stored_exchange) async def test_issue_credential_no_active_rr(self): connection_id = "test_conn_id" @@ -1014,6 +1023,13 @@ async def test_issue_credential_no_active_rr(self): credential_definition_id=CRED_DEF_ID, credential_offer=indy_offer, credential_request=indy_cred_req, + credential_proposal_dict=CredentialProposal( + credential_proposal=CredentialPreview.deserialize( + {"attributes": [{"name": "attr", "value": "value"}]} + ), + cred_def_id=CRED_DEF_ID, + schema_id=SCHEMA_ID, + ).serialize(), initiator=V10CredentialExchange.INITIATOR_SELF, role=V10CredentialExchange.ROLE_ISSUER, state=V10CredentialExchange.STATE_REQUEST_RECEIVED, @@ -1037,9 +1053,7 @@ async def test_issue_credential_no_active_rr(self): return_value=[] ) with self.assertRaises(CredentialManagerError) as x_cred_mgr: - await self.manager.issue_credential( - stored_exchange, comment=comment, credential_values=cred_values - ) + await self.manager.issue_credential(stored_exchange, comment=comment) assert "has no active revocation registry" in x_cred_mgr.message async def test_issue_credential_rr_full(self): @@ -1056,6 +1070,13 @@ async def test_issue_credential_rr_full(self): credential_definition_id=CRED_DEF_ID, credential_offer=indy_offer, credential_request=indy_cred_req, + credential_proposal_dict=CredentialProposal( + credential_proposal=CredentialPreview.deserialize( + {"attributes": [{"name": "attr", "value": "value"}]} + ), + cred_def_id=CRED_DEF_ID, + schema_id=SCHEMA_ID, + ).serialize(), initiator=V10CredentialExchange.INITIATOR_SELF, role=V10CredentialExchange.ROLE_ISSUER, state=V10CredentialExchange.STATE_REQUEST_RECEIVED, @@ -1087,9 +1108,7 @@ async def test_issue_credential_rr_full(self): ) with self.assertRaises(test_module.IssuerRevocationRegistryFullError): - await self.manager.issue_credential( - stored_exchange, comment=comment, credential_values=cred_values - ) + await self.manager.issue_credential(stored_exchange, comment=comment) async def test_receive_credential(self): connection_id = "test_conn_id" diff --git a/aries_cloudagent/protocols/issue_credential/v1_0/tests/test_routes.py b/aries_cloudagent/protocols/issue_credential/v1_0/tests/test_routes.py index 5c4a533522..cf2b0218b0 100644 --- a/aries_cloudagent/protocols/issue_credential/v1_0/tests/test_routes.py +++ b/aries_cloudagent/protocols/issue_credential/v1_0/tests/test_routes.py @@ -1305,8 +1305,6 @@ async def test_credential_exchange_issue(self): ) as mock_credential_manager, async_mock.patch.object( test_module, "V10CredentialExchange", autospec=True ) as mock_cred_ex, async_mock.patch.object( - test_module, "CredentialPreview", autospec=True - ) as mock_cred_preview, async_mock.patch.object( test_module.web, "json_response" ) as mock_response: @@ -1322,37 +1320,12 @@ async def test_credential_exchange_issue(self): async_mock.MagicMock(), ) - mock_cred_preview.return_value.deserialize.return_value = ( - async_mock.MagicMock() - ) - mock_cred_preview.return_value.attr_dict.return_value = ( - async_mock.MagicMock() - ) - await test_module.credential_exchange_issue(mock) mock_response.assert_called_once_with( mock_cred_ex_record.serialize.return_value ) - async def test_credential_exchange_issue_no_preview(self): - mock = async_mock.MagicMock() - mock.json = async_mock.CoroutineMock() - mock.json.return_value = { - "comment": "comment", - } - - mock.app = { - "outbound_message_router": async_mock.CoroutineMock(), - "request_context": async_mock.patch.object( - aio_web, "BaseRequest", autospec=True - ), - } - mock.app["request_context"].settings = {} - - with self.assertRaises(test_module.web.HTTPBadRequest): - await test_module.credential_exchange_issue(mock) - async def test_credential_exchange_issue_bad_cred_ex_id(self): mock = async_mock.MagicMock() mock.json = async_mock.CoroutineMock() @@ -1394,9 +1367,7 @@ async def test_credential_exchange_issue_no_conn_record(self): test_module, "CredentialManager", autospec=True ) as mock_credential_manager, async_mock.patch.object( test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, async_mock.patch.object( - test_module, "CredentialPreview", autospec=True - ) as mock_cred_preview: + ) as mock_cred_ex: mock_cred_ex.retrieve_by_id = async_mock.CoroutineMock() mock_cred_ex.retrieve_by_id.return_value.state = ( @@ -1416,13 +1387,6 @@ async def test_credential_exchange_issue_no_conn_record(self): async_mock.MagicMock(), ) - mock_cred_preview.return_value.deserialize.return_value = ( - async_mock.MagicMock() - ) - mock_cred_preview.return_value.attr_dict.return_value = ( - async_mock.MagicMock() - ) - with self.assertRaises(test_module.web.HTTPBadRequest): await test_module.credential_exchange_issue(mock) @@ -1444,9 +1408,7 @@ async def test_credential_exchange_issue_not_ready(self): test_module, "CredentialManager", autospec=True ) as mock_credential_manager, async_mock.patch.object( test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, async_mock.patch.object( - test_module, "CredentialPreview", autospec=True - ) as mock_cred_preview: + ) as mock_cred_ex: mock_cred_ex.retrieve_by_id = async_mock.CoroutineMock() mock_cred_ex.retrieve_by_id.return_value.state = ( @@ -1465,13 +1427,6 @@ async def test_credential_exchange_issue_not_ready(self): async_mock.MagicMock(), ) - mock_cred_preview.return_value.deserialize.return_value = ( - async_mock.MagicMock() - ) - mock_cred_preview.return_value.attr_dict.return_value = ( - async_mock.MagicMock() - ) - with self.assertRaises(test_module.web.HTTPForbidden): await test_module.credential_exchange_issue(mock) @@ -1493,9 +1448,7 @@ async def test_credential_exchange_issue_rev_reg_full(self): test_module, "CredentialManager", autospec=True ) as mock_credential_manager, async_mock.patch.object( test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, async_mock.patch.object( - test_module, "CredentialPreview", autospec=True - ) as mock_cred_preview: + ) as mock_cred_ex: mock_cred_ex.retrieve_by_id = async_mock.CoroutineMock() mock_cred_ex.retrieve_by_id.return_value.state = ( @@ -1510,13 +1463,6 @@ async def test_credential_exchange_issue_rev_reg_full(self): ) mock_credential_manager.return_value.issue_credential = mock_issue_cred - mock_cred_preview.return_value.deserialize.return_value = ( - async_mock.MagicMock() - ) - mock_cred_preview.return_value.attr_dict.return_value = ( - async_mock.MagicMock() - ) - with self.assertRaises(test_module.web.HTTPBadRequest) as context: await test_module.credential_exchange_issue(mock) @@ -1532,27 +1478,24 @@ async def test_credential_exchange_issue_deser_x(self): } mock.app["request_context"].settings = {} + mock_cred_ex_rec = async_mock.MagicMock( + connection_id="dummy", + serialize=async_mock.MagicMock(side_effect=test_module.BaseModelError()), + ) with async_mock.patch.object( test_module, "ConnectionRecord", autospec=True ) as mock_conn_rec, async_mock.patch.object( test_module, "CredentialManager", autospec=True ) as mock_credential_manager, async_mock.patch.object( test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, async_mock.patch.object( - test_module, "CredentialPreview", autospec=True - ) as mock_cred_preview: - mock_cred_ex.retrieve_by_id = async_mock.CoroutineMock() - mock_cred_ex.retrieve_by_id.return_value.state = ( - mock_cred_ex.STATE_REQUEST_RECEIVED + ) as mock_cred_ex: + mock_cred_ex.retrieve_by_id = async_mock.CoroutineMock( + return_value=mock_cred_ex_rec ) - mock_cred_ex_record = async_mock.MagicMock() mock_credential_manager.return_value.issue_credential.return_value = ( - mock_cred_ex_record, + mock_cred_ex_rec, async_mock.MagicMock(), ) - mock_cred_preview.deserialize = async_mock.MagicMock( - side_effect=test_module.BaseModelError() - ) with self.assertRaises(test_module.web.HTTPBadRequest): await test_module.credential_exchange_issue(mock)