Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ async def emit_event(self, session: ProfileSession, payload: Optional[Any] = Non
if not session.profile.settings.get("debug.webhooks"):
payload = V20PresExRecordWebhook(**payload)
payload = payload.__dict__
elif by_format := payload.get("by_format"):
# Issue #3802: remove legacy fields only when represented in by_format
for key in ("pres_proposal", "pres_request", "pres"):
if key in by_format:
payload.pop(key, None)

await session.emit_event(topic, payload)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
from ......messaging.models.base_record import BaseExchangeRecord, BaseExchangeSchema
from ......tests import mock
from ......utils.testing import create_test_profile
from ...message_types import ATTACHMENT_FORMAT, PRES_20_PROPOSAL
from ...message_types import ATTACHMENT_FORMAT, PRES_20, PRES_20_PROPOSAL, PRES_20_REQUEST
from ...messages.pres import V20Pres
from ...messages.pres_format import V20PresFormat
from ...messages.pres_proposal import V20PresProposal
from ...messages.pres_request import V20PresRequest
from .. import pres_exchange as test_module
from ..pres_exchange import V20PresExRecord

Expand Down Expand Up @@ -52,6 +54,16 @@
}
},
}
INDY_PROOF = {
"proof": {"proofs": []},
"requested_proof": {
"revealed_attrs": {},
"self_attested_attrs": {},
"unrevealed_attrs": {},
"predicates": {},
},
"identifiers": [],
}


class BasexRecordImpl(BaseExchangeRecord):
Expand Down Expand Up @@ -134,3 +146,71 @@ async def test_save_error_state(self):
mock_save.side_effect = test_module.StorageError()
await record.save_error_state(session, reason="testing")
mock_log_exc.assert_called_once()

# BUG #3802: ensure webhook payloads omit legacy pres_* fields when by_format exists
async def test_emit_event_strips_legacy_pres_fields(self):
settings = {
"wallet.type": "askar",
"auto_provision": True,
"wallet.key": "5BngFuBpS4wjFfVFCtPqoix3ZXG2XR8XJ7qosUzMak7R",
"wallet.key_derivation_method": "RAW",
"debug.webhooks": True,
}
self.profile = await create_test_profile(settings=settings)
pres_request = V20PresRequest(
formats=[
V20PresFormat(
attach_id="indy",
format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][
V20PresFormat.Format.INDY.api
],
)
],
request_presentations_attach=[
AttachDecorator.data_base64(mapping=INDY_PROOF_REQ, ident="indy")
],
)
pres_proposal = V20PresProposal(
formats=[
V20PresFormat(
attach_id="indy",
format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][
V20PresFormat.Format.INDY.api
],
)
],
proposals_attach=[
AttachDecorator.data_base64(mapping=INDY_PROOF_REQ, ident="indy")
],
)
pres = V20Pres(
formats=[
V20PresFormat(
attach_id="indy",
format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api],
)
],
presentations_attach=[
AttachDecorator.data_base64(mapping=INDY_PROOF, ident="indy")
],
)
record = V20PresExRecord(
pres_ex_id="pxid",
thread_id="thid",
connection_id="conn_id",
initiator="init",
role="role",
state=V20PresExRecord.STATE_PRESENTATION_RECEIVED,
pres_proposal=pres_proposal,
pres_request=pres_request,
pres=pres,
)

async with self.profile.session() as session:
session.emit_event = mock.CoroutineMock()
await record.emit_event(session)

payload = session.emit_event.call_args.args[1]
assert "by_format" in payload
for key in ("pres", "pres_proposal", "pres_request"):
assert key not in payload and key in payload["by_format"]
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@
didexchange,
indy_anoncred_credential_artifacts,
indy_issue_credential_v2,
indy_present_proof_v2,
params,
)
from aiohttp import ClientSession
from examples.util import _presentation_request_payload, indy_present_proof_v2

ALICE = getenv("ALICE", "http://alice:3001")
BOB = getenv("BOB", "http://bob:3001")


def summary(presentation: V20PresExRecord) -> str:
"""Summarize a presentation exchange record."""
request = presentation.pres_request
request = _presentation_request_payload(presentation)
return "Summary: " + json.dumps(
{
"state": presentation.state,
"verified": presentation.verified,
"presentation_request": request.dict(by_alias=True) if request else None,
"presentation_request": request,
},
indent=2,
sort_keys=True,
Expand Down
71 changes: 38 additions & 33 deletions scenarios/examples/json_ld/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@
from uuid import uuid4

from acapy_controller import Controller
from acapy_controller.controller import ControllerError
from acapy_controller.logging import logging_to_stdout, pause_for_input, section
from acapy_controller.models import DIDResult, V20PresExRecord
from acapy_controller.protocols import (
didexchange,
jsonld_issue_credential,
jsonld_present_proof,
params,
)
from aiohttp import ClientSession
from examples.util import jsonld_present_proof_v2

ALICE = getenv("ALICE", "http://alice:3001")
BOB = getenv("BOB", "http://bob:3001")
Expand Down Expand Up @@ -159,7 +160,7 @@ async def main():
pause_for_input()

with section("Present example ED25519 credential"):
alice_pres_ex, bob_pres_ex = await jsonld_present_proof(
alice_pres_ex, bob_pres_ex = await jsonld_present_proof_v2(
alice,
bob,
alice_conn.connection_id,
Expand Down Expand Up @@ -207,7 +208,7 @@ async def main():
domain="test-degree",
)
with section("Presentation summary", character="-"):
print(presentation_summary(alice_pres_ex.into(V20PresExRecord)))
print(presentation_summary(alice_pres_ex))

pause_for_input()

Expand Down Expand Up @@ -241,7 +242,7 @@ async def main():
pause_for_input()

with section("Present example P256 credential"):
alice_pres_ex, bob_pres_ex = await jsonld_present_proof(
alice_pres_ex, bob_pres_ex = await jsonld_present_proof_v2(
alice,
bob,
alice_conn.connection_id,
Expand Down Expand Up @@ -294,7 +295,7 @@ async def main():
domain="test-degree",
)
with section("Presentation summary", character="-"):
print(presentation_summary(alice_pres_ex.into(V20PresExRecord)))
print(presentation_summary(alice_pres_ex))

pause_for_input()

Expand Down Expand Up @@ -327,7 +328,7 @@ async def main():
pause_for_input()

with section("Present ED25519 quick context credential"):
alice_pres_ex, bob_pres_ex = await jsonld_present_proof(
alice_pres_ex, bob_pres_ex = await jsonld_present_proof_v2(
alice,
bob,
alice_conn.connection_id,
Expand Down Expand Up @@ -370,42 +371,46 @@ async def main():
domain="test-degree",
)
with section("Presentation summary", character="-"):
print(presentation_summary(alice_pres_ex.into(V20PresExRecord)))
print(presentation_summary(alice_pres_ex))

pause_for_input()

with section("Issue BBS+ Credential"):
issuer_cred_ex, holder_cred_ex = await jsonld_issue_credential(
alice,
bob,
alice_conn.connection_id,
bob_conn.connection_id,
credential={
"@context": [
"https://www.w3.org/2018/credentials/v1",
{
"ex": "https://example.com/examples#",
"Employment": "ex:Employment",
"dateHired": "ex:dateHired",
"clearance": "ex:clearance",
try:
issuer_cred_ex, holder_cred_ex = await jsonld_issue_credential(
alice,
bob,
alice_conn.connection_id,
bob_conn.connection_id,
credential={
"@context": [
"https://www.w3.org/2018/credentials/v1",
{
"ex": "https://example.com/examples#",
"Employment": "ex:Employment",
"dateHired": "ex:dateHired",
"clearance": "ex:clearance",
},
],
"type": ["VerifiableCredential", "Employment"],
"issuer": bls_alice_did,
"issuanceDate": str(date.today()),
"credentialSubject": {
"id": bls_bob_did,
"dateHired": str(date.today()),
"clearance": 1,
},
],
"type": ["VerifiableCredential", "Employment"],
"issuer": bls_alice_did,
"issuanceDate": str(date.today()),
"credentialSubject": {
"id": bls_bob_did,
"dateHired": str(date.today()),
"clearance": 1,
},
},
options={"proofType": "BbsBlsSignature2020"},
)
options={"proofType": "BbsBlsSignature2020"},
)
except ControllerError as err:
print(f"Skipping BBS+ flow due to runtime capability/error: {err}")
return

pause_for_input()

with section("Present BBS+ Credential with SD"):
alice_pres_ex, bob_pres_ex = await jsonld_present_proof(
alice_pres_ex, bob_pres_ex = await jsonld_present_proof_v2(
alice,
bob,
alice_conn.connection_id,
Expand Down Expand Up @@ -447,7 +452,7 @@ async def main():
domain="building-access",
)
with section("Presentation summary", character="-"):
print(presentation_summary(alice_pres_ex.into(V20PresExRecord)))
print(presentation_summary(alice_pres_ex))


if __name__ == "__main__":
Expand Down
5 changes: 3 additions & 2 deletions scenarios/examples/kanon_issuance_and_presentation/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from examples.util import (
CredDefResultAnonCreds,
SchemaResultAnonCreds,
_presentation_request_payload,
anoncreds_issue_credential_v2,
anoncreds_present_proof_v2,
)
Expand All @@ -31,12 +32,12 @@

def summary(presentation: V20PresExRecord) -> str:
"""Summarize a presentation exchange record."""
request = presentation.pres_request
request = _presentation_request_payload(presentation)
return "Summary: " + json.dumps(
{
"state": presentation.state,
"verified": presentation.verified,
"presentation_request": request.dict(by_alias=True) if request else None,
"presentation_request": request,
},
indent=2,
sort_keys=True,
Expand Down
2 changes: 1 addition & 1 deletion scenarios/examples/multitenancy/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
didexchange,
indy_anoncred_credential_artifacts,
indy_issue_credential_v2,
indy_present_proof_v2,
params,
)
from aiohttp import ClientSession
from examples.util import indy_present_proof_v2

AGENCY = getenv("AGENCY", "http://agency:3001")

Expand Down
6 changes: 3 additions & 3 deletions scenarios/examples/presenting_revoked_credential/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@
didexchange,
indy_anoncred_credential_artifacts,
indy_issue_credential_v2,
indy_present_proof_v2,
params,
)
from aiohttp import ClientSession
from examples.util import _presentation_request_payload, indy_present_proof_v2

ALICE = getenv("ALICE", "http://alice:3001")
BOB = getenv("BOB", "http://bob:3001")


def summary(presentation: V20PresExRecord) -> str:
"""Summarize a presentation exchange record."""
request = presentation.pres_request
request = _presentation_request_payload(presentation)
return "Summary: " + json.dumps(
{
"state": presentation.state,
"verified": presentation.verified,
"presentation_request": request.dict(by_alias=True) if request else None,
"presentation_request": request,
},
indent=2,
sort_keys=True,
Expand Down
3 changes: 1 addition & 2 deletions scenarios/examples/simple_restart/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
indy_anoncred_credential_artifacts,
indy_anoncred_onboard,
indy_issue_credential_v2,
indy_present_proof_v2,
)
from examples.util import wait_until_healthy
from examples.util import indy_present_proof_v2, wait_until_healthy

import docker

Expand Down
Loading