Skip to content

Commit ed82706

Browse files
Copilotazvoleff
andcommitted
Fix timezone-aware datetime comparisons in PasswordResetToken model
Co-authored-by: azvoleff <107753+azvoleff@users.noreply.github.com>
1 parent 635cbae commit ed82706

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

gefapi/models/password_reset_token.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class PasswordResetToken(db.Model):
4040
token = db.Column(db.String(128), unique=True, nullable=False, index=True)
4141
user_id = db.Column(db.GUID(), db.ForeignKey("user.id"), nullable=False)
4242
created_at = db.Column(
43-
db.DateTime(), default=datetime.datetime.utcnow
43+
db.DateTime(), default=lambda: datetime.datetime.now(datetime.UTC)
4444
)
4545
expires_at = db.Column(db.DateTime(), nullable=False)
4646
used_at = db.Column(db.DateTime(), nullable=True) # Track when token was used
@@ -51,7 +51,7 @@ class PasswordResetToken(db.Model):
5151
def __init__(self, user_id):
5252
self.user_id = user_id
5353
self.token = self._generate_secure_token()
54-
self.created_at = datetime.datetime.utcnow()
54+
self.created_at = datetime.datetime.now(datetime.UTC)
5555
self.expires_at = self.created_at + datetime.timedelta(
5656
hours=PASSWORD_RESET_TOKEN_EXPIRY_HOURS
5757
)
@@ -66,12 +66,17 @@ def _generate_secure_token():
6666

6767
def is_valid(self):
6868
"""Check if the token is valid (not expired and not used)."""
69-
now = datetime.datetime.utcnow()
70-
return self.used_at is None and self.expires_at > now
69+
# Make expires_at timezone-aware (assume UTC) if it's naive from the database
70+
expires_at = (
71+
self.expires_at.replace(tzinfo=datetime.UTC)
72+
if self.expires_at.tzinfo is None
73+
else self.expires_at
74+
)
75+
return self.used_at is None and expires_at > datetime.datetime.now(datetime.UTC)
7176

7277
def mark_used(self):
7378
"""Mark the token as used."""
74-
self.used_at = datetime.datetime.utcnow()
79+
self.used_at = datetime.datetime.now(datetime.UTC)
7580

7681
@classmethod
7782
def get_valid_token(cls, token_string):
@@ -95,7 +100,7 @@ def invalidate_user_tokens(cls, user_id):
95100
Called when creating a new reset token to ensure only one
96101
valid token exists per user at a time.
97102
"""
98-
now = datetime.datetime.utcnow()
103+
now = datetime.datetime.now(datetime.UTC)
99104
cls.query.filter(
100105
cls.user_id == user_id,
101106
cls.used_at.is_(None),
@@ -112,7 +117,7 @@ def cleanup_expired_tokens(cls, days_old=7):
112117
Returns:
113118
Number of tokens deleted
114119
"""
115-
cutoff = datetime.datetime.utcnow() - datetime.timedelta(days=days_old)
120+
cutoff = datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=days_old)
116121
result = cls.query.filter(cls.created_at < cutoff).delete(
117122
synchronize_session=False
118123
)

0 commit comments

Comments
 (0)