Skip to content

Commit

Permalink
Merge branch 'main' into fix/dif-claim-format-designation
Browse files Browse the repository at this point in the history
  • Loading branch information
TimoGlastra authored Jan 19, 2023
2 parents 31e10a2 + 5c9ce16 commit a276ee7
Show file tree
Hide file tree
Showing 54 changed files with 904 additions and 342 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/blackformat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ jobs:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.9"
- name: Black Code Formatter Check
uses: psf/black@stable
9 changes: 6 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ jobs:
runs-on: ubuntu-latest
if: (github.event_name == 'pull_request' && github.repository == 'hyperledger/aries-cloudagent-python') || (github.event_name != 'pull_request')

permissions:
security-events: write

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: python

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
2 changes: 1 addition & 1 deletion .github/workflows/integrationtests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
if: (github.event_name == 'pull_request' && github.repository == 'hyperledger/aries-cloudagent-python') || (github.event_name != 'pull_request')
steps:
- name: checkout-acapy
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
path: acapy
#- name: run-von-network
Expand Down
32 changes: 16 additions & 16 deletions .github/workflows/pythonpublish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.x"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
2 changes: 1 addition & 1 deletion .github/workflows/tests-indy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
${{ runner.os }}-buildx-test-
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v2

- name: Build test image
uses: docker/build-push-action@v3
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repos:
hooks:
- id: black
stages: [commit]
- repo: https://gitlab.com/pycqa/flake8
- repo: https://github.com/pycqa/flake8.git
rev: 3.9.0
hooks:
- id: flake8
Expand Down
45 changes: 45 additions & 0 deletions DIDMethods.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# DID methods in ACA-Py
Decentralized Identifiers, or DIDs, are URIs that point to documents that describe cryptographic primitives and protocols used in decentralized identity management.
DIDs include methods that describe where and how documents can be retrieved.
DID methods support specific types of keys and may or may not require the holder to specify the DID itself.

ACA-Py provides a `DIDMethods` registry holding all the DID methods supported for storage in a wallet

> :warning: Askar and InMemory are the only wallets supporting this registry.
## Registering a DID method
By default, ACA-Py supports `did:key` and `did:sov`.
Plugins can register DID additional methods to make them available to holders.
Here's a snippet adding support for `did:web` to the registry from a plugin `setup` method.

```python=
WEB = DIDMethod(
name="web",
key_types=[ED25519, BLS12381G2],
rotation=True,
holder_defined_did=HolderDefinedDid.REQUIRED # did:web is not derived from key material but from a user-provided respository name
)
async def setup(context: InjectionContext):
methods = context.inject(DIDMethods)
methods.register(WEB)
```

## Creating a DID

`POST /wallet/did/create` can be provided with parameters for any registered DID method. Here's a follow-up to the
`did:web` method example:

```json=
{
"method": "web",
"options": {
"did": "did:web:doma.in",
"key_type": "ed25519"
}
}
```

## Resolving DIDs

For specifics on how DIDs are resolved in ACA-Py, see: [DID Resolution](DIDResolution.md).
3 changes: 2 additions & 1 deletion Mediation.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

* `--open-mediation` - Instructs mediators to automatically grant all incoming mediation requests.
* `--mediator-invitation` - Receive invitation, send mediation request and set as default mediator.
* `--mediator-connections-invite` - Connect to mediator through a connection invitation. If not specified, connect using an OOB invitation.
* `--default-mediator-id` - Set pre-existing mediator as default mediator.
* `--clear-default-mediator` - Clear the stored default mediator.

Expand Down Expand Up @@ -72,4 +73,4 @@ See [Aries RFC 0211: Coordinate Mediation Protocol](https://github.com/hyperledg
## Using a Mediator

After establishing a connection with a mediator also having mediation granted, you can use that mediator id for future did_comm connections.
When creating, receiving or accepting a invitation intended to be Mediated, you provide `mediation_id` with the desired mediator id. if using a single mediator for all future connections, You can set a default mediation id. If no mediation_id is provided the default mediation id will be used instead.
When creating, receiving or accepting a invitation intended to be Mediated, you provide `mediation_id` with the desired mediator id. if using a single mediator for all future connections, You can set a default mediation id. If no mediation_id is provided the default mediation id will be used instead.
2 changes: 1 addition & 1 deletion aries_cloudagent/admin/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ async def setup_context(request: web.Request, handler):
)

server_routes = [
web.get("/", self.redirect_handler, allow_head=False),
web.get("/", self.redirect_handler, allow_head=True),
web.get("/plugins", self.plugins_handler, allow_head=False),
web.get("/status", self.status_handler, allow_head=False),
web.get("/status/config", self.config_handler, allow_head=False),
Expand Down
19 changes: 18 additions & 1 deletion aries_cloudagent/config/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,17 @@ def add_arguments(self, parser: ArgumentParser):
action="store_true",
env_var="ACAPY_PUBLIC_INVITES",
help=(
"Send invitations out, and receive connection requests, "
"Send invitations out using the public DID for the agent, "
"and receive connection requests solicited by invitations "
"which use the public DID. Default: false."
),
)
parser.add_argument(
"--requests-through-public-did",
action="store_true",
env_var="ACAPY_REQUESTS_THROUGH_PUBLIC_DID",
help=(
"Allow agent to receive unsolicited connection requests, "
"using the public DID for the agent. Default: false."
),
)
Expand Down Expand Up @@ -1134,6 +1144,13 @@ def get_settings(self, args: Namespace) -> dict:
settings["monitor_forward"] = args.monitor_forward
if args.public_invites:
settings["public_invites"] = True
if args.requests_through_public_did:
if not args.public_invites:
raise ArgsParseError(
"--public-invites is required to use "
"--requests-through-public-did"
)
settings["requests_through_public_did"] = True
if args.timing:
settings["timing.enabled"] = True
if args.timing_log:
Expand Down
8 changes: 5 additions & 3 deletions aries_cloudagent/connections/base_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,16 +269,18 @@ async def resolve_invitation(

endpoint = first_didcomm_service.service_endpoint
recipient_keys: List[VerificationMethod] = [
doc.dereference(url) for url in first_didcomm_service.recipient_keys
await resolver.dereference(self._profile, url, document=doc)
for url in first_didcomm_service.recipient_keys
]
routing_keys: List[VerificationMethod] = [
doc.dereference(url) for url in first_didcomm_service.routing_keys
await resolver.dereference(self._profile, url, document=doc)
for url in first_didcomm_service.routing_keys
]

for key in [*recipient_keys, *routing_keys]:
if not isinstance(key, self.SUPPORTED_KEY_TYPES):
raise BaseConnectionManagerError(
f"Key type {key.type} is not supported"
f"Key type {type(key).__name__} is not supported"
)

return (
Expand Down
18 changes: 3 additions & 15 deletions aries_cloudagent/connections/models/conn_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,11 +677,7 @@ class Meta:
required=False,
description="Routing state of connection",
validate=validate.OneOf(
[
getattr(ConnRecord, m)
for m in vars(ConnRecord)
if m.startswith("ROUTING_STATE_")
]
ConnRecord.get_attributes_by_prefix("ROUTING_STATE_", walk_mro=False)
),
example=ConnRecord.ROUTING_STATE_ACTIVE,
)
Expand All @@ -690,11 +686,7 @@ class Meta:
description="Connection acceptance: manual or auto",
example=ConnRecord.ACCEPT_AUTO,
validate=validate.OneOf(
[
getattr(ConnRecord, a)
for a in vars(ConnRecord)
if a.startswith("ACCEPT_")
]
ConnRecord.get_attributes_by_prefix("ACCEPT_", walk_mro=False)
),
)
error_msg = fields.Str(
Expand All @@ -707,11 +699,7 @@ class Meta:
description="Invitation mode",
example=ConnRecord.INVITATION_MODE_ONCE,
validate=validate.OneOf(
[
getattr(ConnRecord, i)
for i in vars(ConnRecord)
if i.startswith("INVITATION_MODE_")
]
ConnRecord.get_attributes_by_prefix("INVITATION_MODE_", walk_mro=False)
),
)
alias = fields.Str(
Expand Down
3 changes: 2 additions & 1 deletion aries_cloudagent/core/tests/test_conductor.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from ...utils.stats import Collector
from ...version import __version__
from ...wallet.base import BaseWallet
from ...wallet.did_method import SOV
from ...wallet.did_method import SOV, DIDMethods
from ...wallet.key_type import ED25519
from .. import conductor as test_module

Expand Down Expand Up @@ -87,6 +87,7 @@ async def build_context(self) -> InjectionContext:
context.injector.bind_instance(ProfileManager, InMemoryProfileManager())
context.injector.bind_instance(ProtocolRegistry, ProtocolRegistry())
context.injector.bind_instance(BaseWireFormat, self.wire_format)
context.injector.bind_instance(DIDMethods, DIDMethods())
context.injector.bind_instance(DIDResolver, DIDResolver([]))
context.injector.bind_instance(EventBus, MockEventBus())
return context
Expand Down
2 changes: 1 addition & 1 deletion aries_cloudagent/ledger/tests/test_indy_vdr.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

@pytest.fixture()
def ledger():
profile = InMemoryProfile.test_profile()
profile = InMemoryProfile.test_profile(bind={DIDMethods: DIDMethods()})
ledger = IndyVdrLedger(IndyVdrLedgerPool("test-ledger"), profile)

async def open():
Expand Down
2 changes: 0 additions & 2 deletions aries_cloudagent/messaging/jsonld/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from marshmallow import INCLUDE, Schema, fields
from pydid.verification_method import (
Ed25519VerificationKey2018,
KnownVerificationMethods,
)

from ...admin.request_context import AdminRequestContext
Expand Down Expand Up @@ -148,7 +147,6 @@ async def verify(request: web.BaseRequest):
vmethod = await resolver.dereference(
profile,
doc["proof"]["verificationMethod"],
cls=KnownVerificationMethods,
)

if not isinstance(vmethod, SUPPORTED_VERIFICATION_METHOD_TYPES):
Expand Down
29 changes: 15 additions & 14 deletions aries_cloudagent/messaging/jsonld/tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from ....resolver.did_resolver import DIDResolver
from ....vc.ld_proofs.document_loader import DocumentLoader
from ....wallet.base import BaseWallet
from ....wallet.did_method import SOV
from ....wallet.did_method import SOV, DIDMethods
from ....wallet.error import WalletError
from ....wallet.key_type import ED25519
from ..error import (
Expand Down Expand Up @@ -234,22 +234,22 @@ async def test_verify_bad_ver_meth_deref_req_error(
assert "error" in mock_response.call_args[0][0]


@pytest.mark.asyncio
async def test_verify_bad_ver_meth_not_ver_meth(
mock_resolver, mock_verify_request, mock_response, request_body
):
request_body["doc"]["proof"][
"verificationMethod"
] = "did:example:1234abcd#did-communication"
await test_module.verify(mock_verify_request(request_body))
assert "error" in mock_response.call_args[0][0]


@pytest.mark.parametrize(
"vmethod",
[
"did:example:1234abcd#key-2",
"did:example:1234abcd#did-communication",
],
)
@pytest.mark.asyncio
async def test_verify_bad_vmethod_unsupported(
mock_resolver, mock_verify_request, mock_response, request_body
mock_resolver,
mock_verify_request,
mock_response,
request_body,
vmethod,
):
request_body["doc"]["proof"]["verificationMethod"] = "did:example:1234abcd#key-2"
request_body["doc"]["proof"]["verificationMethod"] = vmethod
with pytest.raises(web.HTTPBadRequest):
await test_module.verify(mock_verify_request(request_body))

Expand All @@ -274,6 +274,7 @@ async def setUp(self):
self.context.profile.context.injector.bind_instance(
DocumentLoader, custom_document_loader
)
self.context.profile.context.injector.bind_instance(DIDMethods, DIDMethods())
self.did_info = await (await self.context.session()).wallet.create_local_did(
SOV, ED25519
)
Expand Down
21 changes: 20 additions & 1 deletion aries_cloudagent/messaging/models/base_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class Meta:
EVENT_NAMESPACE: str = "acapy::record"
LOG_STATE_FLAG = None
TAG_NAMES = {"state"}
STATE_DELETED = "deleted"

def __init__(
self,
Expand Down Expand Up @@ -420,7 +421,7 @@ async def delete_record(self, session: ProfileSession):
storage = session.inject(BaseStorage)
if self.state:
self._previous_state = self.state
self.state = "deleted"
self.state = BaseRecord.STATE_DELETED
await self.emit_event(session, self.serialize())
await storage.delete_record(self.storage_record)

Expand Down Expand Up @@ -497,6 +498,24 @@ def __eq__(self, other: Any) -> bool:
return self.value == other.value and self.tags == other.tags
return False

@classmethod
def get_attributes_by_prefix(cls, prefix: str, walk_mro: bool = True):
"""
List all values for attributes with common prefix.
Args:
prefix: Common prefix to look for
walk_mro: Walk MRO to find attributes inherited from superclasses
"""

bases = cls.__mro__ if walk_mro else [cls]
return [
vars(base)[name]
for base in bases
for name in vars(base)
if name.startswith(prefix)
]


class BaseExchangeRecord(BaseRecord):
"""Represents a base record with event tracing capability."""
Expand Down
Loading

0 comments on commit a276ee7

Please sign in to comment.