You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by sb...@apache.org on 2026/05/19 18:18:13 UTC

(tooling-trusted-releases) branch sbp updated: Add a storage interface class to write as a user service

This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch sbp
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git


The following commit(s) were added to refs/heads/sbp by this push:
     new 9a3a0c80 Add a storage interface class to write as a user service
9a3a0c80 is described below

commit 9a3a0c8087a7dafd99eea7c0c21e082ac61774f3
Author: Sean B. Palmer <se...@miscoranda.com>
AuthorDate: Tue May 19 19:17:40 2026 +0100

    Add a storage interface class to write as a user service
---
 atr/storage/__init__.py | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/atr/storage/__init__.py b/atr/storage/__init__.py
index 0c70c118..64daa8b8 100644
--- a/atr/storage/__init__.py
+++ b/atr/storage/__init__.py
@@ -247,6 +247,19 @@ class WriteAsCommitteeAdmin(WriteAsCommitteeMember):
         self.keys = writers.keys.FoundationAdmin(write, self, data, committee_key)
 
 
+class WriteAsUserService(WriteAs):
+    def __init__(self, data: db.Session, asf_uid: str):
+        asf_uid = asf_uid.strip()
+        if not asf_uid:
+            raise AccessError("User service writes require an ASF UID", status=500)
+        self.__data = data
+        self.__asf_uid = asf_uid
+
+    @property
+    def asf_uid(self) -> str:
+        return self.__asf_uid
+
+
 # TODO: Could name this WriteDispatcher
 class Write:
     # Read and Write have authenticator methods which return access outcomes
@@ -452,6 +465,12 @@ def audit(**kwargs: basic.JSON) -> None:
     logger.info(msg)
 
 
+def ensure_project_active(project: sql.Project) -> None:
+    if project.status == sql.ProjectStatus.ACTIVE:
+        return
+    raise AccessError(f"Project '{project.key}' is archived; release actions are disabled.")
+
+
 @contextlib.asynccontextmanager
 async def read(asf_uid: principal.UID = principal.ArgumentNone) -> AsyncGenerator[Read]:
     if asf_uid is principal.ArgumentNone:
@@ -530,7 +549,8 @@ async def write_as_project_committee_member(
         yield await w.as_project_committee_member(project_key)
 
 
-def ensure_project_active(project: sql.Project) -> None:
-    if project.status == sql.ProjectStatus.ACTIVE:
-        return
-    raise AccessError(f"Project '{project.key}' is archived; release actions are disabled.")
+@contextlib.asynccontextmanager
+async def write_as_user_service(asf_uid: str) -> AsyncGenerator[WriteAsUserService]:
+    async with db.session() as data:
+        waus = WriteAsUserService(data, asf_uid)
+        yield waus


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org