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 0abfa18 Allow public routes to receive committer information
0abfa18 is described below
commit 0abfa18c28286414a76dc3a2a631f8108d514341
Author: Sean B. Palmer <[email protected]>
AuthorDate: Mon Sep 15 16:50:32 2025 +0100
Allow public routes to receive committer information
---
atr/routes/__init__.py | 12 +++++++-----
atr/routes/committees.py | 4 ++--
atr/routes/download.py | 24 ++++++++++++++++--------
atr/routes/projects.py | 2 +-
atr/routes/release.py | 12 ++++++++----
atr/routes/root.py | 4 ++--
6 files changed, 36 insertions(+), 22 deletions(-)
diff --git a/atr/routes/__init__.py b/atr/routes/__init__.py
index 4f628de..ab7bac1 100644
--- a/atr/routes/__init__.py
+++ b/atr/routes/__init__.py
@@ -21,7 +21,7 @@ import asyncio
import functools
import logging
import time
-from typing import TYPE_CHECKING, Any, Final, NoReturn, ParamSpec, Protocol,
TypeVar
+from typing import TYPE_CHECKING, Any, Concatenate, Final, NoReturn,
ParamSpec, Protocol, TypeVar
import aiofiles
import aiofiles.os
@@ -483,12 +483,14 @@ async def get_form(request: quart.Request) ->
datastructures.MultiDict:
def public(
path: str, methods: list[str] | None = None, measure_performance: bool =
True
-) -> Callable[[RouteHandler[R]], RouteHandler[R]]:
+) -> Callable[[Callable[Concatenate[CommitterSession | None, P],
Awaitable[R]]], RouteHandler[R]]:
"""Decorator for public GET routes that provides an enhanced session
object."""
- def decorator(func: RouteHandler[R]) -> RouteHandler[R]:
- async def wrapper(*args: Any, **kwargs: Any) -> R:
- return await func(*args, **kwargs)
+ def decorator(func: Callable[Concatenate[CommitterSession | None, P],
Awaitable[R]]) -> RouteHandler[R]:
+ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
+ web_session = await session.read()
+ enhanced_session = CommitterSession(web_session) if web_session
else None
+ return await func(enhanced_session, *args, **kwargs)
# Generate a unique endpoint name
endpoint = func.__module__ + "_" + func.__name__
diff --git a/atr/routes/committees.py b/atr/routes/committees.py
index 31463a4..1008d63 100644
--- a/atr/routes/committees.py
+++ b/atr/routes/committees.py
@@ -33,7 +33,7 @@ class UpdateCommitteeKeysForm(forms.Typed):
@routes.public("/committees")
-async def directory() -> str:
+async def directory(session: routes.CommitterSession | None) -> str:
"""Main committee directory page."""
async with db.session() as data:
committees = await
data.committee(_projects=True).order_by(sql.Committee.name).all()
@@ -45,7 +45,7 @@ async def directory() -> str:
@routes.public("/committees/<name>")
-async def view(name: str) -> str:
+async def view(session: routes.CommitterSession | None, name: str) -> str:
# TODO: Could also import this from keys.py
async with db.session() as data:
committee = await data.committee(
diff --git a/atr/routes/download.py b/atr/routes/download.py
index efbc526..b1d9b25 100644
--- a/atr/routes/download.py
+++ b/atr/routes/download.py
@@ -65,19 +65,25 @@ async def all_selected(
@routes.public("/download/path/<project_name>/<version_name>/<path:file_path>")
-async def path(project_name: str, version_name: str, file_path: str) ->
response.Response | quart.Response:
+async def path(
+ session: routes.CommitterSession | None, project_name: str, version_name:
str, file_path: str
+) -> response.Response | quart.Response:
"""Download a file or list a directory from a release in any phase."""
return await _download_or_list(project_name, version_name, file_path)
@routes.public("/download/path/<project_name>/<version_name>/")
-async def path_empty(project_name: str, version_name: str) ->
response.Response | quart.Response:
+async def path_empty(
+ session: routes.CommitterSession | None, project_name: str, version_name:
str
+) -> response.Response | quart.Response:
"""List files at the root of a release directory for download."""
return await _download_or_list(project_name, version_name, ".")
@routes.public("/download/sh/<project_name>/<version_name>")
-async def sh_selected(project_name: str, version_name: str) ->
response.Response | quart.Response:
+async def sh_selected(
+ session: routes.CommitterSession | None, project_name: str, version_name:
str
+) -> response.Response | quart.Response:
"""Shell script to download a release."""
conf = config.get()
app_host = conf.APP_HOST
@@ -92,10 +98,12 @@ async def sh_selected(project_name: str, version_name: str)
-> response.Response
@routes.public("/download/urls/<project_name>/<version_name>")
-async def urls_selected(project_name: str, version_name: str) ->
response.Response | quart.Response:
+async def urls_selected(
+ session: routes.CommitterSession | None, project_name: str, version_name:
str
+) -> response.Response | quart.Response:
try:
- async with db.session() as session:
- release = await session.release(project_name=project_name,
version=version_name).demand(
+ async with db.session() as data:
+ release = await data.release(project_name=project_name,
version=version_name).demand(
ValueError("Release not found")
)
url_list_str = await _generate_file_url_list(release)
@@ -149,8 +157,8 @@ async def _download_or_list(project_name: str,
version_name: str, file_path: str
raise routes.FlashError("Path must be relative")
# We allow downloading files from any phase
- async with db.session() as session:
- release = await session.release(project_name=project_name,
version=version_name).demand(
+ async with db.session() as data:
+ release = await data.release(project_name=project_name,
version=version_name).demand(
base.ASFQuartException("Release does not exist", errorcode=404)
)
full_path = util.release_directory(release) / file_path
diff --git a/atr/routes/projects.py b/atr/routes/projects.py
index 7f9253a..6217591 100644
--- a/atr/routes/projects.py
+++ b/atr/routes/projects.py
@@ -277,7 +277,7 @@ async def delete(session: routes.CommitterSession) ->
response.Response:
@routes.public("/projects")
-async def projects() -> str:
+async def projects(session: routes.CommitterSession | None) -> str:
"""Main project directory page."""
async with db.session() as data:
projects = await
data.project(_committee=True).order_by(sql.Project.full_name).all()
diff --git a/atr/routes/release.py b/atr/routes/release.py
index 6cb9af4..0b90a7b 100644
--- a/atr/routes/release.py
+++ b/atr/routes/release.py
@@ -35,7 +35,7 @@ if asfquart.APP is ...:
@routes.public("/releases/finished/<project_name>")
-async def finished(project_name: str) -> str:
+async def finished(session: routes.CommitterSession | None, project_name: str)
-> str:
"""View all finished releases for a project."""
async with db.session() as data:
project = await data.project(name=project_name,
status=sql.ProjectStatus.ACTIVE).demand(
@@ -59,7 +59,7 @@ async def finished(project_name: str) -> str:
@routes.public("/releases")
-async def releases() -> str:
+async def releases(session: routes.CommitterSession | None) -> str:
"""View all releases."""
# Releases are public, so we don't need to filter by user
async with db.session() as data:
@@ -99,7 +99,9 @@ async def select(session: routes.CommitterSession,
project_name: str) -> str:
@routes.public("/release/view/<project_name>/<version_name>")
-async def view(project_name: str, version_name: str) -> response.Response |
str:
+async def view(
+ session: routes.CommitterSession | None, project_name: str, version_name:
str
+) -> response.Response | str:
"""View all the files in the rsync upload directory for a release."""
async with db.session() as data:
release_name = sql.release_name(project_name, version_name)
@@ -126,7 +128,9 @@ async def view(project_name: str, version_name: str) ->
response.Response | str:
@routes.public("/release/view/<project_name>/<version_name>/<path:file_path>")
-async def view_path(project_name: str, version_name: str, file_path: str) ->
response.Response | str:
+async def view_path(
+ session: routes.CommitterSession | None, project_name: str, version_name:
str, file_path: str
+) -> response.Response | str:
"""View the content of a specific file in the final release."""
async with db.session() as data:
release_name = sql.release_name(project_name, version_name)
diff --git a/atr/routes/root.py b/atr/routes/root.py
index 816e995..60f160e 100644
--- a/atr/routes/root.py
+++ b/atr/routes/root.py
@@ -71,7 +71,7 @@ async def about(session: routes.CommitterSession) -> str:
@routes.public("/")
-async def index() -> response.Response | str:
+async def index(session: routes.CommitterSession | None) -> response.Response
| str:
"""Show public info or an entry portal for participants."""
session_data = await asfquart.session.read()
if session_data:
@@ -146,7 +146,7 @@ async def index() -> response.Response | str:
@routes.public("/policies")
-async def policies() -> str:
+async def policies(session: routes.CommitterSession | None) -> str:
return await template.blank("Policies", content=_POLICIES)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]