From 98184e249d4a2675bc4a3fb92d20e107e4375fdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emiliano=20Su=C3=B1=C3=A9?= Date: Fri, 29 Nov 2019 13:08:05 -0800 Subject: [PATCH] Add create-proposal endpoint to the present-proof API namespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Emiliano Suñé --- .../protocols/present_proof/v1_0/routes.py | 61 +++++++- .../present_proof/v1_0/tests/test_routes.py | 131 +++++++++--------- 2 files changed, 122 insertions(+), 70 deletions(-) diff --git a/aries_cloudagent/protocols/present_proof/v1_0/routes.py b/aries_cloudagent/protocols/present_proof/v1_0/routes.py index 89b569bbb3..2f24507fd0 100644 --- a/aries_cloudagent/protocols/present_proof/v1_0/routes.py +++ b/aries_cloudagent/protocols/present_proof/v1_0/routes.py @@ -32,7 +32,6 @@ V10PresentationExchange, V10PresentationExchangeSchema, ) -from .message_types import ATTACH_DECO_IDS, PRESENTATION_REQUEST class V10PresentationExchangeListSchema(Schema): @@ -426,6 +425,58 @@ async def presentation_exchange_send_proposal(request: web.BaseRequest): return web.json_response(presentation_exchange_record.serialize()) +@docs( + tags=["present-proof"], + summary=""" + Creates a presentation request not bound to any proposal or existing connection + """, +) +@request_schema(V10PresentationRequestRequestSchema()) +@response_schema(V10PresentationExchangeSchema(), 200) +async def presentation_exchange_create_request(request: web.BaseRequest): + """ + Request handler for creating a free presentation request. + + The presentation request will not be bound to any proposal + or existing connection. + + Args: + request: aiohttp request object + + Returns: + The presentation exchange details + + """ + context = request.app["request_context"] + outbound_handler = request.app["outbound_message_router"] + + body = await request.json() + + comment = body.get("comment") + indy_proof_request = body.get("proof_request") + if not indy_proof_request.get("nonce"): + indy_proof_request["nonce"] = str(uuid4().int) + + presentation_request_message = PresentationRequest( + comment=comment, + request_presentations_attach=[ + AttachDecorator.from_indy_dict(indy_proof_request) + ], + ) + + presentation_manager = PresentationManager(context) + + ( + presentation_exchange_record + ) = await presentation_manager.create_exchange_for_request( + connection_id=None, presentation_request_message=presentation_request_message + ) + + await outbound_handler(presentation_request_message, connection_id=None) + + return web.json_response(presentation_exchange_record.serialize()) + + @docs( tags=["present-proof"], summary="Sends a free presentation request not bound to any proposal", @@ -467,10 +518,7 @@ async def presentation_exchange_send_free_request(request: web.BaseRequest): presentation_request_message = PresentationRequest( comment=comment, request_presentations_attach=[ - AttachDecorator.from_indy_dict( - indy_dict=indy_proof_request, - ident=ATTACH_DECO_IDS[PRESENTATION_REQUEST], - ) + AttachDecorator.from_indy_dict(indy_proof_request) ], ) @@ -684,6 +732,9 @@ async def register(app: web.Application): web.post( "/present-proof/send-proposal", presentation_exchange_send_proposal ), + web.post( + "/present-proof/create-request", presentation_exchange_create_request + ), web.post( "/present-proof/send-request", presentation_exchange_send_free_request ), diff --git a/aries_cloudagent/protocols/present_proof/v1_0/tests/test_routes.py b/aries_cloudagent/protocols/present_proof/v1_0/tests/test_routes.py index 0897a175af..9edb9c6a96 100644 --- a/aries_cloudagent/protocols/present_proof/v1_0/tests/test_routes.py +++ b/aries_cloudagent/protocols/present_proof/v1_0/tests/test_routes.py @@ -26,9 +26,7 @@ async def test_presentation_exchange_list(self): ) as mock_presentation_exchange: mock_presentation_exchange.query = async_mock.CoroutineMock() - mock_presentation_exchange.query.return_value = [ - mock_presentation_exchange - ] + mock_presentation_exchange.query.return_value = [mock_presentation_exchange] mock_presentation_exchange.serialize = async_mock.MagicMock() mock_presentation_exchange.serialize.return_value = {"hello": "world"} @@ -42,9 +40,7 @@ async def test_presentation_exchange_list(self): async def test_presentation_exchange_credentials_list_not_found(self): mock = async_mock.MagicMock() mock.match_info = {"pres_ex_id": "dummy"} - mock.app = { - "request_context": "context", - } + mock.app = {"request_context": "context"} with async_mock.patch.object( test_module, "V10PresentationExchange", autospec=True @@ -127,9 +123,7 @@ async def test_presentation_exchange_credentials_list_multiple_referents(self): async def test_presentation_exchange_retrieve(self): mock = async_mock.MagicMock() mock.match_info = {"pres_ex_id": "dummy"} - mock.app = { - "request_context": "context", - } + mock.app = {"request_context": "context"} with async_mock.patch.object( test_module, "V10PresentationExchange", autospec=True @@ -149,9 +143,7 @@ async def test_presentation_exchange_retrieve(self): async def test_presentation_exchange_retrieve_not_found(self): mock = async_mock.MagicMock() mock.match_info = {"pres_ex_id": "dummy"} - mock.app = { - "request_context": "context", - } + mock.app = {"request_context": "context"} with async_mock.patch.object( test_module, "V10PresentationExchange", autospec=True @@ -266,13 +258,55 @@ async def test_presentation_exchange_send_proposal_not_ready(self): with self.assertRaises(test_module.web.HTTPForbidden): await test_module.presentation_exchange_send_proposal(mock) + async def test_presentation_exchange_create_request(self): + mock = async_mock.MagicMock() + mock.json = async_mock.CoroutineMock( + return_value={"comment": "dummy", "proof_request": {}} + ) + + mock.app = { + "outbound_message_router": async_mock.CoroutineMock(), + "request_context": self.mock_context, + } + + with async_mock.patch.object( + test_module, "PresentationManager", autospec=True + ) as mock_presentation_manager, async_mock.patch.object( + test_module, "PresentationPreview", autospec=True + ) as mock_presentation_proposal, async_mock.patch.object( + test_module, "PresentationRequest", autospec=True + ) as mock_presentation_request, async_mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_decorator, async_mock.patch.object( + test_module, "V10PresentationExchange", autospec=True + ) as mock_presentation_exchange: + + mock_attach_decorator.from_indy_dict = async_mock.MagicMock( + return_value=mock_attach_decorator + ) + + mock_presentation_exchange.serialize = async_mock.MagicMock() + mock_presentation_exchange.serialize.return_value = {"hello": "world"} + + test_module.web.json_response = async_mock.CoroutineMock() + + mock_presentation_manager.return_value.create_exchange_for_request = async_mock.CoroutineMock( + return_value=mock_presentation_exchange + ) + + await test_module.presentation_exchange_create_request(mock) + + test_module.web.json_response.assert_called_once_with( + mock_presentation_exchange.serialize.return_value + ) + async def test_presentation_exchange_send_free_request(self): mock = async_mock.MagicMock() mock.json = async_mock.CoroutineMock( return_value={ "connection_id": "dummy", "comment": "dummy", - "proof_request": {} + "proof_request": {}, } ) @@ -303,16 +337,12 @@ async def test_presentation_exchange_send_free_request(self): ) mock_presentation_exchange.serialize = async_mock.MagicMock() - mock_presentation_exchange.serialize.return_value = ( - {"hello": "world"} - ) + mock_presentation_exchange.serialize.return_value = {"hello": "world"} test_module.web.json_response = async_mock.CoroutineMock() - mock_presentation_manager.return_value.create_exchange_for_request = ( - async_mock.CoroutineMock( - return_value=mock_presentation_exchange - ) + mock_presentation_manager.return_value.create_exchange_for_request = async_mock.CoroutineMock( + return_value=mock_presentation_exchange ) await test_module.presentation_exchange_send_free_request(mock) @@ -323,11 +353,7 @@ async def test_presentation_exchange_send_free_request(self): async def test_presentation_exchange_send_free_request_not_found(self): mock = async_mock.MagicMock() - mock.json = async_mock.CoroutineMock( - return_value={ - "connection_id": "dummy", - } - ) + mock.json = async_mock.CoroutineMock(return_value={"connection_id": "dummy"}) mock.app = { "outbound_message_router": async_mock.CoroutineMock(), @@ -346,10 +372,7 @@ async def test_presentation_exchange_send_free_request_not_found(self): async def test_presentation_exchange_send_free_request_not_ready(self): mock = async_mock.MagicMock() mock.json = async_mock.CoroutineMock( - return_value={ - "connection_id": "dummy", - "proof_request": {} - } + return_value={"connection_id": "dummy", "proof_request": {}} ) mock.app = { @@ -405,9 +428,7 @@ async def test_presentation_exchange_send_bound_request(self): return_value=mock_presentation_exchange ) mock_presentation_exchange.serialize = async_mock.MagicMock() - mock_presentation_exchange.serialize.return_value = ( - {"hello": "world"} - ) + mock_presentation_exchange.serialize.return_value = {"hello": "world"} mock_connection_record.is_ready = True mock_connection_record.retrieve_by_id = async_mock.CoroutineMock( @@ -416,10 +437,8 @@ async def test_presentation_exchange_send_bound_request(self): test_module.web.json_response = async_mock.CoroutineMock() - mock_presentation_manager.return_value.create_bound_request = ( - async_mock.CoroutineMock( - return_value=(mock_presentation_exchange, mock_presentation_request) - ) + mock_presentation_manager.return_value.create_bound_request = async_mock.CoroutineMock( + return_value=(mock_presentation_exchange, mock_presentation_request) ) await test_module.presentation_exchange_send_bound_request(mock) @@ -535,9 +554,7 @@ async def test_presentation_exchange_send_presentation(self): ) mock_presentation_exchange.connection_id = "dummy" mock_presentation_exchange.serialize = async_mock.MagicMock() - mock_presentation_exchange.serialize.return_value = ( - {"hello": "world"} - ) + mock_presentation_exchange.serialize.return_value = {"hello": "world"} mock_connection_record.is_ready = True mock_connection_record.retrieve_by_id = async_mock.CoroutineMock( @@ -546,10 +563,8 @@ async def test_presentation_exchange_send_presentation(self): test_module.web.json_response = async_mock.CoroutineMock() - mock_presentation_manager.return_value.create_presentation = ( - async_mock.CoroutineMock( - return_value=(mock_presentation_exchange, async_mock.MagicMock()) - ) + mock_presentation_manager.return_value.create_presentation = async_mock.CoroutineMock( + return_value=(mock_presentation_exchange, async_mock.MagicMock()) ) await test_module.presentation_exchange_send_presentation(mock) @@ -619,9 +634,7 @@ async def test_presentation_exchange_verify_presentation(self): mock = async_mock.MagicMock() mock.match_info = {"pres_ex_id": "dummy"} - mock.app = { - "request_context": self.mock_context, - } + mock.app = {"request_context": self.mock_context} with async_mock.patch.object( test_module, "ConnectionRecord", autospec=True @@ -639,9 +652,7 @@ async def test_presentation_exchange_verify_presentation(self): ) mock_presentation_exchange.connection_id = "dummy" mock_presentation_exchange.serialize = async_mock.MagicMock() - mock_presentation_exchange.serialize.return_value = ( - {"hello": "world"} - ) + mock_presentation_exchange.serialize.return_value = {"hello": "world"} mock_connection_record.is_ready = True mock_connection_record.retrieve_by_id = async_mock.CoroutineMock( @@ -650,10 +661,8 @@ async def test_presentation_exchange_verify_presentation(self): test_module.web.json_response = async_mock.CoroutineMock() - mock_presentation_manager.return_value.verify_presentation = ( - async_mock.CoroutineMock( - return_value=mock_presentation_exchange - ) + mock_presentation_manager.return_value.verify_presentation = async_mock.CoroutineMock( + return_value=mock_presentation_exchange ) await test_module.presentation_exchange_verify_presentation(mock) @@ -666,9 +675,7 @@ async def test_presentation_exchange_verify_presentation_not_found(self): mock = async_mock.MagicMock() mock.match_info = {"pres_ex_id": "dummy"} - mock.app = { - "request_context": self.mock_context, - } + mock.app = {"request_context": self.mock_context} with async_mock.patch.object( test_module, "ConnectionRecord", autospec=True @@ -692,9 +699,7 @@ async def test_presentation_exchange_verify_presentation_not_ready(self): mock = async_mock.MagicMock() mock.match_info = {"pres_ex_id": "dummy"} - mock.app = { - "request_context": self.mock_context, - } + mock.app = {"request_context": self.mock_context} with async_mock.patch.object( test_module, "ConnectionRecord", autospec=True @@ -719,9 +724,7 @@ async def test_presentation_exchange_remove(self): mock = async_mock.MagicMock() mock.match_info = {"pres_ex_id": "dummy"} - mock.app = { - "request_context": "context", - } + mock.app = {"request_context": "context"} with async_mock.patch.object( test_module, "V10PresentationExchange", autospec=True @@ -743,9 +746,7 @@ async def test_presentation_exchange_remove_not_found(self): mock_request = async_mock.MagicMock() mock_request.json = async_mock.CoroutineMock() - mock_request.app = { - "request_context": "context", - } + mock_request.app = {"request_context": "context"} with async_mock.patch.object( test_module, "V10PresentationExchange", autospec=True