Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading