Skip to content

Commit

Permalink
Merge pull request #2352 from usingtechnology/issue-2126-preserve-pre…
Browse files Browse the repository at this point in the history
…s-ex

Extend `--preserve-exchange-records` to include Presentation Exchange.
  • Loading branch information
usingtechnology authored Jul 26, 2023
2 parents 879196e + a804481 commit 3e97d82
Show file tree
Hide file tree
Showing 15 changed files with 233 additions and 7 deletions.
3 changes: 2 additions & 1 deletion aries_cloudagent/config/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,8 @@ def add_arguments(self, parser: ArgumentParser):
"--preserve-exchange-records",
action="store_true",
env_var="ACAPY_PRESERVE_EXCHANGE_RECORDS",
help="Keep credential exchange records after exchange has completed.",
help="Keep credential and presentation exchange records after "
"exchange has completed.",
)
parser.add_argument(
"--emit-new-didcomm-prefix",
Expand Down
25 changes: 25 additions & 0 deletions aries_cloudagent/protocols/issue_credential/v1_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,19 @@ class CredExIdMatchInfoSchema(OpenAPISchema):
)


class V10CredentialExchangeAutoRemoveRequestSchema(OpenAPISchema):
"""Request Schema for overriding default preserve exchange records setting."""

auto_remove = fields.Bool(
description=(
"Whether to remove the credential exchange record on completion "
"(overrides --preserve-exchange-records configuration setting)"
),
required=False,
default=False,
)


@docs(
tags=["issue-credential v1.0"],
summary="Fetch all credential exchange records",
Expand Down Expand Up @@ -955,6 +968,7 @@ async def credential_exchange_send_bound_offer(request: web.BaseRequest):
summary="Send issuer a credential request",
)
@match_info_schema(CredExIdMatchInfoSchema())
@request_schema(V10CredentialExchangeAutoRemoveRequestSchema())
@response_schema(V10CredentialExchangeSchema(), 200, description="")
async def credential_exchange_send_request(request: web.BaseRequest):
"""
Expand All @@ -975,6 +989,14 @@ async def credential_exchange_send_request(request: web.BaseRequest):

credential_exchange_id = request.match_info["cred_ex_id"]

try:
body = await request.json() or {}
auto_remove = body.get(
"auto_remove", not profile.settings.get("preserve_exchange_records")
)
except JSONDecodeError:
auto_remove = not profile.settings.get("preserve_exchange_records")

cred_ex_record = None
connection_record = None

Expand Down Expand Up @@ -1013,6 +1035,9 @@ async def credential_exchange_send_request(request: web.BaseRequest):
# Transform recipient key into did
holder_did = default_did_from_verkey(oob_record.our_recipient_key)

# assign the auto_remove flag from above...
cred_ex_record.auto_remove = auto_remove

try:
credential_manager = CredentialManager(profile)
(
Expand Down
15 changes: 15 additions & 0 deletions aries_cloudagent/protocols/issue_credential/v2_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,14 @@ class V20CredRequestRequestSchema(OpenAPISchema):
allow_none=True,
example="did:key:ahsdkjahsdkjhaskjdhakjshdkajhsdkjahs",
)
auto_remove = fields.Bool(
description=(
"Whether to remove the credential exchange record on completion "
"(overrides --preserve-exchange-records configuration setting)"
),
required=False,
default=False,
)


class V20CredIssueRequestSchema(OpenAPISchema):
Expand Down Expand Up @@ -1258,8 +1266,12 @@ async def credential_exchange_send_bound_request(request: web.BaseRequest):
try:
body = await request.json() or {}
holder_did = body.get("holder_did")
auto_remove = body.get(
"auto_remove", not profile.settings.get("preserve_exchange_records")
)
except JSONDecodeError:
holder_did = None
auto_remove = not profile.settings.get("preserve_exchange_records")

cred_ex_id = request.match_info["cred_ex_id"]

Expand Down Expand Up @@ -1301,6 +1313,9 @@ async def credential_exchange_send_bound_request(request: web.BaseRequest):
# Transform recipient key into did
holder_did = default_did_from_verkey(oob_record.our_recipient_key)

# assign the auto_remove flag from above...
cred_ex_record.auto_remove = auto_remove

cred_manager = V20CredManager(profile)
cred_ex_record, cred_request_message = await cred_manager.create_request(
cred_ex_record,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ async def handle(self, context: RequestContext, responder: BaseResponder):
"debug.auto_respond_presentation_request"
),
trace=(context.message._trace is not None),
auto_remove=not profile.settings.get("preserve_exchange_records"),
)

presentation_exchange_record = await presentation_manager.receive_request(
Expand Down
23 changes: 22 additions & 1 deletion aries_cloudagent/protocols/present_proof/v1_0/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ async def create_exchange_for_proposal(
connection_id: str,
presentation_proposal_message: PresentationProposal,
auto_present: bool = None,
auto_remove: bool = None,
):
"""
Create a presentation exchange record for input presentation proposal.
Expand All @@ -60,11 +61,14 @@ async def create_exchange_for_proposal(
to exchange record
auto_present: whether to present proof upon receiving proof request
(default to configuration setting)
auto_remove: whether to remove this presentation exchange upon completion
Returns:
Presentation exchange record, created
"""
if auto_remove is None:
auto_remove = not self._profile.settings.get("preserve_exchange_records")
presentation_exchange_record = V10PresentationExchange(
connection_id=connection_id,
thread_id=presentation_proposal_message._thread_id,
Expand All @@ -74,6 +78,7 @@ async def create_exchange_for_proposal(
presentation_proposal_dict=presentation_proposal_message,
auto_present=auto_present,
trace=(presentation_proposal_message._trace is not None),
auto_remove=auto_remove,
)
async with self._profile.session() as session:
await presentation_exchange_record.save(
Expand All @@ -100,6 +105,7 @@ async def receive_proposal(
state=V10PresentationExchange.STATE_PROPOSAL_RECEIVED,
presentation_proposal_dict=message,
trace=(message._trace is not None),
auto_remove=not self._profile.settings.get("preserve_exchange_records"),
)
async with self._profile.session() as session:
await presentation_exchange_record.save(
Expand Down Expand Up @@ -170,6 +176,7 @@ async def create_exchange_for_request(
connection_id: str,
presentation_request_message: PresentationRequest,
auto_verify: bool = None,
auto_remove: bool = None,
):
"""
Create a presentation exchange record for input presentation request.
Expand All @@ -178,11 +185,14 @@ async def create_exchange_for_request(
connection_id: connection identifier
presentation_request_message: presentation request to use in creating
exchange record, extracting indy proof request and thread id
auto_verify: whether to auto-verify presentation exchange
auto_remove: whether to remove this presentation exchange upon completion
Returns:
Presentation exchange record, updated
"""
if auto_remove is None:
auto_remove = not self._profile.settings.get("preserve_exchange_records")
presentation_exchange_record = V10PresentationExchange(
connection_id=connection_id,
thread_id=presentation_request_message._thread_id,
Expand All @@ -193,6 +203,7 @@ async def create_exchange_for_request(
presentation_request_dict=presentation_request_message,
auto_verify=auto_verify,
trace=(presentation_request_message._trace is not None),
auto_remove=auto_remove,
)
async with self._profile.session() as session:
await presentation_exchange_record.save(
Expand Down Expand Up @@ -491,6 +502,11 @@ async def send_presentation_ack(
# connection_id can be none in case of connectionless
connection_id=presentation_exchange_record.connection_id,
)

# all done: delete
if presentation_exchange_record.auto_remove:
async with self._profile.session() as session:
await presentation_exchange_record.delete_record(session)
else:
LOGGER.warning(
"Configuration has no BaseResponder: cannot ack presentation on %s",
Expand Down Expand Up @@ -530,6 +546,11 @@ async def receive_presentation_ack(
session, reason="receive presentation ack"
)

# all done: delete
if presentation_exchange_record.auto_remove:
async with self._profile.session() as session:
await presentation_exchange_record.delete_record(session)

return presentation_exchange_record

async def receive_problem_report(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def __init__(
auto_verify: bool = False,
error_msg: str = None,
trace: bool = False, # backward compat: BaseRecord.from_storage()
auto_remove: bool = False,
**kwargs,
):
"""Initialize a new PresentationExchange."""
Expand All @@ -102,6 +103,7 @@ def __init__(
self.auto_present = auto_present
self.auto_verify = auto_verify
self.error_msg = error_msg
self.auto_remove = auto_remove

@property
def presentation_exchange_id(self) -> str:
Expand Down Expand Up @@ -240,6 +242,7 @@ def record_value(self) -> Mapping:
"verified",
"verified_msgs",
"trace",
"auto_remove",
)
},
**{
Expand Down Expand Up @@ -344,3 +347,11 @@ class Meta:
error_msg = fields.Str(
required=False, description="Error message", example="Invalid structure"
)
auto_remove = fields.Bool(
required=False,
default=True,
description=(
"Verifier choice to remove this presentation exchange record when complete"
),
example=False,
)
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ async def test_record(self):
connection_id="conn_id",
thread_id="thid",
auto_present=True,
auto_remove=True,
)
record.presentation_proposal_dict = presentation_proposal # cover setter
record.presentation_request_dict = None # cover setter
Expand All @@ -115,6 +116,7 @@ async def test_record(self):
"verified": None,
"verified_msgs": None,
"trace": False,
"auto_remove": True,
}

bx_record = BasexRecordImpl()
Expand Down
53 changes: 52 additions & 1 deletion aries_cloudagent/protocols/present_proof/v1_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ class V10PresentationExchangeListSchema(OpenAPISchema):
)


class V10PresentationSendRequestSchema(IndyPresSpecSchema):
"""Request schema for sending a presentation."""

auto_remove = fields.Bool(
description=(
"Whether to remove the presentation exchange record on completion "
"(overrides --preserve-exchange-records configuration setting)"
),
required=False,
default=False,
)


class V10PresentationProposalRequestSchema(AdminAPIMessageTracingSchema):
"""Request schema for sending a presentation proposal admin message."""

Expand All @@ -118,6 +131,14 @@ class V10PresentationProposalRequestSchema(AdminAPIMessageTracingSchema):
required=False,
default=False,
)
auto_remove = fields.Bool(
description=(
"Whether to remove the presentation exchange record on completion "
"(overrides --preserve-exchange-records configuration setting)"
),
required=False,
default=False,
)
trace = fields.Bool(
description="Whether to trace event (default false)",
required=False,
Expand All @@ -135,6 +156,14 @@ class V10PresentationCreateRequestRequestSchema(AdminAPIMessageTracingSchema):
required=False,
example=False,
)
auto_remove = fields.Bool(
description=(
"Whether to remove the presentation exchange record on completion "
"(overrides --preserve-exchange-records configuration setting)"
),
required=False,
default=False,
)
trace = fields.Bool(
description="Whether to trace event (default false)",
required=False,
Expand All @@ -160,6 +189,14 @@ class V10PresentationSendRequestToProposalSchema(AdminAPIMessageTracingSchema):
required=False,
example=False,
)
auto_remove = fields.Bool(
description=(
"Whether to remove the presentation exchange record on completion "
"(overrides --preserve-exchange-records configuration setting)"
),
required=False,
default=False,
)
trace = fields.Bool(
description="Whether to trace event (default false)",
required=False,
Expand Down Expand Up @@ -424,6 +461,7 @@ async def presentation_exchange_send_proposal(request: web.BaseRequest):
auto_present = body.get(
"auto_present", context.settings.get("debug.auto_respond_presentation_request")
)
auto_remove = body.get("auto_remove")

presentation_manager = PresentationManager(profile)
pres_ex_record = None
Expand All @@ -432,6 +470,7 @@ async def presentation_exchange_send_proposal(request: web.BaseRequest):
connection_id=connection_id,
presentation_proposal_message=presentation_proposal_message,
auto_present=auto_present,
auto_remove=auto_remove,
)
result = pres_ex_record.serialize()
except (BaseModelError, StorageError) as err:
Expand Down Expand Up @@ -497,6 +536,7 @@ async def presentation_exchange_create_request(request: web.BaseRequest):
auto_verify = body.get(
"auto_verify", context.settings.get("debug.auto_verify_presentation")
)
auto_remove = body.get("auto_remove")
trace_msg = body.get("trace")
presentation_request_message.assign_trace_decorator(
context.settings,
Expand All @@ -510,6 +550,7 @@ async def presentation_exchange_create_request(request: web.BaseRequest):
connection_id=None,
presentation_request_message=presentation_request_message,
auto_verify=auto_verify,
auto_remove=auto_remove,
)
result = pres_ex_record.serialize()
except (BaseModelError, StorageError) as err:
Expand Down Expand Up @@ -586,6 +627,7 @@ async def presentation_exchange_send_free_request(request: web.BaseRequest):
auto_verify = body.get(
"auto_verify", context.settings.get("debug.auto_verify_presentation")
)
auto_remove = body.get("auto_remove")

pres_ex_record = None
try:
Expand All @@ -594,6 +636,7 @@ async def presentation_exchange_send_free_request(request: web.BaseRequest):
connection_id=connection_id,
presentation_request_message=presentation_request_message,
auto_verify=auto_verify,
auto_remove=auto_remove,
)
result = pres_ex_record.serialize()
except (BaseModelError, StorageError) as err:
Expand Down Expand Up @@ -672,6 +715,8 @@ async def presentation_exchange_send_bound_request(request: web.BaseRequest):
pres_ex_record.auto_verify = body.get(
"auto_verify", context.settings.get("debug.auto_verify_presentation")
)
pres_ex_record.auto_remove = body.get("auto_remove")

try:
presentation_manager = PresentationManager(profile)
(
Expand Down Expand Up @@ -711,7 +756,7 @@ async def presentation_exchange_send_bound_request(request: web.BaseRequest):

@docs(tags=["present-proof v1.0"], summary="Sends a proof presentation")
@match_info_schema(V10PresExIdMatchInfoSchema())
@request_schema(IndyPresSpecSchema())
@request_schema(V10PresentationSendRequestSchema())
@response_schema(V10PresentationExchangeSchema(), description="")
async def presentation_exchange_send_presentation(request: web.BaseRequest):
"""
Expand Down Expand Up @@ -750,6 +795,12 @@ async def presentation_exchange_send_presentation(request: web.BaseRequest):
)
)

auto_remove = body.get("auto_remove")
if auto_remove is None:
auto_remove = not profile.settings.get("preserve_exchange_records")

pres_ex_record.auto_remove = auto_remove

# Fetch connection if exchange has record
connection_record = None
if pres_ex_record.connection_id:
Expand Down
Loading

0 comments on commit 3e97d82

Please sign in to comment.