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 41a1861  Improve the fix for getting user committees from ASFQuart 
properly
41a1861 is described below

commit 41a18614c4474383c59c89af4b6e81b47c5a8d85
Author: Sean B. Palmer <[email protected]>
AuthorDate: Fri Sep 19 15:22:14 2025 +0100

    Improve the fix for getting user committees from ASFQuart properly
---
 atr/blueprints/admin/admin.py |  6 ++++--
 atr/log.py                    |  2 +-
 atr/principal.py              | 17 ++++++-----------
 atr/routes/root.py            |  2 +-
 atr/storage/writers/keys.py   | 21 +++++++++++++--------
 5 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/atr/blueprints/admin/admin.py b/atr/blueprints/admin/admin.py
index a687a01..df3d3d6 100644
--- a/atr/blueprints/admin/admin.py
+++ b/atr/blueprints/admin/admin.py
@@ -126,9 +126,9 @@ async def admin_browse_as() -> str | response.Response:
     ldap_projects_data = await apache.get_ldap_projects_data()
     committee_data = await apache.get_active_committee_data()
     ldap_data = ldap_params.results_list[0]
-    log.info("Current session data: %s", current_session)
+    log.info("Current ASFQuart session data: %s", current_session)
     new_session_data = _session_data(ldap_data, new_uid, current_session, 
ldap_projects_data, committee_data)
-    log.info("New session data: %s", new_session_data)
+    log.info("New Quart cookie (not ASFQuart session) data: %s", 
new_session_data)
     session.write(new_session_data)
 
     await quart.flash(
@@ -881,6 +881,8 @@ def _session_data(
         "isMember": is_member,
         "isChair": is_chair,
         "isRoot": is_root,
+        # WARNING: ASFQuart session.ClientSession uses "committees"
+        # But this is cookie, not ClientSession, data, and requires "pmcs"
         "pmcs": sorted(list(committees)),
         "projects": sorted(list(projects)),
         "mfa": current_session.mfa,
diff --git a/atr/log.py b/atr/log.py
index fe88ad4..2088320 100644
--- a/atr/log.py
+++ b/atr/log.py
@@ -116,7 +116,7 @@ def _caller_logger(depth: int = 1) -> logging.Logger:
 
 
 def _event(level: int, msg: str, *args: Any, stacklevel: int = 3, **kwargs: 
Any) -> None:
-    logger = _caller_logger(depth=2)
+    logger = _caller_logger(depth=3)
     # Stack level 1 is *here*, 2 is the caller, 3 is the caller of the caller
     # I.e. _event (1), log.* (2), actual caller (3)
     logger.log(level, msg, *args, stacklevel=stacklevel, **kwargs)
diff --git a/atr/principal.py b/atr/principal.py
index 8437567..af35fb0 100644
--- a/atr/principal.py
+++ b/atr/principal.py
@@ -250,18 +250,13 @@ class AuthoriserASFQuart:
     async def cache_refresh(self, asf_uid: str, asfquart_session: 
session.ClientSession) -> None:
         if not self.__cache.outdated():
             return
+        if not isinstance(asfquart_session, session.ClientSession):
+            # Defense in depth runtime check, already validated by the type 
checker
+            raise AuthenticationError("ASFQuart session is not a 
ClientSession")
         # We do not check that the ASF UID is the same as the one in the 
session
         # It is the caller's responsibility to ensure this
-        self.__cache.member_of[asf_uid] = 
frozenset(asfquart_session.get("committees", []))
-
-        # TODO: The code previously used "pmcs" above, which was incorrect
-        # The following is a defense in depth check until the reason for this 
is investigated
-        # If there is no evidence to the contrary, we can assume that it was a 
simple typo
-        if ("pmcs" in asfquart_session) and ("committees" not in 
asfquart_session):
-            asfquart_session["committees"] = asfquart_session["pmcs"]
-        # End of defense in depth check
-
-        self.__cache.participant_of[asf_uid] = 
frozenset(asfquart_session.get("projects", []))
+        self.__cache.member_of[asf_uid] = 
frozenset(asfquart_session.committees)
+        self.__cache.participant_of[asf_uid] = 
frozenset(asfquart_session.projects)
         self.__cache.last_refreshed = int(time.time())
 
 
@@ -324,7 +319,7 @@ class Authorisation(AsyncObject):
                 if asfquart_session is None:
                     raise AuthenticationError("No ASFQuart session found")
                 self.__authoriser = authoriser_asfquart
-                self.__asf_uid = asfquart_session.get("uid")
+                self.__asf_uid = asfquart_session.uid
                 if not isinstance(self.__asf_uid, str | None):
                     raise AuthenticationError("ASFQuart session has no uid")
                 self.__authenticated = True
diff --git a/atr/routes/root.py b/atr/routes/root.py
index 6cdc4af..40e3a2d 100644
--- a/atr/routes/root.py
+++ b/atr/routes/root.py
@@ -75,7 +75,7 @@ async def index(session: route.CommitterSession | None) -> 
response.Response | s
     """Show public info or an entry portal for participants."""
     session_data = await asfquart.session.read()
     if session_data:
-        uid = session_data.get("uid")
+        uid = session_data.uid
         if not uid:
             return await template.render("index-public.html")
 
diff --git a/atr/storage/writers/keys.py b/atr/storage/writers/keys.py
index 2fea75a..aee319c 100644
--- a/atr/storage/writers/keys.py
+++ b/atr/storage/writers/keys.py
@@ -500,14 +500,19 @@ class CommitteeParticipant(FoundationCommitter):
         committee = await self.committee()
 
         key_values = [key.key_model.model_dump(exclude={"committees"}) for key 
in key_list]
-        key_insert_result = await self.__data.execute(
-            sqlite.insert(sql.PublicSigningKey)
-            .values(key_values)
-            .on_conflict_do_nothing(index_elements=["fingerprint"])
-            .returning(via(sql.PublicSigningKey.fingerprint))
-        )
-        key_inserts = {row.fingerprint for row in key_insert_result}
-        log.info(f"Inserted {len(key_inserts)} keys")
+        if key_values:
+            key_insert_result = await self.__data.execute(
+                sqlite.insert(sql.PublicSigningKey)
+                .values(key_values)
+                .on_conflict_do_nothing(index_elements=["fingerprint"])
+                .returning(via(sql.PublicSigningKey.fingerprint))
+            )
+            key_inserts = {row.fingerprint for row in key_insert_result}
+            log.info(f"Inserted {len(key_inserts)} keys")
+        else:
+            # TODO: Warn the user about any keys that were already inserted
+            key_inserts = set()
+            log.info("Inserted 0 keys (no keys to insert)")
 
         def replace_with_inserted(key: types.Key) -> types.Key:
             if key.key_model.fingerprint in key_inserts:


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

Reply via email to