Skip to content

Commit

Permalink
Merge pull request #669 from sklump/provision-profile-linked-domain-e…
Browse files Browse the repository at this point in the history
…ndpoints

provisioning for profile endpoints, accommodate w3c (to API) and indy…
  • Loading branch information
andrewwhitehead authored Aug 21, 2020
2 parents 0812c2d + e10747a commit a2530dd
Show file tree
Hide file tree
Showing 17 changed files with 153 additions and 103 deletions.
10 changes: 9 additions & 1 deletion aries_cloudagent/config/argparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,12 @@ def add_arguments(self, parser: ArgumentParser):
The endpoints are used in the formation of a connection\
with another agent.",
)
parser.add_argument(
"--profile-endpoint",
type=str,
metavar="<profile_endpoint>",
help="Specifies the profile endpoint for the (public) DID.",
)
parser.add_argument(
"--read-only-ledger",
action="store_true",
Expand All @@ -413,10 +419,12 @@ def get_settings(self, args: Namespace) -> dict:
if args.external_plugins:
settings["external_plugins"] = args.external_plugins
if args.storage_type:
settings["storage.type"] = args.storage_type
settings["storage_type"] = args.storage_type
if args.endpoint:
settings["default_endpoint"] = args.endpoint[0]
settings["additional_endpoints"] = args.endpoint[1:]
if args.profile_endpoint:
settings["profile_endpoint"] = args.profile_endpoint
if args.read_only_ledger:
settings["read_only_ledger"] = True
if args.tails_server_base_url:
Expand Down
10 changes: 9 additions & 1 deletion aries_cloudagent/config/ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from prompt_toolkit.formatted_text import HTML

from ..ledger.base import BaseLedger
from ..ledger.endpoint_type import EndpointType
from ..ledger.error import LedgerError
from ..utils.http import fetch, FetchError
from ..wallet.base import BaseWallet
Expand Down Expand Up @@ -75,7 +76,7 @@ async def ledger_config(
if not await accept_taa(ledger, taa_info, provision):
return False

# Publish endpoint if necessary - skipped if TAA is required but not accepted
# Publish endpoints if necessary - skipped if TAA is required but not accepted
endpoint = context.settings.get("default_endpoint")
if public_did:
wallet: BaseWallet = await context.inject(BaseWallet)
Expand All @@ -86,6 +87,13 @@ async def ledger_config(
except LedgerError as x_ledger:
raise ConfigError(x_ledger.message) from x_ledger # e.g., read-only

# Publish profile endpoint
profile_endpoint = context.settings.get("profile_endpoint")
if profile_endpoint:
await ledger.update_endpoint_for_did(
public_did, profile_endpoint, EndpointType.PROFILE
)

return True


Expand Down
2 changes: 2 additions & 0 deletions aries_cloudagent/config/tests/test_ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ async def test_ledger_config_genesis_url(self):
settings = {
"ledger.genesis_url": "00000000000000000000000000000000",
"default_endpoint": "http://1.2.3.4:8051",
"profile_endpoint": "http://agent.ca",
}
mock_ledger = async_mock.MagicMock(
type="indy",
Expand All @@ -48,6 +49,7 @@ async def test_ledger_config_genesis_url(self):
get_latest_txn_author_acceptance=async_mock.CoroutineMock(
return_value={"digest": b"1234567890123456789012345678901234567890"}
),
update_endpoint_for_did=async_mock.CoroutineMock(),
)
mock_wallet = async_mock.MagicMock(
type="indy", set_did_endpoint=async_mock.CoroutineMock()
Expand Down
5 changes: 3 additions & 2 deletions aries_cloudagent/ledger/base.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"""Ledger base class."""

from abc import ABC, abstractmethod, ABCMeta
import re

from abc import ABC, abstractmethod, ABCMeta
from typing import Tuple, Sequence

from ..issuer.base import BaseIssuer

from .util import EndpointType
from .endpoint_type import EndpointType


class BaseLedger(ABC, metaclass=ABCMeta):
Expand Down
36 changes: 36 additions & 0 deletions aries_cloudagent/ledger/endpoint_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Ledger utilities."""

from collections import namedtuple
from enum import Enum

EndpointTypeName = namedtuple("EndpointTypeName", "w3c indy")


class EndpointType(Enum):
"""Enum for endpoint/service types."""

ENDPOINT = EndpointTypeName("Endpoint", "endpoint")
PROFILE = EndpointTypeName("Profile", "profile")
LINKED_DOMAINS = EndpointTypeName("LinkedDomains", "linked_domains")

@staticmethod
def get(name: str) -> "EndpointType":
"""Return enum instance corresponding to input string."""
if name is None:
return None

for endpoint_type in EndpointType:
if name.replace("_", "").lower() == endpoint_type.w3c.lower():
return endpoint_type

return None

@property
def w3c(self):
"""W3C name of endpoint type: externally-facing."""
return self.value.w3c

@property
def indy(self):
"""Indy name of endpoint type: internally-facing, on ledger and in wallet."""
return self.value.indy
11 changes: 6 additions & 5 deletions aries_cloudagent/ledger/indy.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@
from ..wallet.base import BaseWallet, DIDInfo

from .base import BaseLedger
from .endpoint_type import EndpointType
from .error import (
BadLedgerRequestError,
ClosedPoolError,
LedgerConfigError,
LedgerError,
LedgerTransactionError,
)
from .util import TAA_ACCEPTED_RECORD_TYPE, EndpointType
from .util import TAA_ACCEPTED_RECORD_TYPE

GENESIS_TRANSACTION_PATH = tempfile.gettempdir()
GENESIS_TRANSACTION_PATH = path.join(
Expand Down Expand Up @@ -793,7 +794,7 @@ async def get_endpoint_for_did(
data_json = json.loads(response_json)["result"]["data"]
if data_json:
endpoint = json.loads(data_json).get("endpoint", None)
address = endpoint.get(endpoint_type.value, None) if endpoint else None
address = endpoint.get(endpoint_type.indy, None) if endpoint else None
else:
address = None

Expand All @@ -814,7 +815,7 @@ async def update_endpoint_for_did(

all_exist_endpoints = await self.get_all_endpoints_for_did(did)
exist_endpoint_of_type = (
all_exist_endpoints.get(endpoint_type.value, None)
all_exist_endpoints.get(endpoint_type.indy, None)
if all_exist_endpoints
else None
)
Expand All @@ -828,10 +829,10 @@ async def update_endpoint_for_did(
nym = self.did_to_nym(did)

if all_exist_endpoints:
all_exist_endpoints[endpoint_type.value] = endpoint
all_exist_endpoints[endpoint_type.indy] = endpoint
attr_json = json.dumps({"endpoint": all_exist_endpoints})
else:
attr_json = json.dumps({"endpoint": {endpoint_type.value: endpoint}})
attr_json = json.dumps({"endpoint": {endpoint_type.indy: endpoint}})

with IndyErrorHandler(
"Exception when building attribute request", LedgerError
Expand Down
14 changes: 9 additions & 5 deletions aries_cloudagent/ledger/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
from ..messaging.valid import ENDPOINT_TYPE, INDY_DID, INDY_RAW_PUBLIC_KEY
from ..storage.error import StorageError
from ..wallet.error import WalletError

from .base import BaseLedger
from .indy import Role
from .endpoint_type import EndpointType
from .error import BadLedgerRequestError, LedgerError, LedgerTransactionError

from .util import EndpointType
from .indy import Role


class AMLRecordSchema(OpenAPISchema):
Expand Down Expand Up @@ -90,7 +90,9 @@ class QueryStringEndpointSchema(OpenAPISchema):

did = fields.Str(description="DID of interest", required=True, **INDY_DID)
endpoint_type = fields.Str(
description="Endpoint type of interest (default 'endpoint')",
description=(
f"Endpoint type of interest (default '{EndpointType.ENDPOINT.w3c}')"
),
required=False,
**ENDPOINT_TYPE,
)
Expand Down Expand Up @@ -253,7 +255,9 @@ async def get_did_endpoint(request: web.BaseRequest):
raise web.HTTPForbidden(reason=reason)

did = request.query.get("did")
endpoint_type = EndpointType(request.query.get("endpoint_type", "endpoint"))
endpoint_type = EndpointType.get(
request.query.get("endpoint_type", EndpointType.ENDPOINT.w3c)
)

if not did:
raise web.HTTPBadRequest(reason="Request query must include DID")
Expand Down
19 changes: 19 additions & 0 deletions aries_cloudagent/ledger/tests/test_endpoint_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from asynctest import TestCase as AsyncTestCase

from ..endpoint_type import EndpointType


class TestEndpointType(AsyncTestCase):
async def test_endpoint_type(self):
assert EndpointType.ENDPOINT == EndpointType.get("endpoint")
assert EndpointType.PROFILE == EndpointType.get("PROFILE")
assert EndpointType.LINKED_DOMAINS == EndpointType.get("linked_domains")
assert EndpointType.get("no-such-type") is None
assert EndpointType.get(None) is None

assert EndpointType.PROFILE.w3c == "Profile"
assert EndpointType.PROFILE.indy == "profile"
assert EndpointType.ENDPOINT.w3c == "Endpoint"
assert EndpointType.ENDPOINT.indy == "endpoint"
assert EndpointType.LINKED_DOMAINS.w3c == "LinkedDomains"
assert EndpointType.LINKED_DOMAINS.indy == "linked_domains"
27 changes: 16 additions & 11 deletions aries_cloudagent/ledger/tests/test_indy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from asynctest import TestCase as AsyncTestCase
from asynctest import mock as async_mock

from aries_cloudagent.cache.basic import BasicCache
from aries_cloudagent.issuer.base import BaseIssuer, IssuerError
from aries_cloudagent.ledger.indy import (
from ...cache.basic import BasicCache
from ...issuer.base import BaseIssuer, IssuerError
from ...ledger.endpoint_type import EndpointType
from ...ledger.indy import (
BadLedgerRequestError,
ClosedPoolError,
ErrorCode,
Expand All @@ -21,11 +22,9 @@
Role,
TAA_ACCEPTED_RECORD_TYPE,
)
from aries_cloudagent.storage.indy import IndyStorage
from aries_cloudagent.storage.record import StorageRecord
from aries_cloudagent.wallet.base import DIDInfo

from ...ledger.util import EndpointType
from ...storage.indy import IndyStorage
from ...storage.record import StorageRecord
from ...wallet.base import DIDInfo


class TestRole(AsyncTestCase):
Expand Down Expand Up @@ -1775,7 +1774,13 @@ async def test_get_endpoint_of_type_profile_for_did(
endpoint = "http://company.com/masterdata"
endpoint_type = EndpointType.PROFILE
mock_submit.return_value = json.dumps(
{"result": {"data": json.dumps({"endpoint": {"Profile": endpoint}})}}
{
"result": {
"data": json.dumps(
{"endpoint": {EndpointType.PROFILE.indy: endpoint}}
)
}
}
)
ledger = IndyLedger("name", mock_wallet)

Expand Down Expand Up @@ -1807,7 +1812,7 @@ async def test_get_all_endpoints_for_did(
profile_endpoint = "http://company.com/masterdata"
default_endpoint = "http://agent.company.com"
data_json = json.dumps(
{"endpoint": {"endpoint": default_endpoint, "Profile": profile_endpoint}}
{"endpoint": {"endpoint": default_endpoint, "profile": profile_endpoint}}
)
mock_submit.return_value = json.dumps({"result": {"data": data_json}})
ledger = IndyLedger("name", mock_wallet)
Expand Down Expand Up @@ -2028,7 +2033,7 @@ async def test_update_endpoint_of_type_profile_for_did(
{
"result": {
"data": json.dumps(
{"endpoint": {endpoint_type.value: endpoint[i]}}
{"endpoint": {endpoint_type.indy: endpoint[i]}}
)
}
}
Expand Down
7 changes: 5 additions & 2 deletions aries_cloudagent/ledger/tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from ...config.injection_context import InjectionContext
from ...ledger.base import BaseLedger
from ...ledger.util import EndpointType
from ...ledger.endpoint_type import EndpointType

from .. import routes as test_module
from ..indy import Role
Expand Down Expand Up @@ -99,7 +99,10 @@ async def test_get_endpoint(self):
async def test_get_endpoint_of_type_profile(self):
request = async_mock.MagicMock()
request.app = self.app
request.query = {"did": self.test_did, "endpoint_type": self.test_endpoint_type}
request.query = {
"did": self.test_did,
"endpoint_type": self.test_endpoint_type.w3c,
}
with async_mock.patch.object(
test_module.web, "json_response", async_mock.Mock()
) as json_response:
Expand Down
10 changes: 0 additions & 10 deletions aries_cloudagent/ledger/util.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
"""Ledger utilities."""

from enum import Enum

TAA_ACCEPTED_RECORD_TYPE = "taa_accepted"


class EndpointType(Enum):
"""Enum for endpoint/service types."""

ENDPOINT = "endpoint"
PROFILE = "Profile"
LINKED_DOMAINS = "LinkedDomains"
20 changes: 20 additions & 0 deletions aries_cloudagent/messaging/tests/test_valid.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
BASE64URL_NO_PAD,
DID_KEY,
ENDPOINT,
ENDPOINT_TYPE,
INDY_CRED_DEF_ID,
INDY_CRED_REV_ID,
INDY_DID,
Expand Down Expand Up @@ -426,3 +427,22 @@ def test_endpoint(self):
ENDPOINT["validate"]("newproto://myhost.ca:8080/path")
ENDPOINT["validate"]("ftp://10.10.100.90:8021")
ENDPOINT["validate"]("zzzp://someplace.ca:9999/path")

def test_endpoint_type(self):
non_endpoint_types = [
"123",
"endpoint",
"end point",
"end-point",
"profile",
"linked_domains",
None,
]

for non_endpoint_type in non_endpoint_types:
with self.assertRaises(ValidationError):
ENDPOINT_TYPE["validate"](non_endpoint_type)

ENDPOINT_TYPE["validate"]("Endpoint")
ENDPOINT_TYPE["validate"]("Profile")
ENDPOINT_TYPE["validate"]("LinkedDomains")
6 changes: 3 additions & 3 deletions aries_cloudagent/messaging/valid.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from .util import epoch_to_str

from ..ledger.util import EndpointType as EndpointTypeEnum
from ..ledger.endpoint_type import EndpointType as EndpointTypeEnum

B58 = alphabet if isinstance(alphabet, str) else alphabet.decode("ascii")

Expand Down Expand Up @@ -431,13 +431,13 @@ def __init__(self):
class EndpointType(OneOf):
"""Validate value against allowed endpoint/service types."""

EXAMPLE = "endpoint"
EXAMPLE = EndpointTypeEnum.ENDPOINT.w3c

def __init__(self):
"""Initializer."""

super().__init__(
choices=[e.value for e in EndpointTypeEnum],
choices=[e.w3c for e in EndpointTypeEnum],
error="Value {input} must be one of {choices}",
)

Expand Down
2 changes: 1 addition & 1 deletion aries_cloudagent/storage/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ async def provide(self, settings: BaseSettings, injector: BaseInjector):
wallet_type = settings.get_value("wallet.type", default="basic").lower()
storage_default_type = "indy" if wallet_type == "indy" else "basic"
storage_type = settings.get_value(
"storage.type", default=storage_default_type
"storage_type", default=storage_default_type
).lower()
storage_class = self.STORAGE_TYPES.get(storage_type, storage_type)
storage = ClassLoader.load_class(storage_class)(wallet)
Expand Down
Loading

0 comments on commit a2530dd

Please sign in to comment.