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 90356d4  Show user SSH keys and advice next to each rsync command
90356d4 is described below

commit 90356d4eee023a78ef52632949184e965edf140a
Author: Sean B. Palmer <[email protected]>
AuthorDate: Thu May 1 17:13:26 2025 +0100

    Show user SSH keys and advice next to each rsync command
---
 atr/routes/compose.py              |  7 +++++++
 atr/routes/finish.py               |  9 ++++++++-
 atr/routes/upload.py               |  9 ++++++++-
 atr/templates/check-selected.html  |  3 ++-
 atr/templates/finish-selected.html |  4 +++-
 atr/templates/keys-review.html     |  2 +-
 atr/templates/upload-selected.html |  4 +++-
 atr/templates/user-ssh-keys.html   | 31 +++++++++++++++++++++++++++++++
 8 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/atr/routes/compose.py b/atr/routes/compose.py
index 114e395..26a7a2e 100644
--- a/atr/routes/compose.py
+++ b/atr/routes/compose.py
@@ -16,6 +16,7 @@
 # under the License.
 
 import re
+from typing import TYPE_CHECKING
 
 import quart
 import werkzeug.wrappers.response as response
@@ -29,6 +30,9 @@ import atr.routes as routes
 import atr.routes.draft as draft
 import atr.util as util
 
+if TYPE_CHECKING:
+    from collections.abc import Sequence
+
 
 async def check(
     session: routes.CommitterSession,
@@ -45,6 +49,7 @@ async def check(
     path_successes = {}
     path_warnings = {}
     path_errors = {}
+    user_ssh_keys: Sequence[models.SSHKey] = []
 
     for path in paths:
         # Get template and substitutions
@@ -78,6 +83,7 @@ async def check(
             path_errors[path] = await data.check_result(
                 release_name=release.name, primary_rel_path=str(path), 
status=models.CheckResultStatus.FAILURE
             ).all()
+            user_ssh_keys = await data.ssh_key(asf_uid=session.uid).all()
 
     revision_name_from_link, revision_editor, revision_time = await 
revision.latest_info(
         release.project.name, release.version
@@ -112,6 +118,7 @@ async def check(
         delete_file_form=delete_file_form,
         asf_id=session.uid,
         server_domain=session.host,
+        user_ssh_keys=user_ssh_keys,
         format_datetime=routes.format_datetime,
         models=models,
         task_mid=task_mid,
diff --git a/atr/routes/finish.py b/atr/routes/finish.py
index 29e6fd4..b6ad452 100644
--- a/atr/routes/finish.py
+++ b/atr/routes/finish.py
@@ -29,6 +29,7 @@ import atr.revision as revision
 import atr.routes as routes
 import atr.routes.root as root
 import atr.util as util
+from atr import db
 
 _LOGGER: Final = logging.getLogger(__name__)
 
@@ -56,7 +57,12 @@ async def selected(session: routes.CommitterSession, 
project_name: str, version_
     """Finish a release preview."""
     await session.check_access(project_name)
 
-    release = await session.release(project_name, version_name, 
phase=models.ReleasePhase.RELEASE_PREVIEW)
+    async with db.session() as data:
+        release = await session.release(
+            project_name, version_name, 
phase=models.ReleasePhase.RELEASE_PREVIEW, data=data
+        )
+        user_ssh_keys = await data.ssh_key(asf_uid=session.uid).all()
+
     current_revision_dir = util.release_directory(release)
     file_paths_rel: list[pathlib.Path] = []
     unique_dirs: set[pathlib.Path] = {pathlib.Path(".")}
@@ -91,6 +97,7 @@ async def selected(session: routes.CommitterSession, 
project_name: str, version_
         file_paths=sorted(file_paths_rel),
         form=form,
         can_move=can_move,
+        user_ssh_keys=user_ssh_keys,
     )
 
 
diff --git a/atr/routes/upload.py b/atr/routes/upload.py
index 0733619..d74da4e 100644
--- a/atr/routes/upload.py
+++ b/atr/routes/upload.py
@@ -26,6 +26,7 @@ import werkzeug.datastructures as datastructures
 import werkzeug.wrappers.response as response
 import wtforms
 
+import atr.db as db
 import atr.revision as revision
 import atr.routes as routes
 import atr.routes.compose as compose
@@ -96,15 +97,21 @@ async def selected(session: routes.CommitterSession, 
project_name: str, version_
             await quart.flash(f"Error adding file: {e!s}", "error")
 
     svn_form = await SvnImportForm.create_form()
-    release = await session.release(project_name, version_name)
+
+    async with db.session() as data:
+        release = await session.release(project_name, version_name, data=data)
+        user_ssh_keys = await data.ssh_key(asf_uid=session.uid).all()
 
     return await quart.render_template(
         "upload-selected.html",
         asf_id=session.uid,
         server_domain=session.host,
         release=release,
+        project_name=project_name,
+        version_name=version_name,
         form=form,
         svn_form=svn_form,
+        user_ssh_keys=user_ssh_keys,
     )
 
 
diff --git a/atr/templates/check-selected.html 
b/atr/templates/check-selected.html
index a9bb04c..230eace 100644
--- a/atr/templates/check-selected.html
+++ b/atr/templates/check-selected.html
@@ -329,9 +329,10 @@
   <h2 id="rsync-download">Rsync download</h2>
   <p>You can download the files in this release using rsync with the following 
command:</p>
   <!-- TODO: Add a button to copy the command to the clipboard -->
-  <pre class="bg-light p-3 mb-0">
+  <pre class="bg-light p-3 mb-3">
 rsync -av -e 'ssh -p 2222' {{ asf_id }}@{{ server_domain }}:/{{ 
release.project.name }}/{{ release.version }}/ ${DOWNLOAD_PATH}/
 </pre>
+  {% include "user-ssh-keys.html" %}
 
 {% endblock content %}
 
diff --git a/atr/templates/finish-selected.html 
b/atr/templates/finish-selected.html
index 99a0d36..6fe03c7 100644
--- a/atr/templates/finish-selected.html
+++ b/atr/templates/finish-selected.html
@@ -103,9 +103,11 @@
   <h2 id="rsync-download">Rsync download</h2>
   <p>You can download the files in this release using rsync with the following 
command:</p>
   <!-- TODO: Add a button to copy the command to the clipboard -->
-  <pre class="bg-light p-3 mb-0">
+  <pre class="bg-light p-3 mb-3">
 rsync -av -e 'ssh -p 2222' {{ asf_id }}@{{ server_domain }}:/{{ 
release.project.name }}/{{ release.version }}/ ${DOWNLOAD_PATH}/
 </pre>
+  {% include "user-ssh-keys.html" %}
+
 {% endblock content %}
 
 {% block javascripts %}
diff --git a/atr/templates/keys-review.html b/atr/templates/keys-review.html
index ec7cde3..e3bc453 100644
--- a/atr/templates/keys-review.html
+++ b/atr/templates/keys-review.html
@@ -120,7 +120,7 @@
     <div class="mb-5 p-4 bg-light rounded">
       <div class="d-grid gap-4">
         {% for key in user_ssh_keys %}
-          <div class="card p-3 border">
+          <div id="ssh-key-{{ key.fingerprint }}" class="card p-3 border">
             <table class="mb-0">
               <tbody>
                 <tr>
diff --git a/atr/templates/upload-selected.html 
b/atr/templates/upload-selected.html
index dcf144b..24766fd 100644
--- a/atr/templates/upload-selected.html
+++ b/atr/templates/upload-selected.html
@@ -135,7 +135,9 @@
   <h2 id="rsync-upload">Rsync upload</h2>
   <p>Import files from a remote server using rsync with the following 
command:</p>
   <!-- TODO: Add a button to copy the command to the clipboard -->
-  <pre class="bg-light p-3 mb-0">
+  <pre class="bg-light p-3 mb-3">
 rsync -av -e 'ssh -p 2222' ${YOUR_FILES}/ {{ asf_id }}@{{ server_domain }}:/{{ 
release.project.name }}/{{ release.version }}/
 </pre>
+  {% include "user-ssh-keys.html" %}
+
 {% endblock content %}
diff --git a/atr/templates/user-ssh-keys.html b/atr/templates/user-ssh-keys.html
new file mode 100644
index 0000000..756cf44
--- /dev/null
+++ b/atr/templates/user-ssh-keys.html
@@ -0,0 +1,31 @@
+{% set key_count = user_ssh_keys|length %}
+{# TODO: Abstract this and the section in finish-selected.html to a common 
include or macro #}
+<div class="card bg-warning-subtle mb-3">
+  <div class="card-body p-3">
+    <p>
+      {% if key_count == 0 %}
+        We have no SSH keys on file for you, so you cannot yet use this 
command. Please <a href="{{ as_url(routes.keys.ssh_add) }}">add an SSH key</a>.
+      {% elif key_count == 1 %}
+        {% set key = user_ssh_keys[0] %}
+        {% set key_parts = key.key.split(' ', 2) %}
+        {% set key_comment = key_parts[2] if key_parts|length > 2 else 'key' %}
+        We have the SSH key <a href="{{ as_url(routes.keys.keys, 
_anchor='ssh-key-' + key.fingerprint) }}"
+    title="{{ key.fingerprint }}"><code>{{- key_comment | trim -}}</code></a> 
on file for you. You can also <a href="{{ as_url(routes.keys.ssh_add) }}">add 
another SSH key</a>.
+      {% else %}
+        We have the SSH keys
+        {% for key in user_ssh_keys %}
+          {% if loop.last and key_count > 1 %}and{% endif %}
+          {% set key_parts = key.key.split(' ', 2) %}
+          {% set key_comment = key_parts[2] if key_parts|length > 2 else 'key' 
%}
+          <a href="{{ as_url(routes.keys.keys, _anchor='ssh-key-' + 
key.fingerprint) }}"
+             title="{{ key.fingerprint }}"><code>{{- key_comment | trim 
-}}</code></a>
+          {% if not loop.last %},{% endif %}
+        {% endfor %}
+        on file for you. You can also <a href="{{ as_url(routes.keys.ssh_add) 
}}">add another SSH key</a>.
+      {% endif %}
+    </p>
+    <p class="mb-0">
+      The ATR server should be compatible with long obsolete versions of 
rsync, as long as you use the command as shown, but as of May 2025 the only 
rsync version line without <a 
href="https://github.com/google/security-research/security/advisories/GHSA-p5pg-x43v-mvqj";>known
 CVEs</a> is 3.4.*. Your package manager may have backports.
+    </p>
+  </div>
+</div>


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

Reply via email to