Skip to content

Commit 839ce4f

Browse files
authored
Updates to make credential admit fully work (WebOfTrust#122)
* Ensure that ipex admit API does not attempt to parse an embedded ACDC without an attachment. Signed-off-by: pfeairheller <pfeairheller@gmail.com> * Moving fix for credential without attachments to the appropriate place. Update Seeker to properly query for credentials without a filter. Query for TEL events regardless of witnesses. Signed-off-by: pfeairheller <pfeairheller@gmail.com> * Moving fix for credential without attachments to the appropriate place. Update Seeker to properly query for credentials without a filter. Query for TEL events regardless of witnesses. Signed-off-by: pfeairheller <pfeairheller@gmail.com> * Adding test coverage to patch. Signed-off-by: pfeairheller <pfeairheller@gmail.com> --------- Signed-off-by: pfeairheller <pfeairheller@gmail.com>
1 parent f80d976 commit 839ce4f

File tree

7 files changed

+115
-31
lines changed

7 files changed

+115
-31
lines changed

src/keria/app/agenting.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,9 @@ def recur(self, tyme):
508508
self.admits.append(msg)
509509
return False
510510

511+
admit, _ = exchanging.cloneMessage(self.hby, said)
511512
hab = self.hby.habs[msg['pre']]
512-
grant, pathed = exchanging.cloneMessage(self.hby, said)
513+
grant, pathed = exchanging.cloneMessage(self.hby, admit.ked['p'])
513514

514515
embeds = grant.ked['e']
515516
acdc = embeds["acdc"]
@@ -518,10 +519,13 @@ def recur(self, tyme):
518519
# Lets get the latest KEL and Registry if needed
519520
self.witq.query(hab=self.agentHab, pre=issr)
520521
if "ri" in acdc:
521-
self.witq.telquery(hab=self.agentHab, wits=hab.kevers[issr].wits, ri=acdc["ri"], i=acdc["d"])
522+
self.witq.telquery(hab=self.agentHab, pre=issr, ri=acdc["ri"], i=acdc["d"])
522523

523524
for label in ("anc", "iss", "acdc"):
524525
ked = embeds[label]
526+
if label not in pathed or not pathed[label]:
527+
continue
528+
525529
sadder = coring.Sadder(ked=ked)
526530
ims = bytearray(sadder.raw) + pathed[label]
527531
self.psr.parseOne(ims=ims)
@@ -540,8 +544,14 @@ def recur(self, tyme=None):
540544
cue = self.cues.popleft()
541545
if cue["kin"] == "saved":
542546
creder = cue["creder"]
543-
print(f"indexing {creder.said}")
544-
self.seeker.index(said=creder.said)
547+
try:
548+
self.seeker.index(said=creder.said)
549+
except Exception:
550+
self.cues.append(cue)
551+
return False
552+
else:
553+
self.cues.append(cue)
554+
return False
545555

546556

547557
class ExnSeekerDoer(doing.Doer):

src/keria/app/credentialing.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ def on_post(req, rep, name):
385385

386386
cur = agent.seeker.find(filtr=filtr, sort=sort, skip=skip, limit=limit)
387387
saids = [coring.Saider(qb64=said) for said in cur]
388-
creds = agent.rgy.reger.cloneCreds(saids=saids)
388+
creds = agent.rgy.reger.cloneCreds(saids=saids, db=agent.hby.db)
389389

390390
rep.status = falcon.HTTP_200
391391
rep.content_type = "application/json"
@@ -567,7 +567,7 @@ def on_get(req, rep, name, said):
567567
data = CredentialResourceEnd.outputCred(agent.hby, agent.rgy, said)
568568
else:
569569
rep.content_type = "application/json"
570-
creds = agent.rgy.reger.cloneCreds([coring.Saider(qb64=said)])
570+
creds = agent.rgy.reger.cloneCreds([coring.Saider(qb64=said)], db=agent.hby.db)
571571
if not creds:
572572
raise falcon.HTTPNotFound(description=f"credential for said {said} not found.")
573573

@@ -659,7 +659,7 @@ def on_delete(self, req, rep, name, said):
659659
raise falcon.HTTPNotFound(description=f"revocation against invalid registry SAID {regk}")
660660

661661
try:
662-
agent.rgy.reger.cloneCreds([coring.Saider(qb64=said)])
662+
agent.rgy.reger.cloneCreds([coring.Saider(qb64=said)], db=agent.hby.db)
663663
except:
664664
raise falcon.HTTPNotFound(description=f"credential for said {said} not found.")
665665

src/keria/app/ipexing.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,18 @@ def on_post(req, rep, name):
5656

5757
match route:
5858
case "/ipex/admit":
59-
IpexAdmitCollectonEnd.sendAdmit(agent, hab, ked, sigs, atc, rec)
59+
IpexAdmitCollectonEnd.sendAdmit(agent, hab, ked, sigs, rec)
6060
case "/multisig/exn":
6161
IpexAdmitCollectonEnd.sendMultisigExn(agent, hab, ked, sigs, atc, rec)
6262

6363
rep.status = falcon.HTTP_202
6464
rep.data = json.dumps(ked).encode("utf-8")
6565

6666
@staticmethod
67-
def sendAdmit(agent, hab, ked, sigs, atc, rec):
67+
def sendAdmit(agent, hab, ked, sigs, rec):
6868
for recp in rec: # Have to verify we already know all the recipients.
6969
if recp not in agent.hby.kevers:
70-
raise falcon.HTTPBadRequest(f"attempt to send to unknown AID={recp}")
70+
raise falcon.HTTPBadRequest(description=f"attempt to send to unknown AID={recp}")
7171

7272
# use that data to create th Serder and Sigers for the exn
7373
serder = coring.Serder(ked=ked)
@@ -79,35 +79,36 @@ def sendAdmit(agent, hab, ked, sigs, atc, rec):
7979

8080
ims = eventing.messagize(serder=serder, sigers=sigers, seal=seal)
8181

82-
# Have to add the atc to the end... this will be Pathed signatures for embeds
83-
ims.extend(atc.encode("utf-8")) # add the pathed attachments
84-
8582
# make a copy and parse
8683
agent.hby.psr.parseOne(ims=bytearray(ims))
8784

8885
# now get rid of the event so we can pass it as atc to send
8986
del ims[:serder.size]
9087

9188
agent.exchanges.append(dict(said=serder.said, pre=hab.pre, rec=rec, topic='credential'))
92-
agent.admits.append(dict(said=ked['p'], pre=hab.pre))
89+
agent.admits.append(dict(said=ked['d'], pre=hab.pre))
9390

9491
@staticmethod
9592
def sendMultisigExn(agent, hab, ked, sigs, atc, rec):
9693
for recp in rec: # Have to verify we already know all the recipients.
9794
if recp not in agent.hby.kevers:
98-
raise falcon.HTTPBadRequest(f"attempt to send to unknown AID={recp}")
95+
raise falcon.HTTPBadRequest(description=f"attempt to send to unknown AID={recp}")
9996

10097
embeds = ked['e']
10198
admit = embeds['exn']
10299
if admit['r'] != "/ipex/admit":
103-
raise falcon.HTTPBadRequest(f"invalid route for embedded ipex admit {ked['r']}")
100+
raise falcon.HTTPBadRequest(description=f"invalid route for embedded ipex admit {ked['r']}")
101+
102+
# Have to add the atc to the end... this will be Pathed signatures for embeds
103+
if 'exn' not in atc or not atc['exn']:
104+
raise falcon.HTTPBadRequest(description=f"attachment missing for ACDC, unable to process request.")
104105

105106
holder = admit['a']['i']
106107
serder = coring.Serder(ked=admit)
107108
ims = bytearray(serder.raw) + atc['exn'].encode("utf-8")
108109
agent.hby.psr.parseOne(ims=ims)
109110
agent.exchanges.append(dict(said=serder.said, pre=hab.pre, rec=holder, topic="credential"))
110-
agent.admits.append(dict(said=admit['p'], pre=hab.pre))
111+
agent.admits.append(dict(said=admit['d'], pre=hab.pre))
111112

112113
# use that data to create th Serder and Sigers for the exn
113114
serder = coring.Serder(ked=ked)
@@ -119,7 +120,7 @@ def sendMultisigExn(agent, hab, ked, sigs, atc, rec):
119120

120121
ims = eventing.messagize(serder=serder, sigers=sigers, seal=seal)
121122

122-
# Have to add the atc to the end... this will be Pathed signatures for embeds
123+
123124
ims.extend(atc['exn'].encode("utf-8")) # add the pathed attachments
124125

125126
# make a copy and parse

src/keria/db/basing.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,12 @@ def reopen(self, **kwa):
176176

177177
@property
178178
def table(self):
179-
return self.reger.creds
179+
return self.reger.saved
180+
181+
def value(self, said):
182+
saider = self.reger.saved.get(keys=(said,))
183+
creder = self.reger.creds.get(keys=(saider.qb64,))
184+
return creder.crd
180185

181186
def saidIter(self):
182187
return self.reger.saved.getItemIter()
@@ -187,7 +192,6 @@ def createIndex(self, key):
187192
self.dynIdx.pin(keys=(key,), val=IndexRecord(subkey=key, paths=[key]))
188193

189194
def index(self, said):
190-
191195
if (saider := self.reger.saved.get(keys=(said,))) is None:
192196
raise ValueError(f"{said} is not a verified credential")
193197

@@ -358,6 +362,10 @@ def reopen(self, **kwa):
358362
def table(self):
359363
return self.db.exns
360364

365+
def value(self, said):
366+
serder = self.db.exns.get(keys=(said,))
367+
return serder.ked
368+
361369
def saidIter(self):
362370
for (said,), _ in self.db.exns.getItemIter():
363371
yield said
@@ -495,9 +503,9 @@ def fullTableScan(self):
495503
def tableScan(self, saids, ops):
496504
res = []
497505
for said in saids:
498-
creder = self.seeker.table.get(keys=(said,))
506+
val = self.seeker.value(said)
499507
for op in ops:
500-
if op(creder):
508+
if op(val):
501509
res.append(said)
502510

503511
return res
@@ -591,7 +599,7 @@ def __call__(self, *args, **kwargs):
591599
if len(args) != 1:
592600
raise ValueError(f"invalid argument length={len(args)} for equals operator, must be 2")
593601

594-
val = self.pather.resolve(args[0].crd)
602+
val = self.pather.resolve(args[0])
595603
return val == self.value
596604

597605
@property
@@ -615,7 +623,7 @@ def __call__(self, *args, **kwargs):
615623
if len(args) != 1:
616624
raise ValueError(f"invalid argument length={len(args)} for begins operator, must be 2")
617625

618-
val = self.pather.resolve(args[0].crd)
626+
val = self.pather.resolve(args[0])
619627
if not isinstance(val, str):
620628
raise ValueError(f"invalid type={type(args[0])} for begins, must be `str`")
621629

tests/app/test_agenting.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from keri.core import coring
2222
from keri.core.coring import MtrDex
2323
from keri.db import basing
24+
from keri.vc import proving
2425
from keri.vdr import credentialing
2526

2627
from keria.app import agenting, aiding
@@ -388,6 +389,7 @@ def test_querier(helpers):
388389
assert isinstance(qryDoer, querying.QueryDoer) is True
389390
assert qryDoer.pre == "EI7AkI40M11MS7lkTCb10JC9-nDt-tXwQh44OHAFlv_9"
390391

392+
391393
class MockServerTls:
392394
def __init__(self, certify, keypath, certpath, cafilepath, port):
393395
pass
@@ -414,8 +416,29 @@ def test_createHttpServer(monkeypatch):
414416
assert isinstance(server.servant, MockServerTls)
415417

416418

417-
418-
419-
420-
421-
419+
def test_seeker_doer(helpers):
420+
with helpers.openKeria() as (agency, agent, app, client):
421+
cues = decking.Deck()
422+
seeker = agenting.SeekerDoer(agent.seeker, cues)
423+
424+
creder = proving.Creder(ked={
425+
"v": "ACDC10JSON000197_",
426+
"d": "EG7ZlUq0Z6a1EUPTM_Qg1LGEg1BWiypHLAekxo8crGzK",
427+
"i": "EPbOCiPM7IItIMzMwslKWfPM4tqNIKUCyVVuYJNQHwMB",
428+
"ri": "EE5upBEf9JlH0ZCkZwLcNOOQYkiowcF7QBa-SDZg3GLo",
429+
"s": "EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao",
430+
"a": {
431+
"d": "EH8sB2FZuSYBi6dj8edmPMxS-ZoikR2ova3LAVJvelMe",
432+
"i": "ECfRBXooQPoNNQC4i0bkwNfKm-VwV3QsUce14uFfejyj",
433+
"dt": "2023-11-07T23:38:05.508152+00:00",
434+
"LEI": "5493001KJTIIGC8Y1R17"
435+
}
436+
})
437+
438+
assert creder.said == "EG7ZlUq0Z6a1EUPTM_Qg1LGEg1BWiypHLAekxo8crGzK"
439+
440+
cues.append(dict(kin="saved", creder=creder))
441+
442+
result = seeker.recur()
443+
assert result is False
444+
assert len(cues) == 1

tests/app/test_basing.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ def test_seeker(helpers, seeder, mockHelpingNowUTC):
103103
# Assure that no knew index tables needed to be created
104104
assert len(seeker.indexes) == 29
105105

106+
# Test with a bad credential SAID
107+
with pytest.raises(ValueError):
108+
seeker.index("EZ-i0d8JZAoTNZH3ULaU6JR2nmwyvYAfSVPzhzS6b5CM")
109+
106110
# test credemtial with "oneOf"
107111
seeker.generateIndexes(said="EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao")
108112

@@ -270,6 +274,9 @@ def test_exnseeker(helpers, seeder, mockHelpingNowUTC):
270274
parsing.Parser().parseOne(ims=msg, exc=exc)
271275
seeker.index(apply.said)
272276

277+
saids = seeker.find({})
278+
assert list(saids) == [apply.said]
279+
273280
saids = seeker.find({'-i': {'$eq': issuerHab.pre}})
274281
assert list(saids) == [apply.said]
275282

tests/app/test_ipexing.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ def test_ipex_admit(helpers, mockHelpingNowIso8601):
8080
res = client.simulate_post(path="/identifiers/test/ipex/admit", body=data)
8181

8282
assert res.status_code == 400
83-
assert res.json == {'title': 'attempt to send to unknown '
84-
'AID=EZ-i0d8JZAoTNZH3ULaU6JR2nmwyvYAfSVPzhzS6b5CM'}
83+
assert res.json == {'description': 'attempt to send to unknown '
84+
'AID=EZ-i0d8JZAoTNZH3ULaU6JR2nmwyvYAfSVPzhzS6b5CM',
85+
'title': '400 Bad Request'}
8586

8687
body = dict(
8788
exn=exn.ked,
@@ -90,6 +91,11 @@ def test_ipex_admit(helpers, mockHelpingNowIso8601):
9091
rec=[pre1]
9192
)
9293

94+
#Bad Sender
95+
data = json.dumps(body).encode("utf-8")
96+
res = client.simulate_post(path="/identifiers/BAD/ipex/admit", body=data)
97+
assert res.status_code == 404
98+
9399
data = json.dumps(body).encode("utf-8")
94100
res = client.simulate_post(path="/identifiers/test/ipex/admit", body=data)
95101

@@ -109,6 +115,35 @@ def test_ipex_admit(helpers, mockHelpingNowIso8601):
109115
dig=dig,
110116
date=helping.nowIso8601())
111117

118+
# Bad recipient
119+
body = dict(
120+
exn=exn.ked,
121+
sigs=sigs,
122+
atc=dict(exn=end.decode("utf-8")),
123+
rec=["EZ-i0d8JZAoTNZH3ULaU6JR2nmwyvYAfSVPzhzS6b5CM"]
124+
)
125+
126+
data = json.dumps(body).encode("utf-8")
127+
res = client.simulate_post(path="/identifiers/test/ipex/admit", body=data)
128+
assert res.status_code == 400
129+
assert res.json == {'description': 'attempt to send to unknown '
130+
'AID=EZ-i0d8JZAoTNZH3ULaU6JR2nmwyvYAfSVPzhzS6b5CM',
131+
'title': '400 Bad Request'}
132+
133+
# Bad attachments
134+
body = dict(
135+
exn=exn.ked,
136+
sigs=sigs,
137+
atc=dict(bad=end.decode("utf-8")),
138+
rec=[pre1]
139+
)
140+
141+
data = json.dumps(body).encode("utf-8")
142+
res = client.simulate_post(path="/identifiers/test/ipex/admit", body=data)
143+
assert res.status_code == 400
144+
assert res.json == {'description': 'attachment missing for ACDC, unable to process request.',
145+
'title': '400 Bad Request'}
146+
112147
body = dict(
113148
exn=exn.ked,
114149
sigs=sigs,

0 commit comments

Comments
 (0)