diff --git a/aries_cloudagent/protocols/issue_credential/v2_0/routes.py b/aries_cloudagent/protocols/issue_credential/v2_0/routes.py index b7d98758b0..e8ee7ca41a 100644 --- a/aries_cloudagent/protocols/issue_credential/v2_0/routes.py +++ b/aries_cloudagent/protocols/issue_credential/v2_0/routes.py @@ -396,19 +396,31 @@ def _formats_filters(filt_spec: Mapping) -> Mapping: ) -async def _get_result_with_details( +async def _get_attached_credentials( profile: Profile, cred_ex_record: V20CredExRecord ) -> Mapping: - """Get credential exchange result with detail records.""" - result = {"cred_ex_record": cred_ex_record.serialize()} + """Fetch the detail records attached to a credential exchange.""" + result = {} for fmt in V20CredFormat.Format: detail_record = await fmt.handler(profile).get_detail_record( cred_ex_record.cred_ex_id ) + if detail_record: + result[fmt.api] = detail_record + + return result - result[fmt.api] = detail_record.serialize() if detail_record else None +def _format_result_with_details( + cred_ex_record: V20CredExRecord, details: Mapping +) -> Mapping: + """Get credential exchange result with detail records.""" + result = {"cred_ex_record": cred_ex_record.serialize()} + for fmt in V20CredFormat.Format: + ident = fmt.api + detail_record = details.get(ident) + result[ident] = detail_record.serialize() if detail_record else None return result @@ -450,7 +462,8 @@ async def credential_exchange_list(request: web.BaseRequest): results = [] for cxr in cred_ex_records: - result = await _get_result_with_details(profile, cxr) + details = await _get_attached_credentials(profile, cxr) + result = _format_result_with_details(cxr, details) results.append(result) except (StorageError, BaseModelError) as err: @@ -486,7 +499,7 @@ async def credential_exchange_retrieve(request: web.BaseRequest): async with profile.session() as session: cred_ex_record = await V20CredExRecord.retrieve_by_id(session, cred_ex_id) - result = await _get_result_with_details(context.profile, cred_ex_record) + details = await _get_attached_credentials(profile, cred_ex_record) except StorageNotFoundError as err: # no such cred ex record: not protocol error, user fat-fingered id @@ -501,6 +514,7 @@ async def credential_exchange_retrieve(request: web.BaseRequest): outbound_handler, ) + result = _format_result_with_details(cred_ex_record, details) return web.json_response(result) @@ -1321,8 +1335,9 @@ async def credential_exchange_issue(request: web.BaseRequest): connection_id = cred_ex_record.connection_id conn_record = await ConnRecord.retrieve_by_id(session, connection_id) - if not conn_record.is_ready: - raise web.HTTPForbidden(reason=f"Connection {connection_id} not ready") + + if not conn_record.is_ready: + raise web.HTTPForbidden(reason=f"Connection {connection_id} not ready") cred_manager = V20CredManager(profile) (cred_ex_record, cred_issue_message) = await cred_manager.issue_credential( @@ -1330,7 +1345,8 @@ async def credential_exchange_issue(request: web.BaseRequest): comment=comment, ) - result = await _get_result_with_details(profile, cred_ex_record) + details = await _get_attached_credentials(profile, cred_ex_record) + result = _format_result_with_details(cred_ex_record, details) except ( BaseModelError, @@ -1433,14 +1449,16 @@ async def credential_exchange_store(request: web.BaseRequest): ) try: + # fetch these early, before potential removal + details = await _get_attached_credentials(profile, cred_ex_record) + + # the record may be auto-removed here ( cred_ex_record, cred_ack_message, ) = await cred_manager.send_cred_ack(cred_ex_record) - # We first need to retrieve the the cred_ex_record with detail record - # as the record may be auto removed - result = await _get_result_with_details(profile, cred_ex_record) + result = _format_result_with_details(cred_ex_record, details) except ( BaseModelError,