Skip to content

Commit 708f9d3

Browse files
authored
Merge branch 'main' into feature/event-bus
2 parents 39f2c9a + 8a60d1a commit 708f9d3

File tree

21 files changed

+1298
-347
lines changed

21 files changed

+1298
-347
lines changed

aries_cloudagent/messaging/credential_definitions/routes.py

+51-17
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
from .util import CredDefQueryStringSchema, CRED_DEF_TAGS, CRED_DEF_SENT_RECORD_TYPE
3737

3838

39+
from ..valid import UUIDFour
40+
from ...connections.models.conn_record import ConnRecord
41+
from ...storage.error import StorageNotFoundError
42+
from ..models.base import BaseModelError
43+
44+
3945
class CredentialDefinitionSendRequestSchema(OpenAPISchema):
4046
"""Request schema for schema send request."""
4147

@@ -132,21 +138,20 @@ class CredDefIdMatchInfoSchema(OpenAPISchema):
132138
)
133139

134140

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

138-
auto_endorse = fields.Boolean(
139-
description="Auto-endorse Transaction",
144+
create_transaction_for_endorser = fields.Boolean(
145+
description="Create Transaction For Endorser's signature",
140146
required=False,
141147
)
142148

143149

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

147-
endorser_did = fields.Str(
148-
description="Endorser DID",
149-
required=False,
153+
conn_id = fields.Str(
154+
description="Connection identifier", required=False, example=UUIDFour.EXAMPLE
150155
)
151156

152157

@@ -155,8 +160,8 @@ class EndorserDIDOptionSchema(OpenAPISchema):
155160
summary="Sends a credential definition to the ledger",
156161
)
157162
@request_schema(CredentialDefinitionSendRequestSchema())
158-
@querystring_schema(AutoEndorseOptionSchema())
159-
@querystring_schema(EndorserDIDOptionSchema())
163+
@querystring_schema(CreateTransactionForEndorserOptionSchema())
164+
@querystring_schema(ConnIdMatchInfoSchema())
160165
@response_schema(TxnOrCredentialDefinitionSendResultSchema(), 200, description="")
161166
async def credential_definitions_send_credential_definition(request: web.BaseRequest):
162167
"""
@@ -170,8 +175,12 @@ async def credential_definitions_send_credential_definition(request: web.BaseReq
170175
171176
"""
172177
context: AdminRequestContext = request["context"]
173-
auto_endorse = json.loads(request.query.get("auto_endorse", "true"))
174-
endorser_did = request.query.get("endorser_did", None)
178+
create_transaction_for_endorser = json.loads(
179+
request.query.get("create_transaction_for_endorser", "false")
180+
)
181+
write_ledger = not create_transaction_for_endorser
182+
endorser_did = None
183+
connection_id = request.query.get("conn_id")
175184

176185
body = await request.json()
177186

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

192+
if not write_ledger:
193+
194+
try:
195+
async with context.session() as session:
196+
connection_record = await ConnRecord.retrieve_by_id(
197+
session, connection_id
198+
)
199+
except StorageNotFoundError as err:
200+
raise web.HTTPNotFound(reason=err.roll_up) from err
201+
except BaseModelError as err:
202+
raise web.HTTPBadRequest(reason=err.roll_up) from err
203+
204+
session = await context.session()
205+
endorser_info = await connection_record.metadata_get(session, "endorser_info")
206+
if not endorser_info:
207+
raise web.HTTPForbidden(
208+
reason="Endorser Info is not set up in "
209+
"connection metadata for this connection record"
210+
)
211+
if "endorser_did" not in endorser_info.keys():
212+
raise web.HTTPForbidden(
213+
reason=' "endorser_did" is not set in "endorser_info"'
214+
" in connection metadata for this connection record"
215+
)
216+
endorser_did = endorser_info["endorser_did"]
217+
183218
ledger = context.inject(BaseLedger, required=False)
184219
if not ledger:
185220
reason = "No ledger available"
@@ -197,7 +232,7 @@ async def credential_definitions_send_credential_definition(request: web.BaseReq
197232
signature_type=None,
198233
tag=tag,
199234
support_revocation=support_revocation,
200-
write_ledger=auto_endorse,
235+
write_ledger=write_ledger,
201236
endorser_did=endorser_did,
202237
)
203238
)
@@ -258,7 +293,7 @@ async def credential_definitions_send_credential_definition(request: web.BaseReq
258293
except RevocationError as e:
259294
raise web.HTTPBadRequest(reason=e.message) from e
260295

261-
if auto_endorse:
296+
if not create_transaction_for_endorser:
262297
return web.json_response({"sent": {"credential_definition_id": cred_def_id}})
263298

264299
else:
@@ -267,8 +302,7 @@ async def credential_definitions_send_credential_definition(request: web.BaseReq
267302
transaction_mgr = TransactionManager(session)
268303
try:
269304
transaction = await transaction_mgr.create_record(
270-
messages_attach=cred_def["signed_txn"],
271-
expires_time="1597708800",
305+
messages_attach=cred_def["signed_txn"], connection_id=connection_id
272306
)
273307
except StorageError as err:
274308
raise web.HTTPBadRequest(reason=err.roll_up) from err

aries_cloudagent/messaging/credential_definitions/tests/test_routes.py

+151-11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from ....tails.base import BaseTailsServer
1010

1111
from .. import routes as test_module
12+
from ....connections.models.conn_record import ConnRecord
1213

1314

1415
SCHEMA_ID = "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0"
@@ -67,7 +68,7 @@ async def test_send_credential_definition(self):
6768
}
6869
)
6970

70-
self.request.query = {"auto_endorse": "true"}
71+
self.request.query = {"create_transaction_for_endorser": "false"}
7172

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

92-
self.request.query = {"auto_endorse": "true"}
93+
self.request.query = {"create_transaction_for_endorser": "false"}
9394

9495
self.context.profile.settings.set_value(
9596
"tails_server_base_url", "http://1.2.3.4:8222"
@@ -133,7 +134,7 @@ async def test_send_credential_definition_revoc_no_tails_server_x(self):
133134
}
134135
)
135136

136-
self.request.query = {"auto_endorse": "true"}
137+
self.request.query = {"create_transaction_for_endorser": "false"}
137138

138139
with self.assertRaises(test_module.web.HTTPBadRequest):
139140
await test_module.credential_definitions_send_credential_definition(
@@ -149,7 +150,7 @@ async def test_send_credential_definition_revoc_no_support_x(self):
149150
}
150151
)
151152

152-
self.request.query = {"auto_endorse": "true"}
153+
self.request.query = {"create_transaction_for_endorser": "false"}
153154

154155
self.context.profile.settings.set_value(
155156
"tails_server_base_url", "http://1.2.3.4:8222"
@@ -177,7 +178,7 @@ async def test_send_credential_definition_revoc_upload_x(self):
177178
}
178179
)
179180

180-
self.request.query = {"auto_endorse": "true"}
181+
self.request.query = {"create_transaction_for_endorser": "false"}
181182

182183
self.context.profile.settings.set_value(
183184
"tails_server_base_url", "http://1.2.3.4:8222"
@@ -218,7 +219,7 @@ async def test_send_credential_definition_revoc_init_issuer_rev_reg_x(self):
218219
}
219220
)
220221

221-
self.request.query = {"auto_endorse": "true"}
222+
self.request.query = {"create_transaction_for_endorser": "false"}
222223

223224
self.context.profile.settings.set_value(
224225
"tails_server_base_url", "http://1.2.3.4:8222"
@@ -250,7 +251,7 @@ async def test_send_credential_definition_revoc_init_issuer_rev_reg_x(self):
250251
self.request
251252
)
252253

253-
async def test_send_credential_definition_no_auto_endorse(self):
254+
async def test_send_credential_definition_create_transaction_for_endorser(self):
254255
self.request.json = async_mock.CoroutineMock(
255256
return_value={
256257
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
@@ -259,9 +260,14 @@ async def test_send_credential_definition_no_auto_endorse(self):
259260
}
260261
)
261262

262-
self.request.query = {"auto_endorse": "false"}
263+
self.request.query = {
264+
"create_transaction_for_endorser": "true",
265+
"conn_id": "dummy",
266+
}
263267

264268
with async_mock.patch.object(
269+
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
270+
) as mock_conn_rec_retrieve, async_mock.patch.object(
265271
test_module, "TransactionManager", async_mock.MagicMock()
266272
) as mock_txn_mgr, async_mock.patch.object(
267273
test_module.web, "json_response", async_mock.MagicMock()
@@ -273,6 +279,14 @@ async def test_send_credential_definition_no_auto_endorse(self):
273279
)
274280
)
275281
)
282+
mock_conn_rec_retrieve.return_value = async_mock.MagicMock(
283+
metadata_get=async_mock.CoroutineMock(
284+
return_value={
285+
"endorser_did": ("did"),
286+
"endorser_name": ("name"),
287+
}
288+
)
289+
)
276290
result = (
277291
await test_module.credential_definitions_send_credential_definition(
278292
self.request
@@ -281,7 +295,9 @@ async def test_send_credential_definition_no_auto_endorse(self):
281295
assert result == mock_response.return_value
282296
mock_response.assert_called_once_with({"txn": {"...": "..."}})
283297

284-
async def test_send_credential_definition_no_auto_endorse_storage_x(self):
298+
async def test_send_credential_definition_create_transaction_for_endorser_storage_x(
299+
self,
300+
):
285301
self.request.json = async_mock.CoroutineMock(
286302
return_value={
287303
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
@@ -290,11 +306,25 @@ async def test_send_credential_definition_no_auto_endorse_storage_x(self):
290306
}
291307
)
292308

293-
self.request.query = {"auto_endorse": "false"}
309+
self.request.query = {
310+
"create_transaction_for_endorser": "true",
311+
"conn_id": "dummy",
312+
}
294313

295314
with async_mock.patch.object(
315+
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
316+
) as mock_conn_rec_retrieve, async_mock.patch.object(
296317
test_module, "TransactionManager", async_mock.MagicMock()
297318
) as mock_txn_mgr:
319+
320+
mock_conn_rec_retrieve.return_value = async_mock.MagicMock(
321+
metadata_get=async_mock.CoroutineMock(
322+
return_value={
323+
"endorser_did": ("did"),
324+
"endorser_name": ("name"),
325+
}
326+
)
327+
)
298328
mock_txn_mgr.return_value = async_mock.MagicMock(
299329
create_record=async_mock.CoroutineMock(
300330
side_effect=test_module.StorageError()
@@ -306,6 +336,116 @@ async def test_send_credential_definition_no_auto_endorse_storage_x(self):
306336
self.request
307337
)
308338

339+
async def test_send_credential_definition_create_transaction_for_endorser_not_found_x(
340+
self,
341+
):
342+
self.request.json = async_mock.CoroutineMock(
343+
return_value={
344+
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
345+
"support_revocation": False,
346+
"tag": "tag",
347+
}
348+
)
349+
350+
self.request.query = {
351+
"create_transaction_for_endorser": "true",
352+
"conn_id": "dummy",
353+
}
354+
355+
with async_mock.patch.object(
356+
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
357+
) as mock_conn_rec_retrieve:
358+
mock_conn_rec_retrieve.side_effect = test_module.StorageNotFoundError()
359+
360+
with self.assertRaises(test_module.web.HTTPNotFound):
361+
await test_module.credential_definitions_send_credential_definition(
362+
self.request
363+
)
364+
365+
async def test_send_credential_definition_create_transaction_for_endorser_base_model_x(
366+
self,
367+
):
368+
self.request.json = async_mock.CoroutineMock(
369+
return_value={
370+
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
371+
"support_revocation": False,
372+
"tag": "tag",
373+
}
374+
)
375+
376+
self.request.query = {
377+
"create_transaction_for_endorser": "true",
378+
"conn_id": "dummy",
379+
}
380+
381+
with async_mock.patch.object(
382+
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
383+
) as mock_conn_rec_retrieve:
384+
mock_conn_rec_retrieve.side_effect = test_module.BaseModelError()
385+
386+
with self.assertRaises(test_module.web.HTTPBadRequest):
387+
await test_module.credential_definitions_send_credential_definition(
388+
self.request
389+
)
390+
391+
async def test_send_credential_definition_create_transaction_for_endorser_no_endorser_info_x(
392+
self,
393+
):
394+
self.request.json = async_mock.CoroutineMock(
395+
return_value={
396+
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
397+
"support_revocation": False,
398+
"tag": "tag",
399+
}
400+
)
401+
402+
self.request.query = {
403+
"create_transaction_for_endorser": "true",
404+
"conn_id": "dummy",
405+
}
406+
407+
with async_mock.patch.object(
408+
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
409+
) as mock_conn_rec_retrieve:
410+
mock_conn_rec_retrieve.return_value = async_mock.MagicMock(
411+
metadata_get=async_mock.CoroutineMock(return_value=None)
412+
)
413+
with self.assertRaises(test_module.web.HTTPForbidden):
414+
await test_module.credential_definitions_send_credential_definition(
415+
self.request
416+
)
417+
418+
async def test_send_credential_definition_create_transaction_for_endorser_no_endorser_did_x(
419+
self,
420+
):
421+
self.request.json = async_mock.CoroutineMock(
422+
return_value={
423+
"schema_id": "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0",
424+
"support_revocation": False,
425+
"tag": "tag",
426+
}
427+
)
428+
429+
self.request.query = {
430+
"create_transaction_for_endorser": "true",
431+
"conn_id": "dummy",
432+
}
433+
434+
with async_mock.patch.object(
435+
ConnRecord, "retrieve_by_id", async_mock.CoroutineMock()
436+
) as mock_conn_rec_retrieve:
437+
mock_conn_rec_retrieve.return_value = async_mock.MagicMock(
438+
metadata_get=async_mock.CoroutineMock(
439+
return_value={
440+
"endorser_name": ("name"),
441+
}
442+
)
443+
)
444+
with self.assertRaises(test_module.web.HTTPForbidden):
445+
await test_module.credential_definitions_send_credential_definition(
446+
self.request
447+
)
448+
309449
async def test_send_credential_definition_no_ledger(self):
310450
self.request.json = async_mock.CoroutineMock(
311451
return_value={
@@ -331,7 +471,7 @@ async def test_send_credential_definition_ledger_x(self):
331471
}
332472
)
333473

334-
self.request.query = {"auto_endorse": "true"}
474+
self.request.query = {"create_transaction_for_endorser": "false"}
335475

336476
self.ledger.__aenter__ = async_mock.CoroutineMock(
337477
side_effect=test_module.LedgerError("oops")

0 commit comments

Comments
 (0)