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-releases.git


The following commit(s) were added to refs/heads/main by this push:
     new 96629d4   Added friendly error messages for issue #243
96629d4 is described below

commit 96629d49f8185873eca2e11d58b100324d1bd98a
Author: vYSEHRAD <[email protected]>
AuthorDate: Mon Oct 20 22:46:40 2025 +0200

     Added friendly error messages for issue #243
---
 atr/blueprints/admin/admin.py |  2 +-
 atr/jwtoken.py                |  9 ++++++++-
 atr/routes/draft.py           | 10 ++++++++--
 atr/routes/keys.py            | 10 ++++++++--
 atr/util.py                   |  5 ++++-
 5 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/atr/blueprints/admin/admin.py b/atr/blueprints/admin/admin.py
index 69fe8fd..6ff6c0e 100644
--- a/atr/blueprints/admin/admin.py
+++ b/atr/blueprints/admin/admin.py
@@ -270,7 +270,7 @@ async def admin_data(model: str = "Committee") -> str:
 async def admin_delete_test_openpgp_keys() -> quart.Response | 
response.Response:
     """Delete all test user OpenPGP keys and their links."""
     if not config.get().ALLOW_TESTS:
-        raise base.ASFQuartException("Test key deletion not enabled", 
errorcode=404)
+        raise base.ASFQuartException("Test operations are disabled in this 
environment", errorcode=403)
 
     test_uid = "test"
 
diff --git a/atr/jwtoken.py b/atr/jwtoken.py
index 177689f..379142a 100644
--- a/atr/jwtoken.py
+++ b/atr/jwtoken.py
@@ -61,6 +61,10 @@ def require[**P, R](func: Callable[P, Coroutine[Any, Any, 
R]]) -> Callable[P, Aw
         token = _extract_bearer_token(quart.request)
         try:
             claims = verify(token)
+        except jwt.ExpiredSignatureError as exc:
+            raise base.ASFQuartException("Token has expired", errorcode=401) 
from exc
+        except jwt.InvalidTokenError as exc:
+            raise base.ASFQuartException("Invalid Bearer JWT format", 
errorcode=401) from exc
         except jwt.PyJWTError as exc:
             raise base.ASFQuartException(f"Invalid Bearer JWT: {exc}", 
errorcode=401) from exc
 
@@ -124,5 +128,8 @@ def _extract_bearer_token(request: quart.Request) -> str:
     header = request.headers.get("Authorization", "")
     scheme, _, token = header.partition(" ")
     if scheme.lower() != "bearer" or not token:
-        raise base.ASFQuartException("Bearer JWT missing", errorcode=401)
+        raise base.ASFQuartException(
+            "Authentication required. Please provide a valid Bearer token in 
the Authorization header",
+            errorcode=401
+        )
     return token
diff --git a/atr/routes/draft.py b/atr/routes/draft.py
index 398ce21..015f399 100644
--- a/atr/routes/draft.py
+++ b/atr/routes/draft.py
@@ -190,7 +190,10 @@ async def hashgen(
     form = await quart.request.form
     hash_type = form.get("hash_type")
     if hash_type not in {"sha256", "sha512"}:
-        raise base.ASFQuartException("Invalid hash type", errorcode=400)
+        raise base.ASFQuartException(
+            f"Invalid hash type '{hash_type}'. Supported types: sha256, 
sha512", 
+            errorcode=400
+        )
 
     rel_path = pathlib.Path(file_path)
 
@@ -224,7 +227,10 @@ async def sbomgen(
 
     # Check that the file is a .tar.gz archive before creating a revision
     if not (file_path.endswith(".tar.gz") or file_path.endswith(".tgz")):
-        raise base.ASFQuartException("SBOM generation is only supported for 
.tar.gz files", errorcode=400)
+        raise base.ASFQuartException(
+            f"SBOM generation requires .tar.gz or .tgz files. Received: 
{file_path}",
+            errorcode=400
+        )
 
     try:
         description = "SBOM generation through web interface"
diff --git a/atr/routes/keys.py b/atr/routes/keys.py
index 2813adb..0755c40 100644
--- a/atr/routes/keys.py
+++ b/atr/routes/keys.py
@@ -497,9 +497,15 @@ async def _get_keys_text(keys_url: str, render: 
Callable[[str], Awaitable[str]])
                 response.raise_for_status()
                 return await response.text()
     except aiohttp.ClientResponseError as e:
-        raise base.ASFQuartException(f"Error fetching URL: {e.status} 
{e.message}")
+        raise base.ASFQuartException(
+                f"Unable to fetch keys from remote server: {e.status} 
{e.message}",
+                errorcode=502
+            )
     except aiohttp.ClientError as e:
-        raise base.ASFQuartException(f"Error fetching URL: {e}")
+        raise base.ASFQuartException(
+                f"Network error while fetching keys: {e}",
+                errorcode=503
+            )
 
 
 async def _key_and_is_owner(
diff --git a/atr/util.py b/atr/util.py
index 021b7fd..4e1fbf2 100644
--- a/atr/util.py
+++ b/atr/util.py
@@ -926,7 +926,10 @@ def validate_as_type[T](value: Any, t: type[T]) -> T:
 async def validate_empty_form() -> None:
     empty_form = await forms.Empty.create_form(data=await quart.request.form)
     if not await empty_form.validate_on_submit():
-        raise base.ASFQuartException("Invalid request", 400)
+        raise base.ASFQuartException(
+            "Invalid form submission. Please check your input and try again.",
+            errorcode=400
+        )
 
 
 def validate_vote_duration(form: wtforms.Form, field: wtforms.IntegerField) -> 
None:


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

Reply via email to