Skip to content

Commit c7145dc

Browse files
authored
Merge pull request #23 from peacekeeper/resolver-services
Updates for "resolve" and "resolver-service" components
2 parents 86c63c0 + f96b0a2 commit c7145dc

File tree

5 files changed

+102
-86
lines changed

5 files changed

+102
-86
lines changed

src/dkr/app/cli/commands/did/keri/resolve.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"""
66
import argparse
77
import json
8+
import sys
89

910
from hio.base import doing
1011
from keri.app import habbing, oobiing
@@ -31,33 +32,34 @@
3132

3233

3334
def handler(args):
34-
res = Resolver(name=args.name, base=args.base, bran=args.bran, did=args.did, oobi=args.oobi, metadata=args.metadata)
35+
hby = existing.setupHby(name=args.name, base=args.base, bran=args.bran)
36+
hbyDoer = habbing.HaberyDoer(habery=hby) # setup doer
37+
obl = oobiing.Oobiery(hby=hby)
38+
res = KeriResolver(hby=hby, hbyDoer=hbyDoer, obl=obl, did=args.did, oobi=args.oobi, metadata=args.metadata)
3539
return [res]
3640

3741

38-
class Resolver(doing.DoDoer):
42+
class KeriResolver(doing.DoDoer):
3943

40-
def __init__(self, name, base, bran, did, oobi, metadata):
44+
def __init__(self, hby, hbyDoer, obl, did, oobi, metadata):
4145

42-
self.hby = existing.setupHby(name=name, base=base, bran=bran)
43-
hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer
44-
obl = oobiing.Oobiery(hby=self.hby)
46+
self.hby = hby
4547
self.did = did
4648
self.oobi = oobi
4749
self.metadata = metadata
4850

4951
self.toRemove = [hbyDoer] + obl.doers
5052
doers = list(self.toRemove) + [doing.doify(self.resolve)]
51-
super(Resolver, self).__init__(doers=doers)
53+
super(KeriResolver, self).__init__(doers=doers)
5254

5355
def resolve(self, tymth, tock=0.0, **opts):
5456
self.wind(tymth)
5557
self.tock = tock
5658
_ = (yield self.tock)
5759

5860
aid = didding.parseDIDKeri(self.did)
59-
print(f"From arguments got aid: {aid}")
60-
print(f"From arguments got oobi: {self.oobi}")
61+
print(f"From arguments got aid: {aid}", file=sys.stderr)
62+
print(f"From arguments got oobi: {self.oobi}", file=sys.stderr)
6163

6264
obr = basing.OobiRecord(date=helping.nowIso8601())
6365
obr.cid = aid
@@ -66,11 +68,13 @@ def resolve(self, tymth, tock=0.0, **opts):
6668
while self.hby.db.roobi.get(keys=(self.oobi,)) is None:
6769
_ = yield tock
6870

69-
result = didding.generateDIDDoc(self.hby, did=self.did, aid=aid, oobi=self.oobi, metadata=self.metadata)
71+
didresult = didding.generateDIDDoc(self.hby, did=self.did, aid=aid, oobi=self.oobi, metadata=True)
72+
dd = didresult['didDocument']
73+
result = didresult if self.metadata else dd
7074
data = json.dumps(result, indent=2)
7175

7276
print(data)
7377
self.remove(self.toRemove)
74-
return True
78+
return result
7579

7680

src/dkr/app/cli/commands/did/keri/resolver-service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def launch(args, expire=0.0):
7171
obl = oobiing.Oobiery(hby=hby)
7272

7373
doers = obl.doers + [hbyDoer]
74-
doers += resolving.setup(hby, httpPort=httpPort)
74+
doers += resolving.setup(hby, hbyDoer, obl, httpPort=httpPort)
7575

7676
print(f"Launched did:keri resolver as an HTTP web service on {httpPort}")
7777
return doers

src/dkr/app/cli/commands/did/webs/resolve.py

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import argparse
77
import json
88
import requests
9+
import sys
910

1011
from hio.base import doing
1112
from keri.app import habbing, oobiing
@@ -32,23 +33,24 @@
3233

3334

3435
def handler(args):
35-
res = Resolver(name=args.name, base=args.base, bran=args.bran, did=args.did)
36+
hby = existing.setupHby(name=args.name, base=args.base, bran=args.bran)
37+
hbyDoer = habbing.HaberyDoer(habery=hby) # setup doer
38+
obl = oobiing.Oobiery(hby=hby)
39+
res = WebsResolver(hby=hby, hbyDoer=hbyDoer, obl=obl, did=args.did, metadata=args.metadata)
3640
return [res]
3741

3842

39-
class Resolver(doing.DoDoer):
43+
class WebsResolver(doing.DoDoer):
4044

41-
def __init__(self, name, base, bran, did, metadata):
45+
def __init__(self, hby, hbyDoer, obl, did, metadata):
4246

43-
self.hby = existing.setupHby(name=name, base=base, bran=bran)
44-
hbyDoer = habbing.HaberyDoer(habery=self.hby) # setup doer
45-
obl = oobiing.Oobiery(hby=self.hby)
47+
self.hby = hby
4648
self.did = did
4749
self.metadata = metadata
4850

4951
self.toRemove = [hbyDoer] + obl.doers
5052
doers = list(self.toRemove) + [doing.doify(self.resolve)]
51-
super(Resolver, self).__init__(doers=doers)
53+
super(WebsResolver, self).__init__(doers=doers)
5254

5355
def resolve(self, tymth, tock=0.0, **opts):
5456
self.wind(tymth)
@@ -61,25 +63,36 @@ def resolve(self, tymth, tock=0.0, **opts):
6163

6264
# Load the did doc
6365
dd_url = f"{base_url}/{webbing.DID_JSON}"
64-
print(f"Loading DID Doc from {dd_url}")
66+
print(f"Loading DID Doc from {dd_url}", file=sys.stderr)
6567
dd_actual = didding.fromDidWeb(json.loads(self.loadUrl(dd_url).decode("utf-8")))
6668

6769
# Load the KERI CESR
6870
kc_url = f"{base_url}/{webbing.KERI_CESR}"
69-
print(f"Loading KERI CESR from {kc_url}")
71+
print(f"Loading KERI CESR from {kc_url}", file=sys.stderr)
7072
self.hby.psr.parse(ims=bytearray(self.loadUrl(kc_url)))
7173

72-
dd_expected = didding.generateDIDDoc(self.hby, did=self.did, aid=aid, oobi=None, metadata=self.metadata)
73-
74+
didresult = didding.generateDIDDoc(self.hby, did=self.did, aid=aid, oobi=None, metadata=True)
75+
didresult['didDocumentMetadata']['didDocUrl'] = dd_url
76+
didresult['didDocumentMetadata']['keriCesrUrl'] = kc_url
77+
78+
dd_expected = didresult['didDocument']
79+
7480
verified = self.verifyDidDocs(dd_expected, dd_actual)
75-
81+
7682
self.remove(self.toRemove)
7783

7884
if verified:
79-
return dd_actual
85+
result = didresult if self.metadata else dd_expected
8086
else:
81-
return None
82-
87+
didresult['didDocument'] = None
88+
didresult['didResolutionMetadata']['error'] = 'notVerified'
89+
didresult['didResolutionMetadata']['errorMessage'] = 'The DID document could not be verified against the KERI event stream'
90+
result = didresult
91+
92+
data = json.dumps(result, indent=2)
93+
print(data)
94+
return result
95+
8396
def loadUrl(self, url):
8497
response = requests.get(f"{url}")
8598
# Ensure the request was successful
@@ -97,49 +110,49 @@ def loadFile(self, aid):
97110

98111
def verifyDidDocs(self, expected, actual):
99112
if expected != actual:
100-
print("DID Doc does not verify")
113+
print("DID Doc does not verify", file=sys.stderr)
101114
compare_dicts(expected, actual)
102115
return False
103116
else:
104-
print("DID Doc verified")
117+
print("DID Doc verified", file=sys.stderr)
105118
return True
106119

107120
def compare_dicts(expected, actual, path=""):
108-
print("Comparing dictionaries:\nexpected:\n{expected} \nand\n \nactual:\n{actual}")
121+
print("Comparing dictionaries:\nexpected:\n{expected} \nand\n \nactual:\n{actual}", file=sys.stderr)
109122

110123
"""Recursively compare two dictionaries and print differences."""
111124
for k in expected.keys():
112125
# Construct current path
113126
current_path = f"{path}.{k}" if path else k
114-
print(f"Comparing key {current_path}")
127+
print(f"Comparing key {current_path}", file=sys.stderr)
115128

116129
# Key not present in the actual dictionary
117130
if k not in actual:
118-
print(f"Key {current_path} not found in the actual dictionary")
131+
print(f"Key {current_path} not found in the actual dictionary", file=sys.stderr)
119132
continue
120133

121134
# If value in expected is a dictionary but not in actual
122135
if isinstance(expected[k], dict) and not isinstance(actual[k], dict):
123-
print(f"{current_path} is a dictionary in expected, but not in actual")
136+
print(f"{current_path} is a dictionary in expected, but not in actual", file=sys.stderr)
124137
continue
125138

126139
# If value in actual is a dictionary but not in expected
127140
if isinstance(actual[k], dict) and not isinstance(expected[k], dict):
128-
print(f"{current_path} is a dictionary in actual, but not in expected")
141+
print(f"{current_path} is a dictionary in actual, but not in expected", file=sys.stderr)
129142
continue
130143

131144
# If value is another dictionary, recurse
132145
if isinstance(expected[k], dict) and isinstance(actual[k], dict):
133146
compare_dicts(expected[k], actual[k], current_path)
134147
# Compare non-dict values
135148
elif expected[k] != actual[k]:
136-
print(f"Different values for key {current_path}: {expected[k]} (expected) vs. {actual[k]} (actual)")
149+
print(f"Different values for key {current_path}: {expected[k]} (expected) vs. {actual[k]} (actual)", file=sys.stderr)
137150

138151
# Check for keys in actual that are not present in expected
139152
for k in actual.keys():
140153
current_path = f"{path}.{k}" if path else k
141154
if k not in expected:
142-
print(f"Key {current_path} not found in the expected dictionary")
155+
print(f"Key {current_path} not found in the expected dictionary", file=sys.stderr)
143156

144157
# # Test with the provided dictionaries
145158
# expected_dict = {

src/dkr/app/cli/commands/did/webs/resolver-service.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
parser.add_argument('-p', '--http',
1717
action='store',
1818
default=7677,
19-
help="Port on which to listen for did:webs resolution requests. Defaults to 967")
19+
help="Port on which to listen for did:webs resolution requests. Defaults to 7677")
2020
parser.add_argument('-n', '--name',
2121
action='store',
2222
default="dkr",
@@ -71,7 +71,7 @@ def launch(args, expire=0.0):
7171
obl = oobiing.Oobiery(hby=hby)
7272

7373
doers = obl.doers + [hbyDoer]
74-
doers += resolving.setup(hby, httpPort=httpPort)
74+
doers += resolving.setup(hby, hbyDoer, obl, httpPort=httpPort)
7575

7676
print(f"Launched did:webs resolver as an HTTP web service on {httpPort}")
7777
return doers

src/dkr/core/resolving.py

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,28 @@
44
55
"""
66
import json
7+
import os
78

89
import falcon
910
from hio.base import doing
1011
from hio.core import http
1112
from keri.db import basing
1213
from keri.help import helping
14+
from dkr.app.cli.commands.did.keri.resolve import KeriResolver
15+
from dkr.app.cli.commands.did.webs.resolve import WebsResolver
1316

1417
from dkr.core import didding
1518

1619

17-
def setup(hby, *, httpPort):
20+
def setup(hby, hbyDoer, obl, *, httpPort):
1821
""" Setup serving package and endpoints
1922
2023
Parameters:
2124
hby (Habery): identifier database environment
2225
httpPort (int): external port to listen on for HTTP messages
2326
2427
"""
28+
print(f"Setup resolving")
2529
app = falcon.App(
2630
middleware=falcon.CORSMiddleware(
2731
allow_origins='*',
@@ -31,18 +35,20 @@ def setup(hby, *, httpPort):
3135
server = http.Server(port=httpPort, app=app)
3236
httpServerDoer = http.ServerDoer(server=server)
3337

34-
loadEnds(app, hby=hby)
38+
loadEnds(app, hby=hby, hbyDoer=hbyDoer, obl=obl)
3539

3640
doers = [httpServerDoer]
3741

3842
return doers
3943

4044

41-
def loadEnds(app, *, hby, prefix=""):
42-
oobiEnd = ResolveResource(hby=hby)
43-
app.add_route(prefix + "/resolve", oobiEnd)
45+
def loadEnds(app, *, hby, hbyDoer, obl, prefix=""):
46+
print(f"Loading resolving endpoints")
47+
resolveEnd = ResolveResource(hby=hby, hbyDoer=hbyDoer, obl=obl)
48+
result = app.add_route('/1.0/identifiers/{did}', resolveEnd)
49+
print(f"Loaded resolving endpoints: {app}")
4450

45-
return [oobiEnd]
51+
return [resolveEnd]
4652

4753

4854
class ResolveResource(doing.DoDoer):
@@ -51,68 +57,61 @@ class ResolveResource(doing.DoDoer):
5157
5258
"""
5359

54-
def __init__(self, hby):
60+
def __init__(self, hby, hbyDoer, obl):
5561
""" Create Endpoints for discovery and resolution of OOBIs
5662
5763
Parameters:
5864
hby (Habery): identifier database environment
5965
6066
"""
6167
self.hby = hby
68+
self.hbyDoer = hbyDoer
69+
self.obl = obl
6270

6371
super(ResolveResource, self).__init__(doers=[])
72+
print(f"Init resolver endpoint")
6473

65-
def on_post(self, req, rep):
66-
""" Resolve did:keri DID endpoint.
74+
def on_get(self, req, rep, did):
75+
print(f"Request to resolve did: {did}")
6776

68-
Parameters:
69-
req: falcon.Request HTTP request
70-
rep: falcon.Response HTTP response
71-
72-
---
73-
summary: Resolve did:keri DID using OOBI resolution and return DIDDoc
74-
description: Resolve OOBI URL or `rpy` message by process results of request and return DIDDoc
75-
tags:
76-
- Resolution
77-
requestBody:
78-
required: true
79-
content:
80-
application/json:
81-
schema:
82-
description: DID
83-
properties:
84-
did:
85-
type: string
86-
description: alias to assign to the identifier resolved from this OOBI
87-
required: false
88-
responses:
89-
200:
90-
description: Valid DIDDoc for resolved did:keri DID
91-
404:
92-
description: DID not found
93-
94-
"""
95-
body = req.get_media()
96-
97-
if "did" not in body:
77+
if did is None:
9878
rep.status = falcon.HTTP_400
9979
rep.text = "invalid resolution request body, 'did' is required"
10080
return
10181

102-
did = body["did"]
103-
aid, oobi = didding.parseDID(did)
104-
105-
obr = basing.OobiRecord(date=helping.nowIso8601())
106-
obr.cid = aid
107-
self.hby.db.oobis.pin(keys=(oobi,), val=obr)
82+
if 'oobi' in req.params:
83+
oobi = req.params['oobi']
84+
print(f"From parameters {req.params} got oobi: {oobi}")
85+
else:
86+
oobi = None
87+
88+
metadata = False
89+
90+
if did.startswith('did:webs:'):
91+
#res = WebsResolver(hby=self.hby, hbyDoer=self.hbyDoer, obl=self.obl, did=did)
92+
#tymth = None # ???
93+
#data = res.resolve(tymth)
94+
cmd = f"dkr did webs resolve --name dkr --did {did} --metadata {metadata}"
95+
stream = os.popen(cmd)
96+
data = stream.read()
97+
elif did.startswith('did:keri'):
98+
#res = KeriResolver(hby=self.hby, hbyDoer=self.hbyDoer, obl=self.obl, did=did, oobi=oobi, metadata=False)
99+
#tymth = None # ???
100+
#data = res.resolve(tymth)
101+
cmd = f"dkr did keri resolve --name dkr --did {did} --oobi {oobi} --metadata {metadata}"
102+
stream = os.popen(cmd)
103+
data = stream.read()
104+
else:
105+
rep.status = falcon.HTTP_400
106+
rep.text = "invalid 'did'"
107+
return
108108

109109
rep.status = falcon.HTTP_200
110-
rep.set_header('Content-Type', "application/json")
111-
rep.stream = OobiIterable(hby=self.hby, aid=aid, did=did, oobi=oobi)
110+
rep.set_header('Content-Type', "application/did+ld+json")
111+
rep.body = data
112112

113113
return
114114

115-
116115
class OobiIterable:
117116
def __init__(self, hby, aid, did, oobi):
118117
self.hby = hby

0 commit comments

Comments
 (0)