Skip to content

Commit b39ccef

Browse files
authored
Merge branch 'main' into master
2 parents e350a43 + eaf010c commit b39ccef

5 files changed

Lines changed: 64 additions & 42 deletions

File tree

aries_cloudagent/config/argparse.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,14 @@ def add_arguments(self, parser: ArgumentParser):
643643
"resolver instance."
644644
),
645645
)
646+
parser.add_argument(
647+
"--universal-resolver-bearer-token",
648+
type=str,
649+
nargs="?",
650+
metavar="<universal_resolver_token>",
651+
env_var="ACAPY_UNIVERSAL_RESOLVER_BEARER_TOKEN",
652+
help="Bearer token if universal resolver instance requires authentication.",
653+
),
646654

647655
def get_settings(self, args: Namespace) -> dict:
648656
"""Extract general settings."""
@@ -688,12 +696,21 @@ def get_settings(self, args: Namespace) -> dict:
688696
"--universal-resolver-regex cannot be used without --universal-resolver"
689697
)
690698

699+
if args.universal_resolver_bearer_token and not args.universal_resolver:
700+
raise ArgsParseError(
701+
"--universal-resolver-bearer-token "
702+
+ "cannot be used without --universal-resolver"
703+
)
704+
691705
if args.universal_resolver:
692706
settings["resolver.universal"] = args.universal_resolver
693707

694708
if args.universal_resolver_regex:
695709
settings["resolver.universal.supported"] = args.universal_resolver_regex
696710

711+
if args.universal_resolver_bearer_token:
712+
settings["resolver.universal.token"] = args.universal_resolver_bearer_token
713+
697714
return settings
698715

699716

aries_cloudagent/protocols/connections/v1_0/manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ async def receive_request(
479479
new_connection = ConnRecord(
480480
invitation_key=connection_key,
481481
my_did=my_info.did,
482-
state=ConnRecord.State.INVITATION.rfc160,
482+
state=ConnRecord.State.REQUEST.rfc160,
483483
accept=connection.accept,
484484
their_role=connection.their_role,
485485
connection_protocol=CONN_PROTO,

aries_cloudagent/resolver/default/tests/test_universal.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class MockClientSession:
5454
def __init__(self, response: MockResponse = None):
5555
self.response = response
5656

57-
def __call__(self):
57+
def __call__(self, headers):
5858
return self
5959

6060
async def __aenter__(self):
@@ -101,7 +101,7 @@ async def test_resolve_not_found(profile, resolver, mock_client_session):
101101

102102

103103
@pytest.mark.asyncio
104-
async def test_resolve_unexpeceted_status(profile, resolver, mock_client_session):
104+
async def test_resolve_unexpected_status(profile, resolver, mock_client_session):
105105
mock_client_session.response = MockResponse(
106106
500, "Server failed to complete request"
107107
)
@@ -112,21 +112,21 @@ async def test_resolve_unexpeceted_status(profile, resolver, mock_client_session
112112
@pytest.mark.asyncio
113113
async def test_fetch_resolver_props(mock_client_session: MockClientSession):
114114
mock_client_session.response = MockResponse(200, {"test": "json"})
115-
assert await test_module._fetch_resolver_props("test") == {"test": "json"}
115+
assert await UniversalResolver()._fetch_resolver_props() == {"test": "json"}
116116
mock_client_session.response = MockResponse(404, "Not found")
117117
with pytest.raises(ResolverError):
118-
await test_module._fetch_resolver_props("test")
118+
await UniversalResolver()._fetch_resolver_props()
119119

120120

121121
@pytest.mark.asyncio
122122
async def test_get_supported_did_regex():
123123
props = {"example": {"http": {"pattern": "match a test string"}}}
124124
with async_mock.patch.object(
125-
test_module,
125+
UniversalResolver,
126126
"_fetch_resolver_props",
127127
async_mock.CoroutineMock(return_value=props),
128128
):
129-
pattern = await test_module._get_supported_did_regex("test")
129+
pattern = await UniversalResolver()._get_supported_did_regex()
130130
assert pattern.fullmatch("match a test string")
131131

132132

@@ -169,7 +169,7 @@ async def test_setup_endpoint_set(resolver: UniversalResolver):
169169
context = async_mock.MagicMock()
170170
context.settings = settings
171171
with async_mock.patch.object(
172-
test_module,
172+
UniversalResolver,
173173
"_get_supported_did_regex",
174174
async_mock.CoroutineMock(return_value="pattern"),
175175
):
@@ -189,7 +189,7 @@ async def test_setup_endpoint_default(resolver: UniversalResolver):
189189
context = async_mock.MagicMock()
190190
context.settings = settings
191191
with async_mock.patch.object(
192-
test_module,
192+
UniversalResolver,
193193
"_get_supported_did_regex",
194194
async_mock.CoroutineMock(return_value="pattern"),
195195
):
@@ -205,7 +205,7 @@ async def test_setup_endpoint_unset(resolver: UniversalResolver):
205205
context = async_mock.MagicMock()
206206
context.settings = settings
207207
with async_mock.patch.object(
208-
test_module,
208+
UniversalResolver,
209209
"_get_supported_did_regex",
210210
async_mock.CoroutineMock(return_value="pattern"),
211211
):

aries_cloudagent/resolver/default/universal.py

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,7 @@
1111
from ..base import BaseDIDResolver, DIDNotFound, ResolverError, ResolverType
1212

1313
LOGGER = logging.getLogger(__name__)
14-
DEFAULT_ENDPOINT = "https://dev.uniresolver.io"
15-
16-
17-
async def _fetch_resolver_props(endpoint: str) -> dict:
18-
"""Retrieve universal resolver properties."""
19-
async with aiohttp.ClientSession() as session:
20-
async with session.get(f"{endpoint}/1.0/properties/") as resp:
21-
if resp.status >= 200 and resp.status < 400:
22-
return await resp.json()
23-
raise ResolverError(
24-
"Failed to retrieve resolver properties: " + await resp.text()
25-
)
26-
27-
28-
async def _get_supported_did_regex(endpoint: str) -> Pattern:
29-
props = await _fetch_resolver_props(endpoint)
30-
return _compile_supported_did_regex(
31-
driver["http"]["pattern"] for driver in props.values()
32-
)
14+
DEFAULT_ENDPOINT = "https://dev.uniresolver.io/1.0"
3315

3416

3517
def _compile_supported_did_regex(patterns: Iterable[Union[str, Pattern]]):
@@ -54,25 +36,37 @@ def __init__(
5436
*,
5537
endpoint: Optional[str] = None,
5638
supported_did_regex: Optional[Pattern] = None,
39+
bearer_token: Optional[str] = None,
5740
):
5841
"""Initialize UniversalResolver."""
5942
super().__init__(ResolverType.NON_NATIVE)
6043
self._endpoint = endpoint
6144
self._supported_did_regex = supported_did_regex
6245

46+
self.__default_headers = (
47+
{"Authorization": f"Bearer {bearer_token}"} if bearer_token else {}
48+
)
49+
6350
async def setup(self, context: InjectionContext):
64-
"""Preform setup, populate supported method list, configuration."""
51+
"""Perform setup, populate supported method list, configuration."""
52+
53+
# configure endpoint
6554
endpoint = context.settings.get_str("resolver.universal")
6655
if endpoint == "DEFAULT" or not endpoint:
6756
endpoint = DEFAULT_ENDPOINT
57+
self._endpoint = endpoint
58+
59+
# configure authorization
60+
token = context.settings.get_str("resolver.universal.token")
61+
self.__default_headers = {"Authorization": f"Bearer {token}"} if token else {}
6862

63+
# configure supported methods
6964
supported = context.settings.get("resolver.universal.supported")
7065
if supported is None:
71-
supported_did_regex = await _get_supported_did_regex(endpoint)
66+
supported_did_regex = await self._get_supported_did_regex()
7267
else:
7368
supported_did_regex = _compile_supported_did_regex(supported)
7469

75-
self._endpoint = endpoint
7670
self._supported_did_regex = supported_did_regex
7771

7872
@property
@@ -91,8 +85,8 @@ async def _resolve(
9185
) -> dict:
9286
"""Resolve DID through remote universal resolver."""
9387

94-
async with aiohttp.ClientSession() as session:
95-
async with session.get(f"{self._endpoint}/1.0/identifiers/{did}") as resp:
88+
async with aiohttp.ClientSession(headers=self.__default_headers) as session:
89+
async with session.get(f"{self._endpoint}/identifiers/{did}") as resp:
9690
if resp.status == 200:
9791
doc = await resp.json()
9892
did_doc = doc["didDocument"]
@@ -103,5 +97,21 @@ async def _resolve(
10397

10498
text = await resp.text()
10599
raise ResolverError(
106-
f"Unexecpted status from universal resolver ({resp.status}): {text}"
100+
f"Unexpected status from universal resolver ({resp.status}): {text}"
101+
)
102+
103+
async def _fetch_resolver_props(self) -> dict:
104+
"""Retrieve universal resolver properties."""
105+
async with aiohttp.ClientSession(headers=self.__default_headers) as session:
106+
async with session.get(f"{self._endpoint}/properties/") as resp:
107+
if 200 <= resp.status < 400:
108+
return await resp.json()
109+
raise ResolverError(
110+
"Failed to retrieve resolver properties: " + await resp.text()
107111
)
112+
113+
async def _get_supported_did_regex(self) -> Pattern:
114+
props = await self._fetch_resolver_props()
115+
return _compile_supported_did_regex(
116+
driver["http"]["pattern"] for driver in props.values()
117+
)

aries_cloudagent/wallet/routes.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
ENDPOINT,
2424
ENDPOINT_TYPE,
2525
INDY_DID,
26-
INDY_OR_KEY_DID,
2726
INDY_RAW_PUBLIC_KEY,
2827
GENERIC_DID,
2928
)
@@ -55,7 +54,7 @@ class WalletModuleResponseSchema(OpenAPISchema):
5554
class DIDSchema(OpenAPISchema):
5655
"""Result schema for a DID."""
5756

58-
did = fields.Str(description="DID of interest", **INDY_OR_KEY_DID)
57+
did = fields.Str(description="DID of interest", **GENERIC_DID)
5958
verkey = fields.Str(description="Public verification key", **INDY_RAW_PUBLIC_KEY)
6059
posture = fields.Str(
6160
description=(
@@ -66,11 +65,7 @@ class DIDSchema(OpenAPISchema):
6665
**DID_POSTURE,
6766
)
6867
method = fields.Str(
69-
description="Did method associated with the DID",
70-
example=SOV.method_name,
71-
validate=validate.OneOf(
72-
[method.method_name for method in [SOV, KEY]]
73-
), # TODO: support more methods
68+
description="Did method associated with the DID", example=SOV.method_name
7469
)
7570
key_type = fields.Str(
7671
description="Key type associated with the DID",

0 commit comments

Comments
 (0)