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 c65d689 Make the storage authentication interface raise exceptions by
default
c65d689 is described below
commit c65d689e43adfd98ea94cf7c0dc15aceacb13b6b
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Jul 23 15:38:48 2025 +0100
Make the storage authentication interface raise exceptions by default
---
atr/blueprints/admin/admin.py | 4 ++--
atr/blueprints/api/api.py | 10 +++++-----
atr/routes/keys.py | 17 ++++++++---------
atr/storage/__init__.py | 32 +++++++++++++++++---------------
atr/storage/writers/keys.py | 2 +-
atr/tasks/keys.py | 3 +--
docs/storage-interface.html | 6 +++---
docs/storage-interface.md | 6 +++---
8 files changed, 40 insertions(+), 40 deletions(-)
diff --git a/atr/blueprints/admin/admin.py b/atr/blueprints/admin/admin.py
index 14e0d52..8004a05 100644
--- a/atr/blueprints/admin/admin.py
+++ b/atr/blueprints/admin/admin.py
@@ -434,7 +434,7 @@ async def admin_keys_regenerate_all() -> quart.Response:
outcomes = types.Outcomes[str]()
async with storage.write(asf_uid) as write:
for committee_name in committee_names:
- wacm = write.as_committee_member(committee_name).result_or_none()
+ wacm = write.as_committee_member(committee_name)
if wacm is None:
continue
outcomes.append(await wacm.keys.autogenerate_keys_file())
@@ -674,7 +674,7 @@ async def admin_test() -> quart.wrappers.response.Response:
if asf_uid is None:
raise base.ASFQuartException("Invalid session, uid is None", 500)
async with storage.write(asf_uid) as write:
- wacm = write.as_committee_member("tooling").result_or_raise()
+ wacm = write.as_committee_member("tooling")
start = time.perf_counter_ns()
outcomes: types.Outcomes[types.Key] = await
wacm.keys.ensure_stored(keys_file_text)
end = time.perf_counter_ns()
diff --git a/atr/blueprints/api/api.py b/atr/blueprints/api/api.py
index 420758a..de2b92f 100644
--- a/atr/blueprints/api/api.py
+++ b/atr/blueprints/api/api.py
@@ -304,12 +304,12 @@ async def keys_add(data: models.api.KeysAddArgs) ->
DictResponse:
selected_committee_names = data.committees
async with storage.write(asf_uid) as write:
- wafc = write.as_foundation_committer().result_or_raise()
+ wafc = write.as_foundation_committer()
ocr: types.Outcome[types.Key] = await
wafc.keys.ensure_stored_one(data.key)
key = ocr.result_or_raise()
for selected_committee_name in selected_committee_names:
- wacm =
write.as_committee_member(selected_committee_name).result_or_raise()
+ wacm = write.as_committee_member(selected_committee_name)
outcome: types.Outcome[types.LinkedCommittee] = await
wacm.keys.associate_fingerprint(
key.key_model.fingerprint
)
@@ -333,12 +333,12 @@ async def keys_delete(data: models.api.KeysDeleteArgs) ->
DictResponse:
outcomes = types.Outcomes[str]()
async with storage.write(asf_uid) as write:
- wafc = write.as_foundation_committer().result_or_raise()
+ wafc = write.as_foundation_committer()
outcome: types.Outcome[sql.PublicSigningKey] = await
wafc.keys.delete_key(fingerprint)
key = outcome.result_or_raise()
for committee in key.committees:
- wacm = write.as_committee_member(committee.name).result_or_none()
+ wacm =
write.as_committee_member_outcome(committee.name).result_or_none()
if wacm is None:
continue
outcomes.append(await wacm.keys.autogenerate_keys_file())
@@ -387,7 +387,7 @@ async def keys_upload(data: models.api.KeysUploadArgs) ->
DictResponse:
filetext = data.filetext
selected_committee_name = data.committee
async with storage.write(asf_uid) as write:
- wacm =
write.as_committee_member(selected_committee_name).result_or_raise()
+ wacm = write.as_committee_member(selected_committee_name)
outcomes: types.Outcomes[types.Key] = await
wacm.keys.ensure_associated(filetext)
# TODO: It would be nice to serialise the actual outcomes
diff --git a/atr/routes/keys.py b/atr/routes/keys.py
index f25f521..0069ee1 100644
--- a/atr/routes/keys.py
+++ b/atr/routes/keys.py
@@ -161,14 +161,14 @@ async def add(session: routes.CommitterSession) -> str:
selected_committee_names: list[str] =
util.unwrap(form.selected_committees.data)
async with storage.write(asf_uid) as write:
- wafc = write.as_foundation_committer().result_or_raise()
+ wafc = write.as_foundation_committer()
ocr: types.Outcome[types.Key] = await
wafc.keys.ensure_stored_one(key_text)
key = ocr.result_or_raise()
for selected_committee_name in selected_committee_names:
# TODO: Should this be committee member or committee
participant?
# Also, should we emit warnings and continue here?
- wacp =
write.as_committee_participant(selected_committee_name).result_or_raise()
+ wacp =
write.as_committee_participant(selected_committee_name)
outcome: types.Outcome[types.LinkedCommittee] = await
wacp.keys.associate_fingerprint(
key.key_model.fingerprint
)
@@ -218,7 +218,7 @@ async def delete(session: routes.CommitterSession) ->
response.Response:
# Otherwise, delete an OpenPGP key
async with storage.write(session.uid) as write:
- wafc = write.as_foundation_committer().result_or_none()
+ wafc = write.as_foundation_committer_outcome().result_or_none()
if wafc is None:
return await session.redirect(keys, error="Key not found or not
owned by you")
outcome: types.Outcome[sql.PublicSigningKey] = await
wafc.keys.delete_key(fingerprint)
@@ -279,7 +279,7 @@ async def details(session: routes.CommitterSession,
fingerprint: str) -> str | r
if affected_committee_names:
async with storage.write(session.uid) as write:
for affected_committee_name in affected_committee_names:
- wacm =
write.as_committee_member(affected_committee_name).result_or_none()
+ wacm =
write.as_committee_member_outcome(affected_committee_name).result_or_none()
if wacm is None:
continue
await wacm.keys.autogenerate_keys_file()
@@ -304,7 +304,7 @@ async def details(session: routes.CommitterSession,
fingerprint: str) -> str | r
async def export(session: routes.CommitterSession, committee_name: str) ->
quart.Response:
"""Export a KEYS file for a specific committee."""
async with storage.write(session.uid) as write:
- wafc = write.as_foundation_committer().result_or_raise()
+ wafc = write.as_foundation_committer()
keys_file_text = await wafc.keys.keys_file_text(committee_name)
return quart.Response(keys_file_text, mimetype="text/plain")
@@ -317,8 +317,7 @@ async def import_selected_revision(
await util.validate_empty_form()
async with storage.write(session.uid) as write:
- access_outcome = await write.as_project_committee_member(project_name)
- wacm = access_outcome.result_or_raise()
+ wacm = await write.as_project_committee_member(project_name)
outcomes: types.Outcomes[types.Key] = await
wacm.keys.import_keys_file(project_name, version_name)
message = f"Uploaded {outcomes.result_count} keys,"
@@ -448,7 +447,7 @@ async def update_committee_keys(session:
routes.CommitterSession, committee_name
return await session.redirect(keys, error="Invalid request to update
KEYS file.")
async with storage.write(session.uid) as write:
- wacm = write.as_committee_member(committee_name).result_or_raise()
+ wacm = write.as_committee_member(committee_name)
match await wacm.keys.autogenerate_keys_file():
case types.OutcomeResult():
await quart.flash(
@@ -527,7 +526,7 @@ async def upload(session: routes.CommitterSession) -> str:
return await render(error="You must select at least one committee")
async with storage.write(session.uid) as write:
- wacm =
write.as_committee_member(selected_committee).result_or_raise()
+ wacm = write.as_committee_member(selected_committee)
outcomes = await wacm.keys.ensure_associated(keys_text)
results = outcomes
success_count = outcomes.result_count
diff --git a/atr/storage/__init__.py b/atr/storage/__init__.py
index 1adc9a7..70cd257 100644
--- a/atr/storage/__init__.py
+++ b/atr/storage/__init__.py
@@ -225,7 +225,10 @@ class Write:
# return types.OutcomeException(e)
# return types.OutcomeResult(wacm)
- def as_committee_member(self, committee_name: str) ->
types.Outcome[WriteAsCommitteeMember]:
+ def as_committee_member(self, committee_name: str) ->
WriteAsCommitteeMember:
+ return
self.as_committee_member_outcome(committee_name).result_or_raise()
+
+ def as_committee_member_outcome(self, committee_name: str) ->
types.Outcome[WriteAsCommitteeMember]:
if self.__asf_uid is None:
return types.OutcomeException(AccessError("No ASF UID"))
if committee_name not in self.__member_of:
@@ -236,7 +239,10 @@ class Write:
return types.OutcomeException(e)
return types.OutcomeResult(wacm)
- def as_committee_participant(self, committee_name: str) ->
types.Outcome[WriteAsCommitteeParticipant]:
+ def as_committee_participant(self, committee_name: str) ->
WriteAsCommitteeParticipant:
+ return
self.as_committee_participant_outcome(committee_name).result_or_raise()
+
+ def as_committee_participant_outcome(self, committee_name: str) ->
types.Outcome[WriteAsCommitteeParticipant]:
if self.__asf_uid is None:
return types.OutcomeException(AccessError("No ASF UID"))
if committee_name not in self.__participant_of:
@@ -247,7 +253,10 @@ class Write:
return types.OutcomeException(e)
return types.OutcomeResult(wacp)
- def as_foundation_committer(self) ->
types.Outcome[WriteAsFoundationCommitter]:
+ def as_foundation_committer(self) -> WriteAsFoundationCommitter:
+ return self.as_foundation_committer_outcome().result_or_raise()
+
+ def as_foundation_committer_outcome(self) ->
types.Outcome[WriteAsFoundationCommitter]:
if self.__asf_uid is None:
return types.OutcomeException(AccessError("No ASF UID"))
try:
@@ -259,7 +268,11 @@ class Write:
# async def as_key_owner(self) -> types.Outcome[WriteAsKeyOwner]:
# ...
- async def as_project_committee_member(self, project_name: str) ->
types.Outcome[WriteAsCommitteeMember]:
+ async def as_project_committee_member(self, project_name: str) ->
WriteAsCommitteeMember:
+ write_as_outcome = await
self.as_project_committee_member_outcome(project_name)
+ return write_as_outcome.result_or_raise()
+
+ async def as_project_committee_member_outcome(self, project_name: str) ->
types.Outcome[WriteAsCommitteeMember]:
project = await self.__data.project(project_name,
_committee=True).demand(
AccessError(f"Project not found: {project_name}")
)
@@ -360,16 +373,6 @@ class ContextManagers:
r = Read(data, asf_uid, member_of, participant_of)
yield r
- @contextlib.asynccontextmanager
- async def read_and_write(self, asf_uid: str | None = None) ->
AsyncGenerator[tuple[Read, Write]]:
- async with db.session() as data:
- # TODO: Replace data with DatabaseReader and DatabaseWriter
instances
- member_of = await self.member_of(data, asf_uid)
- participant_of = await self.participant_of(data, asf_uid)
- r = Read(data, asf_uid, member_of, participant_of)
- w = Write(data, asf_uid, member_of, participant_of)
- yield r, w
-
@contextlib.asynccontextmanager
async def write(self, asf_uid: str | None = None) -> AsyncGenerator[Write]:
async with db.session() as data:
@@ -383,5 +386,4 @@ class ContextManagers:
_MANAGERS: Final[ContextManagers] = ContextManagers()
read = _MANAGERS.read
-read_and_write = _MANAGERS.read_and_write
write = _MANAGERS.write
diff --git a/atr/storage/writers/keys.py b/atr/storage/writers/keys.py
index c84d905..8b8683f 100644
--- a/atr/storage/writers/keys.py
+++ b/atr/storage/writers/keys.py
@@ -100,7 +100,7 @@ class FoundationCommitter:
await self.__data.delete(key)
await self.__data.commit()
for committee in key.committees:
- wacm =
self.__write.as_committee_member(committee.name).result_or_none()
+ wacm =
self.__write.as_committee_member_outcome(committee.name).result_or_none()
if wacm is None:
continue
await wacm.keys.autogenerate_keys_file()
diff --git a/atr/tasks/keys.py b/atr/tasks/keys.py
index 6fe5671..2b8740f 100644
--- a/atr/tasks/keys.py
+++ b/atr/tasks/keys.py
@@ -33,8 +33,7 @@ class ImportFile(schema.Strict):
async def import_file(args: ImportFile) -> results.Results | None:
"""Import a KEYS file from a draft release candidate revision."""
async with storage.write(args.asf_uid) as write:
- access_outcome = await
write.as_project_committee_member(args.project_name)
- wacm = access_outcome.result_or_raise()
+ wacm = await write.as_project_committee_member(args.project_name)
outcomes = await wacm.keys.import_keys_file(args.project_name,
args.version_name)
if outcomes.any_exception:
# TODO: Log this? This code is unused anyway
diff --git a/docs/storage-interface.html b/docs/storage-interface.html
index 727a896..549d55f 100644
--- a/docs/storage-interface.html
+++ b/docs/storage-interface.html
@@ -9,12 +9,12 @@
</ol>
<p>Here is an actual example from our API code:</p>
<pre><code class="language-python">async with storage.write(asf_uid) as write:
- wafc = write.as_foundation_committer().writer_or_raise()
+ wafc = write.as_foundation_committer()
ocr: types.Outcome[types.Key] = await wafc.keys.ensure_stored_one(data.key)
key = ocr.result_or_raise()
for selected_committee_name in selected_committee_names:
- wacm =
write.as_committee_member(selected_committee_name).writer_or_raise()
+ wacm = write.as_committee_member(selected_committee_name)
outcome: types.Outcome[types.LinkedCommittee] = await
wacm.keys.associate_fingerprint(
key.key_model.fingerprint
)
@@ -24,7 +24,7 @@
<p>In this case we decide to raise as soon as there is any error. We could
also choose instead to display a warning, ignore the error, etc.</p>
<p>The first few lines in the context session show the classic three step
approach. Here they are again with comments:</p>
<pre><code class="language-python"> # 1. Request permissions
- wafc = write.as_foundation_committer().writer_or_raise()
+ wafc = write.as_foundation_committer()
# 2. Use the exposed functionality
ocr: types.Outcome[types.Key] = await wafc.keys.ensure_stored_one(data.key)
diff --git a/docs/storage-interface.md b/docs/storage-interface.md
index 8710fb6..84f8b1a 100644
--- a/docs/storage-interface.md
+++ b/docs/storage-interface.md
@@ -14,12 +14,12 @@ Here is an actual example from our API code:
```python
async with storage.write(asf_uid) as write:
- wafc = write.as_foundation_committer().writer_or_raise()
+ wafc = write.as_foundation_committer()
ocr: types.Outcome[types.Key] = await wafc.keys.ensure_stored_one(data.key)
key = ocr.result_or_raise()
for selected_committee_name in selected_committee_names:
- wacm =
write.as_committee_member(selected_committee_name).writer_or_raise()
+ wacm = write.as_committee_member(selected_committee_name)
outcome: types.Outcome[types.LinkedCommittee] = await
wacm.keys.associate_fingerprint(
key.key_model.fingerprint
)
@@ -34,7 +34,7 @@ The first few lines in the context session show the classic
three step approach.
```python
# 1. Request permissions
- wafc = write.as_foundation_committer().writer_or_raise()
+ wafc = write.as_foundation_committer()
# 2. Use the exposed functionality
ocr: types.Outcome[types.Key] = await wafc.keys.ensure_stored_one(data.key)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]