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]