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 8d057cf  Improve the public signing key tables
8d057cf is described below

commit 8d057cf79a7da015b8980cb3484998b195fc82ac
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Jun 18 16:20:31 2025 +0100

    Improve the public signing key tables
---
 atr/routes/keys.py              |   2 +
 atr/templates/keys-details.html | 172 ++++++++++++++++++++--------------------
 atr/templates/keys-review.html  | 120 +++++++++-------------------
 3 files changed, 122 insertions(+), 172 deletions(-)

diff --git a/atr/routes/keys.py b/atr/routes/keys.py
index 28518b0..0bdbffb 100644
--- a/atr/routes/keys.py
+++ b/atr/routes/keys.py
@@ -410,6 +410,8 @@ async def keys(session: routes.CommitterSession) -> str:
         user_keys = await data.public_signing_key(apache_uid=session.uid, 
_committees=True).all()
         user_ssh_keys = await data.ssh_key(asf_uid=session.uid).all()
         user_committees_with_keys = await 
data.committee(name_in=committees_to_query, _public_signing_keys=True).all()
+    for key in user_keys:
+        key.committees.sort(key=lambda c: c.name)
 
     status_message = quart.request.args.get("status_message")
     status_type = quart.request.args.get("status_type")
diff --git a/atr/templates/keys-details.html b/atr/templates/keys-details.html
index 4feead3..08bce30 100644
--- a/atr/templates/keys-details.html
+++ b/atr/templates/keys-details.html
@@ -15,98 +15,94 @@
 
   <h1>OpenPGP key details</h1>
 
-  <div class="card p-3 border mb-4">
-    <table class="mb-0">
-      <tbody>
-        <tr>
-          <th class="p-2 text-dark">Fingerprint</th>
-          <td class="text-break">{{ key.fingerprint.upper() }}</td>
-        </tr>
-        <tr>
-          <th class="p-2 text-dark">Type</th>
-          <td class="text-break">{{ algorithms[key.algorithm] }} ({{ 
key.length }} bits)</td>
-        </tr>
-        <tr>
-          <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">
-            {% if key.expires %}
-              {% set days_until_expiry = (key.expires - now).days %}
-              {% if days_until_expiry < 0 %}
-                <span class="text-danger fw-bold">
-                  {{ key.expires.strftime("%Y-%m-%d %H:%M:%S") }}
-                  <span class="badge bg-danger text-white ms-2">Expired</span>
-                </span>
-              {% elif days_until_expiry <= 30 %}
-                <span class="text-warning fw-bold">
-                  {{ key.expires.strftime("%Y-%m-%d %H:%M:%S") }}
-                  <span class="badge bg-warning text-dark ms-2">Expires in {{ 
days_until_expiry }} days</span>
-                </span>
-              {% else %}
+  <table class="mb-0 table border border-2 table-striped table-sm">
+    <tbody>
+      <tr>
+        <th class="p-2 text-dark">Fingerprint</th>
+        <td class="text-break align-middle">{{ key.fingerprint.upper() }}</td>
+      </tr>
+      <tr>
+        <th class="p-2 text-dark">Type</th>
+        <td class="text-break align-middle">{{ algorithms[key.algorithm] }} 
({{ key.length }} bits)</td>
+      </tr>
+      <tr>
+        <th class="p-2 text-dark">Created</th>
+        <td class="text-break align-middle">{{ 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 align-middle">
+          {{ 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 align-middle">
+          {% if key.expires %}
+            {% set days_until_expiry = (key.expires - now).days %}
+            {% if days_until_expiry < 0 %}
+              <span class="text-danger fw-bold">
                 {{ key.expires.strftime("%Y-%m-%d %H:%M:%S") }}
-              {% endif %}
+                <span class="badge bg-danger text-white ms-2">Expired</span>
+              </span>
+            {% elif days_until_expiry <= 30 %}
+              <span class="text-warning fw-bold">
+                {{ key.expires.strftime("%Y-%m-%d %H:%M:%S") }}
+                <span class="badge bg-warning text-dark ms-2">Expires in {{ 
days_until_expiry }} days</span>
+              </span>
             {% else %}
-              Never
+              {{ key.expires.strftime("%Y-%m-%d %H:%M:%S") }}
             {% 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 align-top">Associated PMCs</th>
-          <td class="text-break pt-2">
-            {% if form %}
-              <form method="post" novalidate>
-                {{ form.hidden_tag() }}
-                <div class="row">
-                  {% for subfield in form.selected_committees %}
-                    <div class="col-sm-12 col-md-6 col-lg-4">
-                      <div class="form-check mb-2">
-                        {{ forms.widget(subfield, classes="form-check-input") 
}}
-                        {{ forms.label(subfield, classes="form-check-label") }}
-                      </div>
+          {% else %}
+            Never
+          {% endif %}
+        </td>
+      </tr>
+      <tr>
+        <th class="p-2 text-dark">Primary UID</th>
+        <td class="text-break align-middle">{{ key.primary_declared_uid or '-' 
}}</td>
+      </tr>
+      <tr>
+        <th class="p-2 text-dark">Secondary UIDs</th>
+        <td class="text-break align-middle">
+          {{ key.secondary_declared_uids | join(", ") if 
key.secondary_declared_uids else '-' }}
+        </td>
+      </tr>
+      <tr>
+        <th class="p-2 text-dark">Apache UID</th>
+        <td class="text-break align-middle">{{ key.apache_uid }}</td>
+      </tr>
+      <tr>
+        <th class="p-2 text-dark align-top">Associated PMCs</th>
+        <td class="text-break pt-2">
+          {% if form %}
+            <form method="post" novalidate>
+              {{ form.hidden_tag() }}
+              <div class="row">
+                {% for subfield in form.selected_committees %}
+                  <div class="col-sm-12 col-md-6 col-lg-4">
+                    <div class="form-check mb-2">
+                      {{ forms.widget(subfield, classes="form-check-input") }}
+                      {{ forms.label(subfield, classes="form-check-label") }}
                     </div>
-                  {% endfor %}
-                </div>
-                {{ forms.errors(form.selected_committees, 
classes="invalid-feedback d-block") }}
-                <div class="mt-3">{{ form.submit(class_='btn btn-primary 
btn-sm') }}</div>
-              </form>
+                  </div>
+                {% endfor %}
+              </div>
+              {{ forms.errors(form.selected_committees, 
classes="invalid-feedback d-block") }}
+              <div class="mt-3">{{ form.submit(class_='btn btn-primary 
btn-sm') }}</div>
+            </form>
+          {% else %}
+            {% if key.committees %}
+              {{ key.committees|map(attribute='name') |join(', ') }}
             {% else %}
-              {% if key.committees %}
-                {{ key.committees|map(attribute='name') |join(', ') }}
-              {% else %}
-                No PMCs associated
-              {% endif %}
+              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>
-      <pre class="mt-3">{{ key.ascii_armored_key }}</pre>
-    </details>
-  </div>
+          {% endif %}
+        </td>
+      </tr>
+    </tbody>
+  </table>
+  <h2>ASCII armored key</h2>
+  <pre class="mt-3 border border-2 p-3">{{ key.ascii_armored_key }}</pre>
+  {# TODO: Add download button for the ASCII armored key #}
 {% endblock content %}
diff --git a/atr/templates/keys-review.html b/atr/templates/keys-review.html
index c11d865..f3698c9 100644
--- a/atr/templates/keys-review.html
+++ b/atr/templates/keys-review.html
@@ -19,12 +19,6 @@
   <h2 id="your-public-keys">Your public keys</h2>
   <p>Review your public keys used for signing release artifacts.</p>
 
-  <div>
-    <p>
-      Welcome, <strong>{{ asf_id }}</strong>! You are authenticated as an ASF 
committer.
-    </p>
-  </div>
-
   <div class="d-flex gap-3 mb-4">
     <a href="{{ as_url(routes.keys.add) }}" class="btn 
btn-outline-primary">Add your OpenPGP key</a>
     <a href="{{ as_url(routes.keys.ssh_add) }}"
@@ -34,84 +28,42 @@
   <h3>OpenPGP keys</h3>
 
   {% if user_keys %}
-    <div class="mb-5 p-4 bg-light rounded">
-      <div class="d-grid gap-4">
-        {% for key in user_keys %}
-          <div class="card p-3 border">
-            <table class="mb-0">
-              <tbody>
-                <tr>
-                  <th class="p-2 text-dark">Fingerprint</th>
-                  <td class="text-break">
-                    <a href="{{ as_url(routes.keys.details, 
fingerprint=key.fingerprint) }}">{{ key.fingerprint.upper() }}</a>
-                  </td>
-                </tr>
-                <tr>
-                  <th class="p-2 text-dark">Type</th>
-                  <td class="text-break">{{ algorithms[key.algorithm] }} ({{ 
key.length }} bits)</td>
-                </tr>
-                <tr>
-                  <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">Expires</th>
-                  <td class="text-break">
-                    {% if key.expires %}
-                      {% set days_until_expiry = (key.expires - now).days %}
-                      {% if days_until_expiry < 0 %}
-                        <span class="text-danger fw-bold">
-                          {{ key.expires.strftime("%Y-%m-%d %H:%M:%S") }}
-                          <span class="badge bg-danger text-white 
ms-2">Expired</span>
-                        </span>
-                      {% elif days_until_expiry <= 30 %}
-                        <span class="text-warning fw-bold">
-                          {{ key.expires.strftime("%Y-%m-%d %H:%M:%S") }}
-                          <span class="badge bg-warning text-dark 
ms-2">Expires in {{ days_until_expiry }} days</span>
-                        </span>
-                      {% else %}
-                        {{ key.expires.strftime("%Y-%m-%d %H:%M:%S") }}
-                      {% endif %}
-                    {% else %}
-                      Never
-                    {% endif %}
-                  </td>
-                </tr>
-                <tr>
-                  <th class="p-2 text-dark">User ID</th>
-                  <td class="text-break">{{ key.apache_uid or 'Not specified' 
}}</td>
-                </tr>
-                <tr>
-                  <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>
-
-            <!-- TODO: We could link to a downloadable version of the key 
instead -->
-            <details class="mt-3 p-3 bg-light rounded">
-              <summary class="fw-bold">View whole key</summary>
-              <pre class="mt-3">{{ key.ascii_armored_key }}</pre>
-            </details>
-
-            <form method="post"
-                  action="{{ as_url(routes.keys.delete) }}"
-                  class="mt-3"
-                  onsubmit="return confirm('Are you sure you want to delete 
this OpenPGP key?');">
-              {{ delete_form.hidden_tag() }}
-
-              <input type="hidden" name="fingerprint" value="{{ 
key.fingerprint }}" />
-              {{ delete_form.submit(class_='btn btn-danger', value='Delete 
key') }}
-            </form>
-          </div>
-        {% endfor %}
-      </div>
+    <div class="table-responsive mb-5">
+      <table class="table border table-striped table-hover table-sm">
+        <thead>
+          <tr>
+            <th class="px-2" scope="col">Key ID</th>
+            <th class="px-2" scope="col">Committees</th>
+            <th class="px-2" scope="col">Action</th>
+          </tr>
+        </thead>
+        <tbody>
+          {% for key in user_keys %}
+            <tr>
+              <td class="text-break px-2 align-middle">
+                <a href="{{ as_url(routes.keys.details, 
fingerprint=key.fingerprint) }}">{{ key.fingerprint[-16:]|upper }}</a>
+              </td>
+              <td class="text-break px-2 align-middle">
+                {% if key.committees %}
+                  {{ key.committees|map(attribute='name') |join(', ') }}
+                {% else %}
+                  No PMCs associated
+                {% endif %}
+              </td>
+              <td class="px-2">
+                <form method="post"
+                      action="{{ as_url(routes.keys.delete) }}"
+                      class="m-0"
+                      onsubmit="return confirm('Are you sure you want to 
delete this OpenPGP key?');">
+                  {{ delete_form.hidden_tag() }}
+                  <input type="hidden" name="fingerprint" value="{{ 
key.fingerprint }}" />
+                  {{ delete_form.submit(class_='btn btn-sm btn-danger', 
value='Delete key') }}
+                </form>
+              </td>
+            </tr>
+          {% endfor %}
+        </tbody>
+      </table>
     </div>
   {% else %}
     <p>


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

Reply via email to