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 21ede7b  Fix a bug with showing key expiration dates
21ede7b is described below

commit 21ede7b4bc68b883da50d25b027ee37ec5660e15
Author: Sean B. Palmer <[email protected]>
AuthorDate: Thu Apr 24 14:40:04 2025 +0100

    Fix a bug with showing key expiration dates
    
    Resolves #36.
---
 atr/db/models.py                  | 18 ++++++++++--------
 atr/routes/committees.py          |  8 +++++++-
 atr/routes/keys.py                | 11 ++++++-----
 atr/routes/projects.py            |  1 +
 atr/templates/committee-view.html |  2 +-
 5 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/atr/db/models.py b/atr/db/models.py
index 6f43510..a7eb176 100644
--- a/atr/db/models.py
+++ b/atr/db/models.py
@@ -87,9 +87,9 @@ class PublicSigningKey(sqlmodel.SQLModel, table=True):
     # Key length in bits
     length: int
     # Creation date
-    created: datetime.datetime
+    created: datetime.datetime = 
sqlmodel.Field(sa_column=sqlalchemy.Column(UTCDateTime))
     # Expiration date
-    expires: datetime.datetime | None
+    expires: datetime.datetime | None = sqlmodel.Field(default=None, 
sa_column=sqlalchemy.Column(UTCDateTime))
     # The UID declared in the key
     declared_uid: str | None
     # The UID used by Apache
@@ -175,7 +175,9 @@ class Project(sqlmodel.SQLModel, table=True):
         cascade_delete=True, sa_relationship_kwargs={"cascade": "all, 
delete-orphan", "single_parent": True}
     )
 
-    created: datetime.datetime = sqlmodel.Field(default_factory=lambda: 
datetime.datetime.now(datetime.UTC))
+    created: datetime.datetime = sqlmodel.Field(
+        default_factory=lambda: datetime.datetime.now(datetime.UTC), 
sa_column=sqlalchemy.Column(UTCDateTime)
+    )
     created_by: str | None = sqlmodel.Field(default=None)
 
     @property
@@ -264,7 +266,7 @@ class Package(sqlmodel.SQLModel, table=True):
     # The signature file
     signature_sha3: str | None = None
     # Uploaded timestamp
-    uploaded: datetime.datetime
+    uploaded: datetime.datetime = 
sqlmodel.Field(sa_column=sqlalchemy.Column(UTCDateTime))
     # The size of the file in bytes
     bytes_size: int
 
@@ -393,7 +395,7 @@ class Release(sqlmodel.SQLModel, table=True):
     name: str = sqlmodel.Field(default="", primary_key=True, unique=True)
     stage: ReleaseStage
     phase: ReleasePhase
-    created: datetime.datetime
+    created: datetime.datetime = 
sqlmodel.Field(sa_column=sqlalchemy.Column(UTCDateTime))
 
     # Many-to-one: A release belongs to one project, a project can have 
multiple releases
     project_id: int = sqlmodel.Field(foreign_key="project.id")
@@ -418,8 +420,8 @@ class Release(sqlmodel.SQLModel, table=True):
 
     votes: list[VoteEntry] = sqlmodel.Field(default_factory=list, 
sa_column=sqlalchemy.Column(sqlalchemy.JSON))
 
-    vote_started: datetime.datetime | None = sqlmodel.Field(default=None)
-    vote_resolved: datetime.datetime | None = sqlmodel.Field(default=None)
+    vote_started: datetime.datetime | None = sqlmodel.Field(default=None, 
sa_column=sqlalchemy.Column(UTCDateTime))
+    vote_resolved: datetime.datetime | None = sqlmodel.Field(default=None, 
sa_column=sqlalchemy.Column(UTCDateTime))
 
     # One-to-many: A release can have multiple tasks
     tasks: list["Task"] = sqlmodel.Relationship(
@@ -474,7 +476,7 @@ class CheckResult(sqlmodel.SQLModel, table=True):
     release: Release = sqlmodel.Relationship(back_populates="check_results")
     checker: str
     primary_rel_path: str | None = sqlmodel.Field(default=None, index=True)
-    created: datetime.datetime
+    created: datetime.datetime = 
sqlmodel.Field(sa_column=sqlalchemy.Column(UTCDateTime))
     status: CheckResultStatus
     message: str
     data: Any = sqlmodel.Field(sa_column=sqlalchemy.Column(sqlalchemy.JSON))
diff --git a/atr/routes/committees.py b/atr/routes/committees.py
index e477c68..dab9c58 100644
--- a/atr/routes/committees.py
+++ b/atr/routes/committees.py
@@ -17,6 +17,7 @@
 
 """project.py"""
 
+import datetime
 import http.client
 
 import quart
@@ -40,4 +41,9 @@ async def view(name: str) -> str:
         committee = await data.committee(name=name, _projects=True, 
_public_signing_keys=True).demand(
             http.client.HTTPException(404)
         )
-        return await quart.render_template("committee-view.html", 
committee=committee, algorithms=routes.algorithms)
+        return await quart.render_template(
+            "committee-view.html",
+            committee=committee,
+            algorithms=routes.algorithms,
+            now=datetime.datetime.now(datetime.UTC),
+        )
diff --git a/atr/routes/keys.py b/atr/routes/keys.py
index 2142991..725d8f0 100644
--- a/atr/routes/keys.py
+++ b/atr/routes/keys.py
@@ -259,14 +259,15 @@ async def key_user_session_add(
     async with data.begin():
         if existing := await data.public_signing_key(fingerprint=fingerprint, 
apache_uid=asf_uid).get():
             raise routes.FlashError(f"Key already exists: 
{existing.fingerprint}")
-
+        created = datetime.datetime.fromtimestamp(int(key["date"]), 
tz=datetime.UTC)
+        expires = datetime.datetime.fromtimestamp(int(key["expires"]), 
tz=datetime.UTC) if key.get("expires") else None
         # Create new key record
         key_record = models.PublicSigningKey(
             fingerprint=fingerprint,
             algorithm=int(key["algo"]),
             length=int(key.get("length", "0")),
-            created=datetime.datetime.fromtimestamp(int(key["date"])),
-            expires=datetime.datetime.fromtimestamp(int(key["expires"])) if 
key.get("expires") else None,
+            created=created,
+            expires=expires,
             declared_uid=uids[0] if uids else None,
             apache_uid=asf_uid,
             ascii_armored_key=public_key,
@@ -287,8 +288,8 @@ async def key_user_session_add(
         "key_id": key["keyid"],
         "fingerprint": key["fingerprint"].lower() if key.get("fingerprint") 
else "Unknown",
         "user_id": key["uids"][0] if key.get("uids") else "Unknown",
-        "creation_date": datetime.datetime.fromtimestamp(int(key["date"])),
-        "expiration_date": 
datetime.datetime.fromtimestamp(int(key["expires"])) if key.get("expires") else 
None,
+        "creation_date": created,
+        "expiration_date": expires,
         "data": pprint.pformat(key),
     }
 
diff --git a/atr/routes/projects.py b/atr/routes/projects.py
index 43ae0ea..cb2b7d5 100644
--- a/atr/routes/projects.py
+++ b/atr/routes/projects.py
@@ -188,6 +188,7 @@ async def view(name: str) -> str:
             previews=await project.previews,
             full_releases=await project.full_releases,
             number_of_release_files=util.number_of_release_files,
+            now=datetime.datetime.now(datetime.UTC),
         )
 
 
diff --git a/atr/templates/committee-view.html 
b/atr/templates/committee-view.html
index 63207a5..5e40597 100644
--- a/atr/templates/committee-view.html
+++ b/atr/templates/committee-view.html
@@ -42,7 +42,7 @@
 
   <div class="card mb-4">
     <div class="card-header bg-light">
-      <h3 class="mb-2">Signing Keys</h3>
+      <h3 class="mb-2">Signing keys</h3>
     </div>
     <div class="card-body">
       <div class="row row-cols-1 g-4">


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

Reply via email to