diff --git a/aries_cloudagent/admin/tests/test_admin_server.py b/aries_cloudagent/admin/tests/test_admin_server.py index 9f2ff6a080..11d8bc5366 100644 --- a/aries_cloudagent/admin/tests/test_admin_server.py +++ b/aries_cloudagent/admin/tests/test_admin_server.py @@ -1,13 +1,12 @@ import json +import pytest from aiohttp import ClientSession, DummyCookieJar, TCPConnector, web from aiohttp.test_utils import unused_port -import pytest from asynctest import TestCase as AsyncTestCase from asynctest import mock as async_mock -from .. import server as test_module from ...config.default_context import DefaultContextBuilder from ...config.injection_context import InjectionContext from ...core.event_bus import Event @@ -16,6 +15,8 @@ from ...transport.outbound.message import OutboundMessage from ...utils.stats import Collector from ...utils.task_queue import TaskQueue + +from .. import server as test_module from ..server import AdminServer, AdminSetupError diff --git a/aries_cloudagent/connections/models/tests/test_conn_record.py b/aries_cloudagent/connections/models/tests/test_conn_record.py index 40a8019e7a..7d5a813ed8 100644 --- a/aries_cloudagent/connections/models/tests/test_conn_record.py +++ b/aries_cloudagent/connections/models/tests/test_conn_record.py @@ -251,6 +251,32 @@ async def test_attach_retrieve_request(self): retrieved = await record.retrieve_request(self.session) assert isinstance(retrieved, ConnectionRequest) + async def test_attach_request_abstain_on_alien_deco(self): + record = ConnRecord( + my_did=self.test_did, + state=ConnRecord.State.INVITATION.rfc23, + ) + connection_id = await record.save(self.session) + + req = ConnectionRequest( + connection=ConnectionDetail( + did=self.test_did, did_doc=DIDDoc(self.test_did) + ), + label="abc123", + ) + ser = req.serialize() + ser["~alien"] = [{"nickname": "profile-image", "data": {"links": ["face.png"]}}] + alien_req = ConnectionRequest.deserialize(ser) + await record.attach_request(self.session, alien_req) + alien_ser = alien_req.serialize() + assert "~alien" in alien_ser + + ser["~alien"] = None + alien_req = ConnectionRequest.deserialize(ser) + await record.attach_request(self.session, alien_req) + alien_ser = alien_req.serialize() + assert "~alien" not in alien_ser + async def test_ser_rfc23_state_present(self): record = ConnRecord( state=ConnRecord.State.INVITATION, diff --git a/aries_cloudagent/messaging/decorators/base.py b/aries_cloudagent/messaging/decorators/base.py index d254b5dc6e..abebad4a91 100644 --- a/aries_cloudagent/messaging/decorators/base.py +++ b/aries_cloudagent/messaging/decorators/base.py @@ -10,7 +10,6 @@ from ..models.base import BaseModel - DECORATOR_PREFIX = "~" @@ -92,8 +91,6 @@ def remove_model(self, key: str): def __setitem__(self, key, value): """Add a decorator.""" - if not isinstance(value, (bool, int, str, float, dict, OrderedDict, BaseModel)): - raise ValueError(f"Unsupported decorator value: {value}") self.load_decorator(key, value) def load_decorator(self, key: str, value, serialized=False): diff --git a/aries_cloudagent/messaging/decorators/tests/test_base.py b/aries_cloudagent/messaging/decorators/tests/test_base.py index 937818f30a..1da1343cc7 100644 --- a/aries_cloudagent/messaging/decorators/tests/test_base.py +++ b/aries_cloudagent/messaging/decorators/tests/test_base.py @@ -11,6 +11,7 @@ from ....messaging.models.base import BaseModel, BaseModelSchema +from .. import base as test_module from ..base import BaseDecoratorSet, DECORATOR_PREFIX @@ -67,8 +68,10 @@ def test_base_decorator_set(self): deco_set.remove_model("c") assert "c" not in deco_set.models - with pytest.raises(ValueError): - deco_set["a"] = None + deco_set["a"] = None # + deco_set.load_decorator("a", None) + assert "a" not in deco_set + deco_set["a"] = {"score": 23} deco_set["a"] = SampleDecorator(23) deco_set.load_decorator("a", None) diff --git a/aries_cloudagent/messaging/jsonld/create_verify_data.py b/aries_cloudagent/messaging/jsonld/create_verify_data.py index abe89b5534..b13a7f0076 100644 --- a/aries_cloudagent/messaging/jsonld/create_verify_data.py +++ b/aries_cloudagent/messaging/jsonld/create_verify_data.py @@ -49,8 +49,8 @@ def _created_at(): return stamp.strftime("%Y-%m-%dT%H:%M:%SZ") -def create_verify_data(data, signature_options): - """Encapsulate the process of constructing the string used during sign and verify.""" +def create_verify_data(data, signature_options, document_loader=None): + """Encapsulate process of constructing string used during sign and verify.""" type_ = signature_options.get("type", "Ed25519Signature2018") if type_ and type_ != "Ed25519Signature2018": @@ -66,9 +66,19 @@ def create_verify_data(data, signature_options): ) signature_options["created"] = signature_options.get("created", _created_at()) - [expanded] = jsonld.expand(data) + [expanded] = jsonld.expand( + data, + options={ + **{opt: document_loader for opt in ["documentLoader"] if document_loader} + }, + ) framed = jsonld.compact( - expanded, "https://w3id.org/security/v2", {"skipExpansion": True} + expanded, + "https://w3id.org/security/v2", + options={ + "skipExpansion": True, + **{opt: document_loader for opt in ["documentLoader"] if document_loader}, + }, ) # Detect any dropped attributes during the expand/contract step. diff --git a/aries_cloudagent/messaging/jsonld/credential.py b/aries_cloudagent/messaging/jsonld/credential.py index 858d962ac0..6ffaf14e78 100644 --- a/aries_cloudagent/messaging/jsonld/credential.py +++ b/aries_cloudagent/messaging/jsonld/credential.py @@ -2,10 +2,12 @@ import json -from ...wallet.util import b64_to_bytes, b64_to_str, bytes_to_b64, str_to_b64 -from ...wallet.key_type import KeyType from ...did.did_key import DIDKey +from ...vc.ld_proofs import DocumentLoader from ...wallet.base import BaseWallet +from ...wallet.key_type import KeyType +from ...wallet.util import b64_to_bytes, b64_to_str, bytes_to_b64, str_to_b64 + from .create_verify_data import create_verify_data from .error import BadJWSHeaderError @@ -83,7 +85,12 @@ async def jws_verify(session, verify_data, signature, public_key): async def sign_credential(session, credential, signature_options, verkey): """Sign Credential.""" - framed, verify_data_hex_string = create_verify_data(credential, signature_options) + document_loader = session.profile.inject(DocumentLoader, required=False) + framed, verify_data_hex_string = create_verify_data( + credential, + signature_options, + document_loader, + ) verify_data_bytes = bytes.fromhex(verify_data_hex_string) jws = await jws_sign(session, verify_data_bytes, verkey) return {**credential, "proof": {**signature_options, "jws": jws}} @@ -92,7 +99,12 @@ async def sign_credential(session, credential, signature_options, verkey): async def verify_credential(session, doc, verkey): """Verify credential.""" - framed, verify_data_hex_string = create_verify_data(doc, doc["proof"]) + document_loader = session.profile.inject(DocumentLoader, required=False) + framed, verify_data_hex_string = create_verify_data( + doc, + doc["proof"], + document_loader, + ) verify_data_bytes = bytes.fromhex(verify_data_hex_string) valid = await jws_verify(session, verify_data_bytes, framed["proof"]["jws"], verkey) return valid diff --git a/aries_cloudagent/messaging/jsonld/tests/__init__.py b/aries_cloudagent/messaging/jsonld/tests/__init__.py index 18291f2850..caed66d51c 100644 --- a/aries_cloudagent/messaging/jsonld/tests/__init__.py +++ b/aries_cloudagent/messaging/jsonld/tests/__init__.py @@ -1,6 +1,7 @@ TEST_SEED = "testseed000000000000000000000001" TEST_DID = "55GkHamhTU1ZbTbV2ab9DE" TEST_VERKEY = "3Dn1SJNPaCXcvvJvSbsFWP2xaCjMom3can8CQNhWrTRx" + TEST_SIGN_OBJ0 = { "doc": { "@context": [ @@ -33,7 +34,7 @@ "https://www.w3.org/2018/credentials/v1", "https://www.w3.org/2018/credentials/examples/v1", ], - "id": "http://example.gov/credentials/3732", + "id": "http://example.gov/credentials/3735", "type": ["VerifiableCredential", "UniversityDegreeCredential"], "issuer": "did:example:123", "issuanceDate": "2020-03-16T22:37:26.544Z", @@ -123,7 +124,7 @@ "issuer": "did:example:28394728934792387", "name": "European Health Insurance Card", "description": "Example of a European Health Insurance Card", - "attribute2drop": "drop it like its a tot.", + "attribute2drop": "drop it like it's hot", "issuanceDate": "2021-01-01T12:19:52Z", "expirationDate": "2029-12-03T12:19:52Z", "institutionID": "09999 - GE KVG", @@ -164,7 +165,7 @@ "credentialSubject": { "id": "did:example:b34ca6cd37bbf23", "type": ["EuropeanHealthInsuranceHolder", "Person"], - "attribute2drop": "drop it like its a tot.", + "attribute2drop": "drop it like it's hot", "familyName": "Muster", "giveName": "Maria", "birthDate": "1958-07-17", @@ -218,7 +219,7 @@ ], "proof": { "verificationMethod": "did:example:123#z6MksHh7qHWvybLg5QTPPdG2DgEjjduBDArV9EF9mRiRzMBN", - "attribute2drop": "drop it like its a tot.", + "attribute2drop": "drop it like it's hot", "proofPurpose": "assertionMethod", "created": "2020-04-02T18:48:36Z", "domain": "example.com", @@ -353,7 +354,7 @@ TEST_VERIFY_OBJ2, ] TEST_VERIFY_ERROR = { - "verkey": ("5yKdnU7ToTjAoRNDzfuzVTfWBH38qyhE1b9xh4v8JaWF"), + "verkey": "5yKdnU7ToTjAoRNDzfuzVTfWBH38qyhE1b9xh4v8JaWF", "doc": { "@context": [ "https://www.w3.org/2018/credentials/v1", @@ -388,3 +389,41 @@ }, }, } +TEST_EURO_HEALTH = { + "@context": { + "@version": 1.1, + "@protected": True, + "name": "http://schema.org/name", + "description": "http://schema.org/description", + "EuropeanHealthInsuranceCard": { + "@id": "https://essif-lab.pages.grnet.gr/interoperability/eidas-generic-use-case#EuropeanHealthInsuranceCard", + "@context": { + "@version": 1.1, + "@protected": True, + "id": "@id", + "type": "@type", + "ehic": "https://essif-lab.pages.grnet.gr/interoperability/eidas-generic-use-case#", + "description": "http://schema.org/description", + "name": "http://schema.org/name", + "institutionID": "ehic:identificationNumberOfTheInstitution", + "cardNo": "ehic:identificationNumberOfTheCard", + "personalID": "ehic:personalIdentificationNumber", + }, + }, + "EuropeanHealthInsuranceHolder": { + "@id": "https://essif-lab.pages.grnet.gr/interoperability/eidas-generic-use-case#EuropeanHealthInsuranceHolder", + "@context": { + "@version": 1.1, + "@protected": True, + "schema": "http://schema.org/", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "id": "@id", + "type": "@type", + "birthDate": {"@id": "schema:birthDate", "@type": "xsd:dateTime"}, + "familyName": "schema:familyName", + "givenName": "schema:givenName", + }, + }, + "Person": "http://schema.org/Person", + } +} diff --git a/aries_cloudagent/messaging/jsonld/tests/document_loader.py b/aries_cloudagent/messaging/jsonld/tests/document_loader.py new file mode 100644 index 0000000000..327448a0c2 --- /dev/null +++ b/aries_cloudagent/messaging/jsonld/tests/document_loader.py @@ -0,0 +1,63 @@ +from ....vc.tests.contexts import ( + CITIZENSHIP_V1, + CREDENTIALS_V1, + EXAMPLES_V1, + ODRL, + SCHEMA_ORG, + SECURITY_V1, + SECURITY_V2, +) + +from . import ( + TEST_EURO_HEALTH, + TEST_SIGN_OBJ0, + TEST_SIGN_OBJ1, + TEST_SIGN_OBJ2, + TEST_VALIDATE_ERROR_OBJ2, + TEST_VERIFY_ERROR, + TEST_VERIFY_OBJ0, + TEST_VERIFY_OBJ1, + TEST_VERIFY_OBJ2, +) + +DOCUMENTS = { + TEST_SIGN_OBJ0["doc"]["id"]: TEST_SIGN_OBJ0["doc"], + TEST_SIGN_OBJ1["doc"]["id"]: TEST_SIGN_OBJ1["doc"], + TEST_VERIFY_ERROR["doc"]["id"]: TEST_VERIFY_ERROR["doc"], + TEST_VERIFY_OBJ0["doc"]["id"]: TEST_VERIFY_OBJ0["doc"], + TEST_VERIFY_OBJ1["doc"]["id"]: TEST_VERIFY_OBJ1["doc"], + "https://w3id.org/citizenship/v1": CITIZENSHIP_V1, + "https://www.w3.org/2018/credentials/v1": CREDENTIALS_V1, + "https://www.w3.org/2018/credentials/examples/v1": EXAMPLES_V1, + "https://www.w3.org/ns/odrl.jsonld": ODRL, + "http://schema.org/": SCHEMA_ORG, + "https://w3id.org/security/v1": SECURITY_V1, + "https://w3id.org/security/v2": SECURITY_V2, + ( + "https://essif-lab.pages.grnet.gr/interoperability/" + "eidas-generic-use-case/contexts/ehic-v1.jsonld" + ): TEST_EURO_HEALTH, +} + + +def custom_document_loader(url: str, options: dict): + # Check if full url (with fragments is in document map) + if url in DOCUMENTS: + return { + "contentType": "application/ld+json", + "contextUrl": None, + "document": DOCUMENTS[url], + "documentUrl": url, + } + + # Otherwise look if it is present without fragment + without_fragment = url.split("#")[0] + if without_fragment in DOCUMENTS: + return { + "contentType": "application/ld+json", + "contextUrl": None, + "document": DOCUMENTS[without_fragment], + "documentUrl": url, + } + + raise Exception(f"No custom context support for {url}") diff --git a/aries_cloudagent/messaging/jsonld/tests/test_credential.py b/aries_cloudagent/messaging/jsonld/tests/test_credential.py index 127b0e5b0a..297d5a3b0e 100644 --- a/aries_cloudagent/messaging/jsonld/tests/test_credential.py +++ b/aries_cloudagent/messaging/jsonld/tests/test_credential.py @@ -2,21 +2,24 @@ import asyncio import json +import pytest + from itertools import cycle -import pytest -from asynctest import TestCase as AsyncTestCase -from asynctest import mock as async_mock +from asynctest import mock as async_mock, TestCase as AsyncTestCase from ....admin.request_context import AdminRequestContext from ....core.in_memory import InMemoryProfile +from ....vc.ld_proofs import DocumentLoader from ....wallet.base import BaseWallet from ....wallet.in_memory import InMemoryWallet from ....wallet.key_type import KeyType + from .. import credential as test_module from ..create_verify_data import DroppedAttributeError from ..credential import did_key, sign_credential, verify_credential from ..error import BadJWSHeaderError, SignatureTypeError + from . import ( TEST_SEED, TEST_SIGN_ERROR_OBJS, @@ -26,6 +29,7 @@ TEST_VERIFY_OBJS, TEST_VERKEY, ) +from .document_loader import custom_document_loader class TestCredential(AsyncTestCase): @@ -53,96 +57,74 @@ async def test_verify_jws_header(self): ) -@pytest.fixture(scope="module") -def event_loop(): - loop = asyncio.get_event_loop() - yield loop - loop.close() - - -@pytest.fixture(scope="module") -async def wallet(): - profile = InMemoryProfile.test_profile() - wallet = InMemoryWallet(profile) - await wallet.create_signing_key(KeyType.ED25519, TEST_SEED) - yield wallet - - -@pytest.fixture(scope="module") -async def mock_session(wallet): - session_inject = {BaseWallet: wallet} - context = AdminRequestContext.test_context(session_inject) - session = await context.session() - yield session - - -@pytest.mark.parametrize("input", TEST_VERIFY_OBJS) -@pytest.mark.asyncio -async def test_verify_credential(input, mock_session): - result = await verify_credential( - mock_session, input.get("doc"), input.get("verkey") - ) - assert result - - -@pytest.mark.parametrize("input", TEST_SIGN_OBJS) -@pytest.mark.asyncio -async def test_sign_credential(input, mock_session): - result = await sign_credential( - mock_session, input.get("doc"), input.get("options"), TEST_VERKEY - ) - assert "proof" in result.keys() - assert "jws" in result.get("proof", {}).keys() - +class TestOps(AsyncTestCase): + async def setUp(self): + self.wallet = InMemoryWallet(InMemoryProfile.test_profile()) + await self.wallet.create_signing_key(KeyType.ED25519, TEST_SEED) -@pytest.mark.parametrize("input", TEST_SIGN_ERROR_OBJS) -@pytest.mark.asyncio -async def test_sign_dropped_attribute_exception(input, mock_session): - with pytest.raises(DroppedAttributeError, match="attribute2drop"): - await sign_credential( - mock_session, input.get("doc"), input.get("options"), TEST_VERKEY + self.session = InMemoryProfile.test_session(bind={BaseWallet: self.wallet}) + self.profile = self.session.profile + self.context = self.profile.context + setattr( + self.profile, + "session", + async_mock.MagicMock(return_value=self.session), ) + self.context.injector.bind_instance(DocumentLoader, custom_document_loader) -@pytest.mark.asyncio -async def test_validate_dropped_attribute_exception(mock_session): - with pytest.raises(DroppedAttributeError, match="attribute2drop"): - input = TEST_VALIDATE_ERROR_OBJ2 - await verify_credential(mock_session, input["doc"], TEST_VERIFY_ERROR["verkey"]) - - -@pytest.mark.parametrize("input", TEST_SIGN_OBJS) -@pytest.mark.asyncio -async def test_signature_option_type(input, mock_session): - with pytest.raises(SignatureTypeError): - input["options"]["type"] = "Ed25519Signature2038" - await sign_credential( - mock_session, input.get("doc"), input.get("options"), TEST_VERKEY - ) - - -@pytest.mark.parametrize("input", TEST_VERIFY_OBJS) -@pytest.mark.asyncio -async def test_verify_optiion_type(input, mock_session): - with pytest.raises(SignatureTypeError): - input["doc"]["proof"]["type"] = "Ed25519Signature2038" - await verify_credential(mock_session, input.get("doc"), input.get("verkey")) - + async def test_verify_credential(self): + for input_ in TEST_VERIFY_OBJS: + assert await verify_credential( + self.session, + input_.get("doc"), + input_.get("verkey"), + ) -@pytest.mark.asyncio -async def test_Invalid_JWS_header(mock_session): - with pytest.raises(BadJWSHeaderError): - await verify_credential( - mock_session, TEST_VERIFY_ERROR.get("doc"), TEST_VERIFY_ERROR.get("verkey") - ) + async def test_sign_credential(self): + for input_ in TEST_SIGN_OBJS: + result = await sign_credential( + self.session, + input_.get("doc"), + input_.get("options"), + TEST_VERKEY, + ) + assert "proof" in result.keys() + assert "jws" in result.get("proof", {}).keys() + + async def test_sign_dropped_attribute_exception(self): + for input_ in TEST_SIGN_ERROR_OBJS: + with self.assertRaises(DroppedAttributeError) as context: + await sign_credential( + self.session, + input_.get("doc"), + input_.get("options"), + TEST_VERKEY, + ) + assert "attribute2drop" in str(context.exception) + + async def test_signature_option_type(self): + for input_ in TEST_SIGN_OBJS: + with self.assertRaises(SignatureTypeError): + input_["options"]["type"] = "Ed25519Signature2038" + await sign_credential( + self.session, + input_.get("doc"), + input_.get("options"), + TEST_VERKEY, + ) + async def test_invalid_jws_header(self): + with self.assertRaises(BadJWSHeaderError): + await verify_credential( + self.session, + TEST_VERIFY_ERROR.get("doc"), + TEST_VERIFY_ERROR.get("verkey"), + ) -@pytest.mark.parametrize( - "verkey", - ( - "3Dn1SJNPaCXcvvJvSbsFWP2xaCjMom3can8CQNhWrTRx", - "did:key:z3Dn1SJNPaCXcvvJvSbsFWP2xaCjMom3can8CQNhWrTRx", - ), -) -def test_did_key(verkey): - assert did_key(verkey).startswith("did:key:z") + async def test_did_key(self): + for verkey in ( + "3Dn1SJNPaCXcvvJvSbsFWP2xaCjMom3can8CQNhWrTRx", + "did:key:z3Dn1SJNPaCXcvvJvSbsFWP2xaCjMom3can8CQNhWrTRx", + ): + assert did_key(verkey).startswith("did:key:z") diff --git a/aries_cloudagent/messaging/jsonld/tests/test_routes.py b/aries_cloudagent/messaging/jsonld/tests/test_routes.py index 3b955d3064..1174f3eb10 100644 --- a/aries_cloudagent/messaging/jsonld/tests/test_routes.py +++ b/aries_cloudagent/messaging/jsonld/tests/test_routes.py @@ -1,8 +1,10 @@ import json +import pytest + from copy import deepcopy + from pydid.doc.service import Service -import pytest from aiohttp import web from asynctest import TestCase as AsyncTestCase from asynctest import mock as async_mock @@ -18,6 +20,7 @@ from ....resolver.tests import DOC from ....wallet.base import BaseWallet from ....wallet.error import WalletError + from .. import routes as test_module from ..error import ( BadJWSHeaderError, diff --git a/aries_cloudagent/messaging/models/base.py b/aries_cloudagent/messaging/models/base.py index 9dcaec0c7b..22b866ee15 100644 --- a/aries_cloudagent/messaging/models/base.py +++ b/aries_cloudagent/messaging/models/base.py @@ -1,7 +1,8 @@ """Base classes for Models and Schemas.""" import logging -from abc import ABC import json + +from abc import ABC from typing import Union from marshmallow import Schema, post_dump, pre_load, post_load, ValidationError, EXCLUDE diff --git a/aries_cloudagent/messaging/tests/test_agent_message.py b/aries_cloudagent/messaging/tests/test_agent_message.py index 55d4ff2e0c..4e1b87e28e 100644 --- a/aries_cloudagent/messaging/tests/test_agent_message.py +++ b/aries_cloudagent/messaging/tests/test_agent_message.py @@ -1,10 +1,11 @@ from asynctest import TestCase as AsyncTestCase + from marshmallow import EXCLUDE, fields from ...core.in_memory import InMemoryProfile from ...protocols.didcomm_prefix import DIDCommPrefix - from ...wallet.key_type import KeyType + from ..agent_message import AgentMessage, AgentMessageSchema from ..decorators.signature_decorator import SignatureDecorator from ..decorators.trace_decorator import TraceReport, TRACE_LOG_TARGET diff --git a/aries_cloudagent/protocols/issue_credential/v2_0/formats/ld_proof/tests/test_handler.py b/aries_cloudagent/protocols/issue_credential/v2_0/formats/ld_proof/tests/test_handler.py index f38cfde568..36728df5d8 100644 --- a/aries_cloudagent/protocols/issue_credential/v2_0/formats/ld_proof/tests/test_handler.py +++ b/aries_cloudagent/protocols/issue_credential/v2_0/formats/ld_proof/tests/test_handler.py @@ -14,10 +14,6 @@ from ..models.cred_detail import ( LDProofVCDetail, ) -from .......wallet.key_type import KeyType -from .......wallet.error import WalletNotFoundError -from .......wallet.did_method import DIDMethod -from .......wallet.base import BaseWallet from .......vc.ld_proofs import ( DocumentLoader, DocumentVerificationResult, @@ -28,6 +24,11 @@ ) from .......vc.ld_proofs.constants import SECURITY_CONTEXT_BBS_URL from .......vc.tests.document_loader import custom_document_loader +from .......wallet.key_type import KeyType +from .......wallet.error import WalletNotFoundError +from .......wallet.did_method import DIDMethod +from .......wallet.base import BaseWallet + from ....models.detail.ld_proof import V20CredExRecordLDProof from ....models.cred_ex_record import V20CredExRecord from ....messages.cred_proposal import V20CredProposal @@ -44,9 +45,11 @@ CRED_20_REQUEST, CRED_20_ISSUE, ) -from ..handler import LDProofCredFormatHandler + from ...handler import LOGGER, V20CredFormatError +from ..handler import LDProofCredFormatHandler + TEST_DID_SOV = "did:sov:LjgpST2rjsoxYegQDRm7EL" TEST_DID_KEY = "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" diff --git a/aries_cloudagent/resolver/default/indy.py b/aries_cloudagent/resolver/default/indy.py index f87ec71a9c..98a8fd6f39 100644 --- a/aries_cloudagent/resolver/default/indy.py +++ b/aries_cloudagent/resolver/default/indy.py @@ -2,13 +2,14 @@ Resolution is performed using the IndyLedger class. """ + from typing import Sequence from pydid import DID, DIDDocumentBuilder, VerificationSuite from ...config.injection_context import InjectionContext from ...core.profile import Profile -from ...ledger.indy import IndySdkLedger +from ...ledger.indy import IndySdkLedger, EndpointType from ...ledger.base import BaseLedger from ...ledger.error import LedgerError from ..base import BaseDIDResolver, DIDNotFound, ResolverError, ResolverType @@ -46,7 +47,7 @@ async def _resolve(self, profile: Profile, did: str) -> dict: try: async with ledger: recipient_key = await ledger.get_key_for_did(did) - endpoint = await ledger.get_endpoint_for_did(did) + endpoints = await ledger.get_all_endpoints_for_did(did) except LedgerError as err: raise DIDNotFound(f"DID {did} could not be resolved") from err @@ -57,14 +58,25 @@ async def _resolve(self, profile: Profile, did: str) -> dict: ) builder.authentication.reference(vmethod.id) builder.assertion_method.reference(vmethod.id) - if endpoint: - # TODO add priority - builder.services.add_didcomm( - ident=self.AGENT_SERVICE_TYPE, - type_=self.AGENT_SERVICE_TYPE, - endpoint=endpoint, - recipient_keys=[vmethod], - routing_keys=[], - ) + if endpoints: + for type_, endpoint in endpoints.items(): + if type_ == EndpointType.ENDPOINT.indy: + # TODO add priority + builder.services.add_didcomm( + ident=self.AGENT_SERVICE_TYPE, + type_=self.AGENT_SERVICE_TYPE, + endpoint=endpoint, + priority=1, + recipient_keys=[vmethod], + routing_keys=[], + ) + else: + # Accept all service types for now + builder.services.add( + ident=type_, + type_=type_, + endpoint=endpoint, + ) + result = builder.build() return result.serialize() diff --git a/aries_cloudagent/vc/ld_proofs/document_loader.py b/aries_cloudagent/vc/ld_proofs/document_loader.py index 514e65b075..a438fcb684 100644 --- a/aries_cloudagent/vc/ld_proofs/document_loader.py +++ b/aries_cloudagent/vc/ld_proofs/document_loader.py @@ -1,14 +1,17 @@ """JSON-LD document loader methods.""" -from pydid.did_url import DIDUrl -from pyld.documentloader import requests -from typing import Callable import asyncio import concurrent.futures -from ...resolver.did_resolver import DIDResolver +from typing import Callable + +from pydid.did_url import DIDUrl +from pyld.documentloader import requests + from ...cache.base import BaseCache from ...core.profile import Profile +from ...resolver.did_resolver import DIDResolver + from .error import LinkedDataProofException diff --git a/aries_cloudagent/vc/ld_proofs/tests/test_ld_proofs.py b/aries_cloudagent/vc/ld_proofs/tests/test_ld_proofs.py index 80c4f923a5..cf9e2b21ef 100644 --- a/aries_cloudagent/vc/ld_proofs/tests/test_ld_proofs.py +++ b/aries_cloudagent/vc/ld_proofs/tests/test_ld_proofs.py @@ -1,13 +1,14 @@ -from asynctest import TestCase +import pytest from datetime import datetime -import pytest +from asynctest import TestCase from ....wallet.key_type import KeyType from ....did.did_key import DIDKey from ....wallet.in_memory import InMemoryWallet from ....core.in_memory import InMemoryProfile + from ...ld_proofs import ( sign, Ed25519Signature2018, @@ -19,6 +20,7 @@ derive, ) from ...tests.document_loader import custom_document_loader + from .test_doc import ( DOC_DERIVED_BBS, DOC_SIGNED_BBS,