Skip to content

Commit

Permalink
Updates to make credential admit fully work (#122)
Browse files Browse the repository at this point in the history
* Ensure that ipex admit API does not attempt to parse an embedded ACDC without an attachment.

Signed-off-by: pfeairheller <[email protected]>

* 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 <[email protected]>

* 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 <[email protected]>

* Adding test coverage to patch.

Signed-off-by: pfeairheller <[email protected]>

---------

Signed-off-by: pfeairheller <[email protected]>
  • Loading branch information
pfeairheller authored Nov 8, 2023
1 parent f80d976 commit 839ce4f
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 31 deletions.
18 changes: 14 additions & 4 deletions src/keria/app/agenting.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,9 @@ def recur(self, tyme):
self.admits.append(msg)
return False

admit, _ = exchanging.cloneMessage(self.hby, said)
hab = self.hby.habs[msg['pre']]
grant, pathed = exchanging.cloneMessage(self.hby, said)
grant, pathed = exchanging.cloneMessage(self.hby, admit.ked['p'])

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

for label in ("anc", "iss", "acdc"):
ked = embeds[label]
if label not in pathed or not pathed[label]:
continue

sadder = coring.Sadder(ked=ked)
ims = bytearray(sadder.raw) + pathed[label]
self.psr.parseOne(ims=ims)
Expand All @@ -540,8 +544,14 @@ def recur(self, tyme=None):
cue = self.cues.popleft()
if cue["kin"] == "saved":
creder = cue["creder"]
print(f"indexing {creder.said}")
self.seeker.index(said=creder.said)
try:
self.seeker.index(said=creder.said)
except Exception:
self.cues.append(cue)
return False
else:
self.cues.append(cue)
return False


class ExnSeekerDoer(doing.Doer):
Expand Down
6 changes: 3 additions & 3 deletions src/keria/app/credentialing.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ def on_post(req, rep, name):

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

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

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

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

Expand Down
23 changes: 12 additions & 11 deletions src/keria/app/ipexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,18 @@ def on_post(req, rep, name):

match route:
case "/ipex/admit":
IpexAdmitCollectonEnd.sendAdmit(agent, hab, ked, sigs, atc, rec)
IpexAdmitCollectonEnd.sendAdmit(agent, hab, ked, sigs, rec)
case "/multisig/exn":
IpexAdmitCollectonEnd.sendMultisigExn(agent, hab, ked, sigs, atc, rec)

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

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

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

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

# Have to add the atc to the end... this will be Pathed signatures for embeds
ims.extend(atc.encode("utf-8")) # add the pathed attachments

# make a copy and parse
agent.hby.psr.parseOne(ims=bytearray(ims))

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

agent.exchanges.append(dict(said=serder.said, pre=hab.pre, rec=rec, topic='credential'))
agent.admits.append(dict(said=ked['p'], pre=hab.pre))
agent.admits.append(dict(said=ked['d'], pre=hab.pre))

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

embeds = ked['e']
admit = embeds['exn']
if admit['r'] != "/ipex/admit":
raise falcon.HTTPBadRequest(f"invalid route for embedded ipex admit {ked['r']}")
raise falcon.HTTPBadRequest(description=f"invalid route for embedded ipex admit {ked['r']}")

# Have to add the atc to the end... this will be Pathed signatures for embeds
if 'exn' not in atc or not atc['exn']:
raise falcon.HTTPBadRequest(description=f"attachment missing for ACDC, unable to process request.")

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

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

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

# Have to add the atc to the end... this will be Pathed signatures for embeds

ims.extend(atc['exn'].encode("utf-8")) # add the pathed attachments

# make a copy and parse
Expand Down
20 changes: 14 additions & 6 deletions src/keria/db/basing.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,12 @@ def reopen(self, **kwa):

@property
def table(self):
return self.reger.creds
return self.reger.saved

def value(self, said):
saider = self.reger.saved.get(keys=(said,))
creder = self.reger.creds.get(keys=(saider.qb64,))
return creder.crd

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

def index(self, said):

if (saider := self.reger.saved.get(keys=(said,))) is None:
raise ValueError(f"{said} is not a verified credential")

Expand Down Expand Up @@ -358,6 +362,10 @@ def reopen(self, **kwa):
def table(self):
return self.db.exns

def value(self, said):
serder = self.db.exns.get(keys=(said,))
return serder.ked

def saidIter(self):
for (said,), _ in self.db.exns.getItemIter():
yield said
Expand Down Expand Up @@ -495,9 +503,9 @@ def fullTableScan(self):
def tableScan(self, saids, ops):
res = []
for said in saids:
creder = self.seeker.table.get(keys=(said,))
val = self.seeker.value(said)
for op in ops:
if op(creder):
if op(val):
res.append(said)

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

val = self.pather.resolve(args[0].crd)
val = self.pather.resolve(args[0])
return val == self.value

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

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

Expand Down
33 changes: 28 additions & 5 deletions tests/app/test_agenting.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from keri.core import coring
from keri.core.coring import MtrDex
from keri.db import basing
from keri.vc import proving
from keri.vdr import credentialing

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


class MockServerTls:
def __init__(self, certify, keypath, certpath, cafilepath, port):
pass
Expand All @@ -414,8 +416,29 @@ def test_createHttpServer(monkeypatch):
assert isinstance(server.servant, MockServerTls)







def test_seeker_doer(helpers):
with helpers.openKeria() as (agency, agent, app, client):
cues = decking.Deck()
seeker = agenting.SeekerDoer(agent.seeker, cues)

creder = proving.Creder(ked={
"v": "ACDC10JSON000197_",
"d": "EG7ZlUq0Z6a1EUPTM_Qg1LGEg1BWiypHLAekxo8crGzK",
"i": "EPbOCiPM7IItIMzMwslKWfPM4tqNIKUCyVVuYJNQHwMB",
"ri": "EE5upBEf9JlH0ZCkZwLcNOOQYkiowcF7QBa-SDZg3GLo",
"s": "EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao",
"a": {
"d": "EH8sB2FZuSYBi6dj8edmPMxS-ZoikR2ova3LAVJvelMe",
"i": "ECfRBXooQPoNNQC4i0bkwNfKm-VwV3QsUce14uFfejyj",
"dt": "2023-11-07T23:38:05.508152+00:00",
"LEI": "5493001KJTIIGC8Y1R17"
}
})

assert creder.said == "EG7ZlUq0Z6a1EUPTM_Qg1LGEg1BWiypHLAekxo8crGzK"

cues.append(dict(kin="saved", creder=creder))

result = seeker.recur()
assert result is False
assert len(cues) == 1
7 changes: 7 additions & 0 deletions tests/app/test_basing.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ def test_seeker(helpers, seeder, mockHelpingNowUTC):
# Assure that no knew index tables needed to be created
assert len(seeker.indexes) == 29

# Test with a bad credential SAID
with pytest.raises(ValueError):
seeker.index("EZ-i0d8JZAoTNZH3ULaU6JR2nmwyvYAfSVPzhzS6b5CM")

# test credemtial with "oneOf"
seeker.generateIndexes(said="EBfdlu8R27Fbx-ehrqwImnK-8Cm79sqbAQ4MmvEAYqao")

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

saids = seeker.find({})
assert list(saids) == [apply.said]

saids = seeker.find({'-i': {'$eq': issuerHab.pre}})
assert list(saids) == [apply.said]

Expand Down
39 changes: 37 additions & 2 deletions tests/app/test_ipexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ def test_ipex_admit(helpers, mockHelpingNowIso8601):
res = client.simulate_post(path="/identifiers/test/ipex/admit", body=data)

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

body = dict(
exn=exn.ked,
Expand All @@ -90,6 +91,11 @@ def test_ipex_admit(helpers, mockHelpingNowIso8601):
rec=[pre1]
)

#Bad Sender
data = json.dumps(body).encode("utf-8")
res = client.simulate_post(path="/identifiers/BAD/ipex/admit", body=data)
assert res.status_code == 404

data = json.dumps(body).encode("utf-8")
res = client.simulate_post(path="/identifiers/test/ipex/admit", body=data)

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

# Bad recipient
body = dict(
exn=exn.ked,
sigs=sigs,
atc=dict(exn=end.decode("utf-8")),
rec=["EZ-i0d8JZAoTNZH3ULaU6JR2nmwyvYAfSVPzhzS6b5CM"]
)

data = json.dumps(body).encode("utf-8")
res = client.simulate_post(path="/identifiers/test/ipex/admit", body=data)
assert res.status_code == 400
assert res.json == {'description': 'attempt to send to unknown '
'AID=EZ-i0d8JZAoTNZH3ULaU6JR2nmwyvYAfSVPzhzS6b5CM',
'title': '400 Bad Request'}

# Bad attachments
body = dict(
exn=exn.ked,
sigs=sigs,
atc=dict(bad=end.decode("utf-8")),
rec=[pre1]
)

data = json.dumps(body).encode("utf-8")
res = client.simulate_post(path="/identifiers/test/ipex/admit", body=data)
assert res.status_code == 400
assert res.json == {'description': 'attachment missing for ACDC, unable to process request.',
'title': '400 Bad Request'}

body = dict(
exn=exn.ked,
sigs=sigs,
Expand Down

0 comments on commit 839ce4f

Please sign in to comment.