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 42ef019  Improve the display of public signing keys
42ef019 is described below

commit 42ef019d7639ffa53caa126123dd394e29823425
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Jun 18 14:53:24 2025 +0100

    Improve the display of public signing keys
---
 atr/routes/keys.py                | 73 ++++++++++++++++++++-------------------
 atr/templates/committee-view.html |  2 +-
 atr/templates/keys-review.html    |  4 +--
 atr/templates/keys-show-gpg.html  | 28 +++++++++++++--
 4 files changed, 65 insertions(+), 42 deletions(-)

diff --git a/atr/routes/keys.py b/atr/routes/keys.py
index 451bca8..baa5de8 100644
--- a/atr/routes/keys.py
+++ b/atr/routes/keys.py
@@ -34,7 +34,6 @@ import asfquart as asfquart
 import asfquart.base as base
 import httpx
 import quart
-import sqlmodel
 import werkzeug.datastructures as datastructures
 import werkzeug.wrappers.response as response
 import wtforms
@@ -256,8 +255,44 @@ async def delete(session: routes.CommitterSession) -> 
response.Response:
             return await session.redirect(keys, error="Key not found or not 
owned by you")
 
 
[email protected]("/keys/details/<fingerprint>", methods=["GET"])
+async def details(session: routes.CommitterSession, fingerprint: str) -> str:
+    """Display details for a specific GPG key."""
+    async with db.session() as data:
+        key = await data.public_signing_key(fingerprint=fingerprint, 
_committees=True).get()
+
+    if not key:
+        quart.abort(404, description="GPG key not found")
+    key.committees.sort(key=lambda c: c.name)
+
+    authorised = False
+    if key.apache_uid == session.uid:
+        authorised = True
+    else:
+        user_affiliations = set(session.committees + session.projects)
+        # async with db.session() as data:
+        #     key_committees = await data.execute(
+        #         
sqlmodel.select(models.KeyLink.committee_name).where(models.KeyLink.key_fingerprint
 == fingerprint)
+        #     )
+        #     key_committee_names = {row[0] for row in key_committees.all()}
+        key_committee_names = {c.name for c in key.committees}
+        if user_affiliations.intersection(key_committee_names):
+            authorised = True
+
+    if not authorised:
+        quart.abort(403, description="You are not authorised to view this key")
+
+    return await template.render(
+        "keys-show-gpg.html",
+        key=key,
+        algorithms=routes.algorithms,
+        now=datetime.datetime.now(datetime.UTC),
+        asf_id=session.uid,
+    )
+
+
 @routes.committer("/keys/export/<committee_name>")
-async def exports(session: routes.CommitterSession, committee_name: str) -> 
quart.Response:
+async def export(session: routes.CommitterSession, committee_name: str) -> 
quart.Response:
     """Generate a KEYS file for a specific committee."""
     if committee_name not in (session.committees + session.projects):
         quart.abort(403, description=f"You are not authorised to update the 
KEYS file for {committee_name}")
@@ -365,40 +400,6 @@ async def keys(session: routes.CommitterSession) -> str:
     )
 
 
[email protected]("/keys/show-gpg/<fingerprint>", methods=["GET"])
-async def show_gpg_key(session: routes.CommitterSession, fingerprint: str) -> 
str:
-    """Display details for a specific GPG key."""
-    async with db.session() as data:
-        key = await data.public_signing_key(fingerprint=fingerprint).get()
-
-    if not key:
-        quart.abort(404, description="GPG key not found")
-
-    authorised = False
-    if key.apache_uid == session.uid:
-        authorised = True
-    else:
-        user_affiliations = set(session.committees + session.projects)
-        async with db.session() as data:
-            key_committees = await data.execute(
-                
sqlmodel.select(models.KeyLink.committee_name).where(models.KeyLink.key_fingerprint
 == fingerprint)
-            )
-            key_committee_names = {row[0] for row in key_committees.all()}
-        if user_affiliations.intersection(key_committee_names):
-            authorised = True
-
-    if not authorised:
-        quart.abort(403, description="You are not authorised to view this key")
-
-    return await template.render(
-        "keys-show-gpg.html",
-        key=key,
-        algorithms=routes.algorithms,
-        now=datetime.datetime.now(datetime.UTC),
-        asf_id=session.uid,
-    )
-
-
 @routes.committer("/keys/ssh/add", methods=["GET", "POST"])
 async def ssh_add(session: routes.CommitterSession) -> response.Response | str:
     """Add a new SSH key to the user's account."""
diff --git a/atr/templates/committee-view.html 
b/atr/templates/committee-view.html
index bc8c133..53c7c61 100644
--- a/atr/templates/committee-view.html
+++ b/atr/templates/committee-view.html
@@ -63,7 +63,7 @@
               {% for key in committee.public_signing_keys %}
                 <tr>
                   <td class="text-break font-monospace px-2">
-                    <a href="{{ as_url(routes.keys.show_gpg_key, 
fingerprint=key.fingerprint) }}">{{ key.fingerprint[:16]|upper }}</a>
+                    <a href="{{ as_url(routes.keys.details, 
fingerprint=key.fingerprint) }}">{{ key.fingerprint[:16]|upper }}</a>
                   </td>
                   <td class="text-break px-2">{{ 
email_from_key(key.primary_declared_uid) or 'Not specified' }}</td>
                   <td class="text-break px-2">{{ key.apache_uid or "-" }}</td>
diff --git a/atr/templates/keys-review.html b/atr/templates/keys-review.html
index 825b2cc..0edbd38 100644
--- a/atr/templates/keys-review.html
+++ b/atr/templates/keys-review.html
@@ -77,7 +77,7 @@
                 </tr>
                 <tr>
                   <th class="p-2 text-dark">User ID</th>
-                  <td class="text-break">{{ key.declared_uid or 'Not 
specified' }}</td>
+                  <td class="text-break">{{ key.apache_uid or 'Not specified' 
}}</td>
                 </tr>
                 <tr>
                   <th class="p-2 text-dark">Associated PMCs</th>
@@ -182,7 +182,7 @@
               {% for key in committee.public_signing_keys %}
                 <tr>
                   <td class="text-break font-monospace px-2">
-                    <a href="{{ as_url(routes.keys.show_gpg_key, 
fingerprint=key.fingerprint) }}">{{ key.fingerprint[:16]|upper }}</a>
+                    <a href="{{ as_url(routes.keys.details, 
fingerprint=key.fingerprint) }}">{{ key.fingerprint[:16]|upper }}</a>
                   </td>
                   <td class="text-break px-2">{{ 
email_from_key(key.primary_declared_uid) or 'Not specified' }}</td>
                   <td class="text-break px-2">{{ key.apache_uid or "-" }}</td>
diff --git a/atr/templates/keys-show-gpg.html b/atr/templates/keys-show-gpg.html
index 5b5ecb9..94cff5d 100644
--- a/atr/templates/keys-show-gpg.html
+++ b/atr/templates/keys-show-gpg.html
@@ -30,6 +30,12 @@
           <th class="p-2 text-dark">Created</th>
           <td class="text-break">{{ key.created.strftime("%Y-%m-%d %H:%M:%S") 
}}</td>
         </tr>
+        <tr>
+          <th class="p-2 text-dark">Latest self signature</th>
+          <td class="text-break">
+            {{ key.latest_self_signature.strftime("%Y-%m-%d %H:%M:%S") if 
key.latest_self_signature else 'Never' }}
+          </td>
+        </tr>
         <tr>
           <th class="p-2 text-dark">Expires</th>
           <td class="text-break">
@@ -53,19 +59,35 @@
             {% endif %}
           </td>
         </tr>
+        <tr>
+          <th class="p-2 text-dark">Primary UID</th>
+          <td class="text-break">{{ key.primary_declared_uid or 'Not 
specified' }}</td>
+        </tr>
+        <tr>
+          <th class="p-2 text-dark">Secondary UIDs</th>
+          <td class="text-break">
+            {{ key.secondary_declared_uids | join(", ") if 
key.secondary_declared_uids else 'Not specified' }}
+          </td>
+        </tr>
         <tr>
           <th class="p-2 text-dark">Apache UID</th>
           <td class="text-break">{{ key.apache_uid }}</td>
         </tr>
         <tr>
-          <th class="p-2 text-dark">Declared UID</th>
-          <td class="text-break">{{ key.declared_uid or 'Not specified' }}</td>
+          <th class="p-2 text-dark">Associated PMCs</th>
+          <td class="text-break">
+            {% if key.committees %}
+              {{ key.committees|map(attribute='name') |join(', ') }}
+            {% else %}
+              No PMCs associated
+            {% endif %}
+          </td>
         </tr>
       </tbody>
     </table>
 
     <details class="mt-3 p-3 bg-light rounded">
-      <summary class="fw-bold">View ASCII Armored Key</summary>
+      <summary class="fw-bold">View ASCII armored key</summary>
       <pre class="mt-3">{{ key.ascii_armored_key }}</pre>
     </details>
   </div>


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

Reply via email to