This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-release.git


The following commit(s) were added to refs/heads/main by this push:
     new 601941c  Add an API endpoint to delete an OpenPGP key
601941c is described below

commit 601941c3e37cb145004c529d840be040936a175e
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Jul 16 18:33:58 2025 +0100

    Add an API endpoint to delete an OpenPGP key
---
 atr/blueprints/api/api.py | 23 +++++++++++++++++++++++
 atr/models/api.py         | 33 ++++++++++++++++++++++-----------
 2 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/atr/blueprints/api/api.py b/atr/blueprints/api/api.py
index 18b95ca..394415a 100644
--- a/atr/blueprints/api/api.py
+++ b/atr/blueprints/api/api.py
@@ -328,6 +328,29 @@ async def keys_add(data: models.api.KeysAddArgs) -> 
DictResponse:
     ).model_dump(), 200
 
 
[email protected]("/keys/delete", methods=["POST"])
[email protected]
+@quart_schema.security_scheme([{"BearerAuth": []}])
+@quart_schema.validate_request(models.api.KeysDeleteArgs)
+@quart_schema.validate_response(models.api.KeysDeleteResults, 200)
+async def keys_delete(data: models.api.KeysDeleteArgs) -> DictResponse:
+    asf_uid = _jwt_asf_uid()
+    fingerprint = data.fingerprint.lower()
+    async with db.session() as db_data:
+        key = await db_data.public_signing_key(fingerprint=fingerprint, 
apache_uid=asf_uid, _committees=True).demand(
+            exceptions.NotFound()
+        )
+        await db_data.delete(key)
+        for committee in key.committees:
+            await keys.autogenerate_keys_file(committee.name, 
committee.is_podling)
+        await db_data.commit()
+
+    return models.api.KeysDeleteResults(
+        endpoint="/keys/delete",
+        success="Key deleted",
+    ).model_dump(), 200
+
+
 @api.BLUEPRINT.route("/keys/committee/<committee>")
 @quart_schema.validate_response(models.api.KeysUserResults, 200)
 async def keys_committee(committee: str) -> DictResponse:
diff --git a/atr/models/api.py b/atr/models/api.py
index be659ef..336ab2e 100644
--- a/atr/models/api.py
+++ b/atr/models/api.py
@@ -101,6 +101,18 @@ class JwtResults(schema.Strict):
     jwt: str
 
 
[email protected]
+class KeysQuery:
+    offset: int = 0
+    limit: int = 20
+
+
+class KeysResults(schema.Strict):
+    endpoint: Literal["/keys"] = schema.Field(alias="endpoint")
+    data: Sequence[sql.PublicSigningKey]
+    count: int
+
+
 class KeysAddArgs(schema.Strict):
     asfuid: str
     key: str
@@ -113,21 +125,18 @@ class KeysAddResults(schema.Strict):
     fingerprints: list[str]
 
 
[email protected]
-class KeysQuery:
-    offset: int = 0
-    limit: int = 20
+class KeysCommitteeResults(schema.Strict):
+    endpoint: Literal["/keys/committee"] = schema.Field(alias="endpoint")
+    keys: Sequence[sql.PublicSigningKey]
 
 
-class KeysResults(schema.Strict):
-    endpoint: Literal["/keys"] = schema.Field(alias="endpoint")
-    data: Sequence[sql.PublicSigningKey]
-    count: int
+class KeysDeleteArgs(schema.Strict):
+    fingerprint: str
 
 
-class KeysCommitteeResults(schema.Strict):
-    endpoint: Literal["/keys/committee"] = schema.Field(alias="endpoint")
-    keys: Sequence[sql.PublicSigningKey]
+class KeysDeleteResults(schema.Strict):
+    endpoint: Literal["/keys/delete"] = schema.Field(alias="endpoint")
+    success: str
 
 
 class KeysGetResults(schema.Strict):
@@ -317,6 +326,7 @@ Results = Annotated[
     | JwtResults
     | KeysResults
     | KeysAddResults
+    | KeysDeleteResults
     | KeysGetResults
     | KeysCommitteeResults
     | KeysUserResults
@@ -367,6 +377,7 @@ validate_jwt = validator(JwtResults)
 validate_keys = validator(KeysResults)
 validate_keys_add = validator(KeysAddResults)
 validate_keys_committee = validator(KeysCommitteeResults)
+validate_keys_delete = validator(KeysDeleteResults)
 validate_keys_get = validator(KeysGetResults)
 validate_keys_user = validator(KeysUserResults)
 validate_list = validator(ListResults)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to