You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2025/09/08 21:10:15 UTC
(allura) 01/02: track the date an email address was confirmed
This is an automated email from the ASF dual-hosted git repository.
brondsem pushed a commit to branch db/email_confirmed_date
in repository https://gitbox.apache.org/repos/asf/allura.git
commit 217feffc52f923e5593834b206fdde17112ed3d0
Author: Dave Brondsema <db...@slashdotmedia.com>
AuthorDate: Mon Sep 8 16:02:41 2025 -0400
track the date an email address was confirmed
---
Allura/allura/controllers/auth.py | 1 +
Allura/allura/model/auth.py | 10 ++++++++++
Allura/allura/tests/model/test_auth.py | 18 ++++++++++++++++++
Allura/allura/websetup/bootstrap.py | 2 ++
4 files changed, 31 insertions(+)
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index ac83b2869..76b02db19 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -360,6 +360,7 @@ def _verify_addr(self, addr, do_auth_check=True):
send_system_mail_to_user(user, 'New Email Address Added', email_body)
addr.confirmed = True
+ addr.confirmed_date = datetime.utcnow()
flash('Email address confirmed')
h.auditlog_user('Email address verified: %s', addr.email, user=user)
if user.get_pref('email_address') is None:
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 630e6c5c5..ed9bbac22 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -88,6 +88,7 @@ class __mongometa__:
email = FieldProperty(str)
claimed_by_user_id = FieldProperty(S.ObjectId, if_missing=None)
confirmed = FieldProperty(bool, if_missing=False)
+ confirmed_date = FieldProperty(datetime)
nonce = FieldProperty(str)
valid_address = FieldProperty(bool, if_missing=None)
valid_details = FieldProperty(S.Anything, if_missing=None)
@@ -189,6 +190,15 @@ def send_verification_link(self):
message_id=h.gen_message_id(),
text=text)
+ @property
+ def confirmed_date_with_fallback(self) -> datetime | None:
+ # since confirmed_date was only added in 2025, use _id as approximate fallback
+ if self.confirmed_date:
+ return self.confirmed_date
+ if self.confirmed and self._id:
+ return self._id.generation_time.replace(tzinfo=None)
+ return None
+
class AuthGlobals(MappedClass):
class __mongometa__:
diff --git a/Allura/allura/tests/model/test_auth.py b/Allura/allura/tests/model/test_auth.py
index 7afb845d1..36a7727cf 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -22,6 +22,7 @@
import textwrap
from datetime import datetime, timedelta
+from bson import ObjectId
from tg import tmpl_context as c, app_globals as g, request as r
from webob import Request
from mock import patch, Mock
@@ -113,6 +114,23 @@ def test_email_address_send_verification_link(self):
return_path, rcpts, body = _client.sendmail.call_args[0]
assert rcpts == ['test_admin@domain.net']
+ def test_email_address_confirmed_date_with_fallback(self):
+ assert M.EmailAddress().confirmed_date_with_fallback is None
+
+ test_date = datetime(2025, 1, 1)
+
+ assert M.EmailAddress(confirmed_date=test_date).confirmed_date_with_fallback == test_date
+
+ assert M.EmailAddress(
+ _id=ObjectId.from_datetime(test_date),
+ confirmed=False,
+ ).confirmed_date_with_fallback is None
+
+ assert M.EmailAddress(
+ _id=ObjectId.from_datetime(test_date),
+ confirmed=True,
+ ).confirmed_date_with_fallback == test_date
+
@td.with_user_project('test-admin')
def test_user(self):
assert c.user.url() .endswith('/u/test-admin/')
diff --git a/Allura/allura/websetup/bootstrap.py b/Allura/allura/websetup/bootstrap.py
index 18989a0b3..c7a903f9e 100644
--- a/Allura/allura/websetup/bootstrap.py
+++ b/Allura/allura/websetup/bootstrap.py
@@ -209,6 +209,7 @@ def set_nbhd_wiki_content(nbhd_proj, content):
admin_email = M.EmailAddress.get(email='test-admin@users.localhost')
admin_email.confirmed = True
+ admin_email.confirmed_date = datetime.utcnow()
else:
u_admin = make_user('Admin 1', username='admin1')
# Admin1 is almost root, with admin access for Users and Projects
@@ -330,6 +331,7 @@ def create_user(display_name, username=None, password='foo', make_project=False)
kw = {"email": email}
em = EmailAddress.get(**kw)
em.confirmed = True
+ em.confirmed_date = datetime.utcnow()
em.set_nonce_hash()
user.set_pref('email_address', email)
fast_set_pwd(user, password)