Skip to content

Commit

Permalink
feat: endpoint to process credential from (acdc, iss) without IPEX (W…
Browse files Browse the repository at this point in the history
…ebOfTrust#297)

* feat: endpoint to process credential from (acdc, iss) without IPEX

* refactor: rename process to verify for credential verification endpoint
  • Loading branch information
iFergal authored Sep 25, 2024
1 parent 8dcfcfb commit 6e6f1f8
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 2 deletions.
66 changes: 66 additions & 0 deletions src/keria/app/credentialing.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ def loadEnds(app, identifierResource):
queryCollectionEnd = CredentialQueryCollectionEnd()
app.add_route("/credentials/query", queryCollectionEnd)

credentialVerificationEnd = CredentialVerificationCollectionEnd()
app.add_route("/credentials/verify", credentialVerificationEnd)


class RegistryCollectionEnd:
"""
Expand Down Expand Up @@ -407,6 +410,69 @@ def on_get(req, rep):
rep.data = json.dumps(data).encode("utf-8")


class CredentialVerificationCollectionEnd:
@staticmethod
def on_post(req, rep):
""" Verify credential endpoint (no IPEX)
Parameters:
req: falcon.Request HTTP request
rep: falcon.Response HTTP response
---
summary: Verify a credential without IPEX
description: Verify a credential without using IPEX (TEL should be updated separately)
tags:
- Credentials
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- acdc
- iss
properties:
acdc:
type: object
description: KED of ACDC
iss:
type: object
description: KED of issuing event in VC TEL
responses:
202:
description: Credential accepted for parsing
content:
application/json:
schema:
description: long running operation of credential processing
type: object
404:
description: Malformed ACDC or iss event
"""
agent = req.context.agent
body = req.get_media()

try:
creder = serdering.SerderACDC(sad=httping.getRequiredParam(body, "acdc"))
iserder = serdering.SerderKERI(sad=httping.getRequiredParam(body, "iss"))
except (kering.ValidationError, json.decoder.JSONDecodeError) as e:
rep.status = falcon.HTTP_400
rep.text = e.args[0]
return

prefixer = coring.Prefixer(qb64=iserder.pre)
seqner = coring.Seqner(sn=iserder.sn)
saider = coring.Saider(qb64=iserder.said)

agent.parser.ims.extend(signing.serialize(creder, prefixer, seqner, saider))
op = agent.monitor.submit(creder.said, longrunning.OpTypes.credential,
metadata=dict(ced=creder.sad))
rep.status = falcon.HTTP_202
rep.data = op.to_json().encode("utf-8")


class CredentialQueryCollectionEnd:
""" This class provides a collection endpoint for creating credential queries.
Expand Down
32 changes: 30 additions & 2 deletions tests/app/test_credentialing.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ def test_registry_end(helpers, seeder):


def test_issue_credential(helpers, seeder):
with helpers.openKeria() as (agency, agent, app, client):
with (helpers.openKeria() as (agency, agent, app, client),
helpers.openKeria() as (agency1, agent1, app1, client1)):
idResEnd = aiding.IdentifierResourceEnd()
app.add_route("/identifiers/{name}", idResEnd)
registryEnd = credentialing.RegistryCollectionEnd(idResEnd)
Expand All @@ -238,6 +239,7 @@ def test_issue_credential(helpers, seeder):
app.add_route("/identifiers/{name}/endroles", endRolesEnd)

seeder.seedSchema(agent.hby.db)
seeder.seedSchema(agent1.hby.db)

# create the server that will receive the credential issuance messages
serverDoer = helpers.server(agency)
Expand Down Expand Up @@ -293,7 +295,7 @@ def test_issue_credential(helpers, seeder):
assert result.status_code == 404
assert result.json == {'description': "badname is not a valid reference to an identifier",
'title': '404 Not Found'}

result = client.simulate_post(path="/identifiers/issuer/credentials", body=json.dumps(body).encode("utf-8"))
op = result.json

Expand All @@ -309,6 +311,32 @@ def test_issue_credential(helpers, seeder):
result = client.simulate_post(path="/identifiers/issuer/credentials", body=json.dumps(body).encode("utf-8"))
assert result.status_code == 400

# Try to load into another agent after TEL query without IPEX
agent1.parser.parse(ims=agent.hby.habByName("issuer").replay())
assert iaid in agent1.hby.kevers

agent1.parser.parse(ims=agent.rgy.reger.cloneTvtAt(registry["regk"]))
assert registry["regk"] in agent1.rgy.tevers

agent1.parser.parse(ims=agent.rgy.reger.cloneTvtAt(creder.said))
assert agent1.rgy.tevers[registry["regk"]].vcSn(creder.said) is not None

credVerifyEnd = credentialing.CredentialVerificationCollectionEnd()
app1.add_route("/credentials/verify", credVerifyEnd)

body = dict(acdc=creder.sad, iss=regser.ked) # still has changed LEI
result = client1.simulate_post(path="/credentials/verify", body=json.dumps(body).encode("utf-8"))
assert result.status_code == 400

body["acdc"]["a"]["LEI"] = "254900DA0GOGCFVWB618" # change back
result = client1.simulate_post(path="/credentials/verify", body=json.dumps(body).encode("utf-8"))
assert result.status_code == 202

deeds = doist.enter(doers=[agent1])
while not agent1.rgy.reger.creds.get(keys=(creder.said,)):
doist.recur(deeds=deeds)


def test_credentialing_ends(helpers, seeder):
salt = b'0123456789abcdef'

Expand Down

0 comments on commit 6e6f1f8

Please sign in to comment.