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 1fd2843 Keep all key UIDs in the database
1fd2843 is described below
commit 1fd28436ad8271df593598a2c588d099d32c2a88
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed May 21 17:01:18 2025 +0100
Keep all key UIDs in the database
---
atr/db/__init__.py | 9 ++++---
atr/db/interaction.py | 7 +++---
atr/db/models.py | 8 +++++--
atr/routes/keys.py | 6 ++---
migrations/versions/0003_2025.05.21_ebed2397.py | 31 +++++++++++++++++++++++++
5 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/atr/db/__init__.py b/atr/db/__init__.py
index 942613c..02094ec 100644
--- a/atr/db/__init__.py
+++ b/atr/db/__init__.py
@@ -312,7 +312,8 @@ class Session(sqlalchemy.ext.asyncio.AsyncSession):
length: Opt[int] = NOT_SET,
created: Opt[datetime.datetime] = NOT_SET,
expires: Opt[datetime.datetime | None] = NOT_SET,
- declared_uid: Opt[str | None] = NOT_SET,
+ primary_declared_uid: Opt[str | None] = NOT_SET,
+ secondary_declared_uids: Opt[list[str]] = NOT_SET,
apache_uid: Opt[str] = NOT_SET,
ascii_armored_key: Opt[str] = NOT_SET,
_committees: bool = False,
@@ -329,8 +330,10 @@ class Session(sqlalchemy.ext.asyncio.AsyncSession):
query = query.where(models.PublicSigningKey.created == created)
if is_defined(expires):
query = query.where(models.PublicSigningKey.expires == expires)
- if is_defined(declared_uid):
- query = query.where(models.PublicSigningKey.declared_uid ==
declared_uid)
+ if is_defined(primary_declared_uid):
+ query = query.where(models.PublicSigningKey.primary_declared_uid
== primary_declared_uid)
+ if is_defined(secondary_declared_uids):
+ query =
query.where(models.PublicSigningKey.secondary_declared_uids ==
secondary_declared_uids)
if is_defined(apache_uid):
query = query.where(models.PublicSigningKey.apache_uid ==
apache_uid)
if is_defined(ascii_armored_key):
diff --git a/atr/db/interaction.py b/atr/db/interaction.py
index 86476fd..678c024 100644
--- a/atr/db/interaction.py
+++ b/atr/db/interaction.py
@@ -120,7 +120,7 @@ async def key_user_session_add(
if not isinstance(fingerprint, str):
raise RuntimeError("Invalid key fingerprint")
fingerprint = fingerprint.lower()
- uids = key.get("uids")
+ uids = key.get("uids", [])
key_record: models.PublicSigningKey | None = None
async with data.begin():
@@ -143,7 +143,8 @@ async def key_user_session_add(
length=int(key.get("length", "0")),
created=created,
expires=expires,
- declared_uid=uids[0] if uids else None,
+ primary_declared_uid=uids[0] if uids else None,
+ secondary_declared_uids=uids[1:],
apache_uid=asf_uid,
ascii_armored_key=public_key,
)
@@ -181,7 +182,7 @@ async def key_user_session_add(
continue
# Extract email for sorting
- user_id_str = key_record.declared_uid or ""
+ user_id_str = key_record.primary_declared_uid or ""
email_match = re.search(r"<([^>]+)>", user_id_str)
email = email_match.group(1) if email_match else user_id_str
diff --git a/atr/db/models.py b/atr/db/models.py
index fe7ab68..1789475 100644
--- a/atr/db/models.py
+++ b/atr/db/models.py
@@ -102,8 +102,12 @@ class PublicSigningKey(sqlmodel.SQLModel, table=True):
created: datetime.datetime =
sqlmodel.Field(sa_column=sqlalchemy.Column(UTCDateTime))
# Expiration date
expires: datetime.datetime | None = sqlmodel.Field(default=None,
sa_column=sqlalchemy.Column(UTCDateTime))
- # The UID declared in the key
- declared_uid: str | None
+ # The primary UID declared in the key
+ primary_declared_uid: str | None
+ # The secondary UIDs declared in the key
+ secondary_declared_uids: list[str] = sqlmodel.Field(
+ default_factory=list, sa_column=sqlalchemy.Column(sqlalchemy.JSON)
+ )
# The UID used by Apache
apache_uid: str
# The ASCII armored key
diff --git a/atr/routes/keys.py b/atr/routes/keys.py
index 215ba47..e30678e 100644
--- a/atr/routes/keys.py
+++ b/atr/routes/keys.py
@@ -382,9 +382,9 @@ async def update_committee_keys(session:
routes.CommitterSession, committee_name
for key in sorted_keys:
fingerprint_short = key.fingerprint[:16].upper()
apache_uid = key.apache_uid
- declared_uid_str = key.declared_uid or ""
- email_match = re.search(r"<([^>]+)>", declared_uid_str)
- email = email_match.group(1) if email_match else declared_uid_str
+ primary_declared_uid_str = key.primary_declared_uid or ""
+ email_match = re.search(r"<([^>]+)>", primary_declared_uid_str)
+ email = email_match.group(1) if email_match else
primary_declared_uid_str
if email == f"{apache_uid}@apache.org":
comment_line = f"# {fingerprint_short} {email}"
else:
diff --git a/migrations/versions/0003_2025.05.21_ebed2397.py
b/migrations/versions/0003_2025.05.21_ebed2397.py
new file mode 100644
index 0000000..06da93b
--- /dev/null
+++ b/migrations/versions/0003_2025.05.21_ebed2397.py
@@ -0,0 +1,31 @@
+"""Add secondary signing key UIDs
+
+Revision ID: 0003_2025.05.21_ebed2397
+Revises: 0002_2025.05.19_93ec427d
+Create Date: 2025-05-21 15:56:45.161982+00:00
+"""
+
+from collections.abc import Sequence
+
+import sqlalchemy as sa
+from alembic import op
+
+# Revision identifiers, used by Alembic
+revision: str = "0003_2025.05.21_ebed2397"
+down_revision: str | None = "0002_2025.05.19_93ec427d"
+branch_labels: str | Sequence[str] | None = None
+depends_on: str | Sequence[str] | None = None
+
+
+def upgrade() -> None:
+ op.add_column("publicsigningkey", sa.Column("primary_declared_uid",
sa.String(), nullable=True))
+ op.add_column("publicsigningkey", sa.Column("secondary_declared_uids",
sa.JSON(), nullable=True))
+ op.execute("UPDATE publicsigningkey SET primary_declared_uid =
declared_uid")
+ op.drop_column("publicsigningkey", "declared_uid")
+
+
+def downgrade() -> None:
+ op.add_column("publicsigningkey", sa.Column("declared_uid", sa.VARCHAR(),
nullable=True))
+ op.execute("UPDATE publicsigningkey SET declared_uid =
primary_declared_uid")
+ op.drop_column("publicsigningkey", "secondary_declared_uids")
+ op.drop_column("publicsigningkey", "primary_declared_uid")
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]