From afab757b1229379fd6b5760875c13ab25abd83ae Mon Sep 17 00:00:00 2001 From: Albin Antony Date: Fri, 24 May 2024 10:22:29 +0530 Subject: [PATCH] Fix #13: Support creating disclosure mapping from credential definition --- sdjwt/sdjwt.py | 21 +++++++ sdjwt/tests/test_sdjwt.py | 117 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/sdjwt/sdjwt.py b/sdjwt/sdjwt.py index b211c79..0eb5731 100644 --- a/sdjwt/sdjwt.py +++ b/sdjwt/sdjwt.py @@ -594,3 +594,24 @@ def iterate_mapping(obj, path): iterate_mapping(credential_subject, []) return credential_subject["credentialSubject"] + + +def _create_disclosure_mapping_from_credential_definition(data): + result = {} + if isinstance(data, dict): + for key, value in data.items(): + if isinstance(value, dict) and "limitDisclosure" in value and value["limitDisclosure"] is True: + # Direct property with limitDisclosure + result[key] = {k: v for k, v in value.items() if k == "limitDisclosure"} + elif isinstance(value, dict) and "properties" in value: + # Nested property, need to go deeper + nested_result = _create_disclosure_mapping_from_credential_definition(value["properties"]) + if nested_result: + result[key] = nested_result + return result + +def create_disclosure_mapping_from_credential_definition(credential_definition): + data = credential_definition["properties"] + disclosure_mapping = {} + disclosure_mapping["credentialSubject"] = _create_disclosure_mapping_from_credential_definition(data) + return disclosure_mapping diff --git a/sdjwt/tests/test_sdjwt.py b/sdjwt/tests/test_sdjwt.py index 52d6e34..a1fbf9b 100644 --- a/sdjwt/tests/test_sdjwt.py +++ b/sdjwt/tests/test_sdjwt.py @@ -8,6 +8,7 @@ create_w3c_vc_sd_jwt, get_all_disclosures_with_sd_from_token, decode_credential_sd_to_credential_subject, + create_disclosure_mapping_from_credential_definition, ) import jwt import json @@ -390,6 +391,122 @@ async def test_decode_credential_sd_to_credential_subject(self): "Expected credential subject attribute `section6` doesn't match with result", ) + async def test_create_disclosure_mapping_from_credential_definition(self): + # Case 1 + credential_definition_1 = { + "type": "object", + "properties": { + "identifier": { + "type": "object", + "limitDisclosure": False, + "properties": { + "id": { + "type": "object", + "limitDisclosure": True, + "properties": { + "legalName": { + "type": "string", + "limitDisclosure": False, + }, + }, + } + }, + }, + "legalName": {"type": "string", "limitDisclosure": False}, + "legalAddress": {"type": "string", "limitDisclosure": True}, + }, + "required": ["identifier", "legalName", "legalAddress"], + "additionalProperties": False, + } + expected_disclosure_mapping_1 = { + "credentialSubject": { + "identifier": {"id": {"limitDisclosure": True}}, + "legalAddress": {"limitDisclosure": True}, + } + } + + # Case 2 + + credential_definition_2 = { + "type": "object", + "properties": { + "identifier": { + "type": "object", + "limitDisclosure": True, + "properties": { + "id": { + "type": "object", + "limitDisclosure": True, + "properties": { + "legalName": { + "type": "string", + "limitDisclosure": False, + }, + }, + } + }, + }, + "legalName": {"type": "string", "limitDisclosure": True}, + "legalAddress": {"type": "string", "limitDisclosure": False}, + }, + "required": ["identifier", "legalName", "legalAddress"], + "additionalProperties": False, + } + expected_disclosure_mapping_2 = { + "credentialSubject": { + "identifier": {"limitDisclosure": True}, + "legalName": {"limitDisclosure": True}, + } + } + + # Tescase for case 1 + disclosure_mapping_1 = create_disclosure_mapping_from_credential_definition( + credential_definition_1 + ) + + condition_1 = ( + disclosure_mapping_1["credentialSubject"]['identifier']["id"][ + "limitDisclosure" + ] + == expected_disclosure_mapping_1["credentialSubject"]["identifier"]["id"][ + "limitDisclosure" + ] + ) + self.assert_( + condition_1, + "Expected desclosure mapping for id field doesn't match", + ) + condition_2 = ( + disclosure_mapping_1["credentialSubject"]["legalAddress"] + == expected_disclosure_mapping_1["credentialSubject"]["legalAddress"] + ) + self.assert_( + condition_2, + "Expected desclosure mapping for legalAddress field doesn't match", + ) + + # Tescase for case 2 + disclosure_mapping_2 = create_disclosure_mapping_from_credential_definition( + credential_definition_2 + ) + + condition_1 = ( + disclosure_mapping_2["credentialSubject"]["identifier"] + == expected_disclosure_mapping_2["credentialSubject"]["identifier"] + ) + self.assert_( + condition_1, + "Expected desclosure mapping for identifier field doesn't match", + ) + condition_2 = ( + disclosure_mapping_2["credentialSubject"]["legalName"] + == expected_disclosure_mapping_2["credentialSubject"]["legalName"] + ) + self.assert_( + condition_2, + "Expected desclosure mapping for legalName field doesn't match", + ) + if __name__ == "__main__": unittest.main()