Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend --preserve-exchange-records to include Presentation Exchange. #2352

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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