From 9107d02351078e93b8a76cbe6cada464a83ef06b Mon Sep 17 00:00:00 2001 From: Fergal Date: Fri, 6 Dec 2024 15:46:52 -0300 Subject: [PATCH] feat: delete/remove credential endpoint (#330) --- src/keria/app/credentialing.py | 49 +++++++++++++++++++++++++++++++++ tests/app/test_credentialing.py | 16 +++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/keria/app/credentialing.py b/src/keria/app/credentialing.py index 54c981b8..36d4f64b 100644 --- a/src/keria/app/credentialing.py +++ b/src/keria/app/credentialing.py @@ -789,6 +789,55 @@ def outputCred(hby, rgy, said): return out + @staticmethod + def on_delete(req, rep, said): + """ Credentials DELETE endpoint + + Parameters: + req: falcon.Request HTTP request + rep: falcon.Response HTTP response + said (str): SAID of credential to delete + + --- + summary: Delete a credential from the database + description: Delete a credential from the database and remove any associated indices + tags: + - Credentials + parameters: + - in: path + name: said + schema: + type: string + required: true + description: SAID of credential to delete + responses: + 204: + description: Credential deleted successfully + 400: + description: The requested credential was not found + """ + reger = req.context.agent.rgy.reger + + try: + creder, _, _, _ = reger.cloneCred(said) + except kering.MissingEntryError: + raise falcon.HTTPNotFound(description=f"credential for said {said} not found.") + + saider = coring.Saider(qb64b=said) + + if not isinstance(creder.attrib, str) and 'i' in creder.attrib: + subj = creder.attrib["i"] + if subj: + reger.subjs.rem(keys=subj, val=saider) + + reger.schms.rem(keys=creder.sad["s"], val=saider) + reger.issus.rem(keys=creder.sad["i"], val=saider) + reger.saved.rem(keys=said) + reger.creds.rem(keys=said) + reger.cancs.rem(keys=said) + + rep.status = falcon.HTTP_204 + class CredentialResourceDeleteEnd: def __init__(self, identifierResource): diff --git a/tests/app/test_credentialing.py b/tests/app/test_credentialing.py index 562f6664..8632b03a 100644 --- a/tests/app/test_credentialing.py +++ b/tests/app/test_credentialing.py @@ -487,6 +487,22 @@ def test_credentialing_ends(helpers, seeder): assert res.json == {'description': f"registry EBVaw6pCqfMIiZGkA6qevzRUGsxTRuZXxl6YG1neeCGF not found", 'title': '404 Not Found'} + res = client.simulate_delete(f"/credentials/doesnotexist") + assert res.status_code == 404 + assert res.json == {'description': f"credential for said doesnotexist not found.", + 'title': '404 Not Found'} + + res = client.simulate_delete(f"/credentials/{saids[0]}") + assert res.status_code == 204 + + # Check db directly to make sure all indices are gone too (GET endpoints don't cover all indices) + assert agent.rgy.reger.creds.get(keys=saids[0]) is None + assert agent.rgy.reger.cancs.get(keys=saids[0]) is None + assert agent.rgy.reger.saved.get(keys=saids[0]) is None + assert agent.rgy.reger.issus.cnt(keys=hab.pre) == 4 + assert agent.rgy.reger.schms.cnt(keys="EFgnk_c08WmZGgv9_mpldibRuqFMTQN-rAgtD-TCOwbs") == 1 + assert agent.rgy.reger.subjs.cnt(keys=issuee) == 4 + def test_revoke_credential(helpers, seeder): with helpers.openKeria() as (agency, agent, app, client):