Skip to content

Commit

Permalink
✨ Deduplicate save_exchange_record
Browse files Browse the repository at this point in the history
Defines a helper class `SaveExchangeRecordField`, with `auto_remove` property, and is extended where needed
  • Loading branch information
ff137 committed Nov 21, 2024
1 parent 1995cc8 commit e9615f5
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 47 deletions.
10 changes: 2 additions & 8 deletions app/models/issuer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from aries_cloudcontroller import LDProofVCDetail, TxnOrPublishRevocationsResult
from pydantic import BaseModel, Field, ValidationInfo, field_validator, model_validator

from app.util.save_exchange_record import SaveExchangeRecordField
from shared.exceptions import CloudApiValueError


Expand All @@ -18,17 +19,10 @@ class IndyCredential(BaseModel):
attributes: Dict[str, str]


class CredentialBase(BaseModel):
class CredentialBase(BaseModel, SaveExchangeRecordField):
type: CredentialType = CredentialType.INDY
indy_credential_detail: Optional[IndyCredential] = None
ld_credential_detail: Optional[LDProofVCDetail] = None
save_exchange_record: Optional[bool] = Field(
default=None,
description=(
"Whether the credential exchange record should be saved on completion. "
"Default is to use the setting configured for the wallet"
),
)

@field_validator("indy_credential_detail", mode="before")
@classmethod
Expand Down
22 changes: 6 additions & 16 deletions app/models/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from aries_cloudcontroller import IndyProofRequest as AcaPyIndyProofRequest
from pydantic import BaseModel, Field, ValidationInfo, field_validator, model_validator

from app.util.save_exchange_record import SaveExchangeRecordField
from shared.exceptions import CloudApiValueError


Expand Down Expand Up @@ -62,14 +63,10 @@ class ProofRequestMetadata(BaseModel):
comment: Optional[str] = None


class CreateProofRequest(ProofRequestBase, ProofRequestMetadata):
save_exchange_record: Optional[bool] = Field(
default=None,
description=(
"Whether the presentation exchange record should be saved on completion. "
"Default is to use the setting configured for the wallet"
),
)
class CreateProofRequest(
ProofRequestBase, ProofRequestMetadata, SaveExchangeRecordField
):
pass


class SendProofRequest(CreateProofRequest):
Expand All @@ -80,17 +77,10 @@ class ProofId(BaseModel):
proof_id: str


class AcceptProofRequest(ProofId):
class AcceptProofRequest(ProofId, SaveExchangeRecordField):
type: ProofRequestType = ProofRequestType.INDY
indy_presentation_spec: Optional[IndyPresSpec] = None
dif_presentation_spec: Optional[DIFPresSpec] = None
save_exchange_record: Optional[bool] = Field(
default=None,
description=(
"Whether the presentation exchange record should be saved on completion. "
"Default is to use the setting configured for the wallet"
),
)

@field_validator("indy_presentation_spec", mode="before")
@classmethod
Expand Down
12 changes: 2 additions & 10 deletions app/services/issuer/acapy_issuer_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,9 @@ async def send_credential(
f"Unsupported credential type: {credential.type}", status_code=501
)

auto_remove = None
if credential.save_exchange_record is not None:
auto_remove = not credential.save_exchange_record

bound_logger.debug("Issue v2 credential (automated)")
request_body = V20CredExFree(
auto_remove=auto_remove,
auto_remove=credential.auto_remove,
connection_id=credential.connection_id,
filter=cred_filter,
credential_preview=credential_preview,
Expand Down Expand Up @@ -115,13 +111,9 @@ async def create_offer(
f"Unsupported credential type: {credential.type}", status_code=501
)

auto_remove = None
if credential.save_exchange_record is not None:
auto_remove = not credential.save_exchange_record

bound_logger.debug("Creating v2 credential offer")
request_body = V20CredOfferConnFreeRequest(
auto_remove=auto_remove,
auto_remove=credential.auto_remove,
credential_preview=credential_preview,
filter=cred_filter,
)
Expand Down
16 changes: 3 additions & 13 deletions app/services/verifier/acapy_verifier_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,10 @@ async def create_proof_request(
status_code=501,
)

auto_remove = None
if create_proof_request.save_exchange_record is not None:
auto_remove = not create_proof_request.save_exchange_record

bound_logger = logger.bind(body=create_proof_request)
bound_logger.debug("Creating v2 proof request")
request_body = V20PresCreateRequestRequest(
auto_remove=auto_remove,
auto_remove=create_proof_request.auto_remove,
presentation_request=presentation_request,
auto_verify=True,
comment=create_proof_request.comment,
Expand Down Expand Up @@ -97,13 +93,9 @@ async def send_proof_request(
status_code=501,
)

auto_remove = None
if send_proof_request.save_exchange_record is not None:
auto_remove = not send_proof_request.save_exchange_record

bound_logger = logger.bind(body=send_proof_request)
request_body = V20PresSendRequestRequest(
auto_remove=auto_remove,
auto_remove=send_proof_request.auto_remove,
connection_id=send_proof_request.connection_id,
presentation_request=presentation_request,
auto_verify=True,
Expand All @@ -129,9 +121,7 @@ async def send_proof_request(
async def accept_proof_request(
cls, controller: AcaPyClient, accept_proof_request: AcceptProofRequest
) -> PresentationExchange:
auto_remove = None
if accept_proof_request.save_exchange_record is not None:
auto_remove = not accept_proof_request.save_exchange_record
auto_remove = accept_proof_request.auto_remove

if accept_proof_request.type == ProofRequestType.INDY:
presentation_spec = V20PresSpecByFormatRequest(
Expand Down
22 changes: 22 additions & 0 deletions app/util/save_exchange_record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import Optional

from pydantic import BaseModel, Field

save_exchange_record_field = Field(
default=None,
description=(
"Controls exchange record retention after exchange is complete. None uses "
"wallet default (typically to delete), true forces save, false forces delete."
),
)


class SaveExchangeRecordField(BaseModel):
save_exchange_record: Optional[bool] = save_exchange_record_field

@property
def auto_remove(self) -> Optional[bool]:
"""Returns the inverse of save_exchange_record if set, otherwise None."""
if self.save_exchange_record is None:
return None
return not self.save_exchange_record

0 comments on commit e9615f5

Please sign in to comment.