This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch cc/8618-part2
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 2786e9f7162ce6d78de70a560ede36d3cc0fc51a
Author: Carlos Cruz <[email protected]>
AuthorDate: Thu Jun 18 20:59:58 2026 +0000

    [#8610] Implement field level encryption for Users email addresses
---
 Allura/allura/model/auth.py            | 22 +++-------------------
 Allura/allura/tests/model/test_auth.py |  4 ++--
 2 files changed, 5 insertions(+), 21 deletions(-)

diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 8bf930cae..4c03fb225 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -38,8 +38,8 @@
 from tg import tmpl_context as c, app_globals as g
 from tg import request
 from ming import schema as S
-from ming.odm import session, state, MapperExtension
-from ming.odm import FieldProperty, RelationProperty, ForeignIdProperty, 
DecryptedProperty
+from ming.odm import session, state
+from ming.odm import FieldProperty, RelationProperty, ForeignIdProperty, 
DecryptedProperty, DecryptedListProperty
 from ming.odm.declarative import MappedClass
 from ming.odm.odmsession import ThreadLocalODMSession
 from ming.utils import LazyProperty
@@ -264,15 +264,6 @@ def __set__(self, instance, value):
         instance.display_name_encrypted = 
type(instance).encr(state(instance).document[self.name])
 
 
-class UserEmailAddressesMapperExtension(MapperExtension):
-
-    def before_insert(self, obj, state, sess):
-        obj.sync_email_addresses_encrypted()
-
-    def before_update(self, obj, state, sess):
-        obj.sync_email_addresses_encrypted()
-
-
 class User(MappedClass, ActivityNode, ActivityObject, SearchIndexable):
     SALT_LEN = 8
 
@@ -281,7 +272,6 @@ class __mongometa__:
         session = main_orm_session
         indexes = ['tool_data.AuthPasswordReset.hash']
         unique_indexes = ['username']
-        extensions = [UserEmailAddressesMapperExtension]
         custom_indexes = [
             dict(fields=('tool_data.phone_verification.number_hash',), 
sparse=True),
         ]
@@ -293,7 +283,7 @@ class __mongometa__:
     _id = FieldProperty(S.ObjectId)
     sfx_userid = FieldProperty(S.Deprecated)
     username = FieldProperty(str)
-    email_addresses = FieldProperty([str])
+    email_addresses = DecryptedListProperty('email_addresses_encrypted')
     email_addresses_encrypted = FieldProperty([S.Binary], if_missing=[])
     password = FieldProperty(str)  # hashed
     last_password_updated = FieldProperty(datetime)  # to access, use 
AuthProvider's get_last_password_updated
@@ -792,12 +782,6 @@ def set_tool_data(self, tool, **kw):
         d.update(kw)
         state(self).soil()
 
-    @classmethod
-    def encrypt_email_addresses(cls, email_addresses):
-        return [cls.encr(addr) if addr is not None else None for addr in 
email_addresses or []]
-
-    def sync_email_addresses_encrypted(self):
-        self.email_addresses_encrypted = 
type(self).encrypt_email_addresses(self.email_addresses)
 
     def address_object(self, addr):
         return EmailAddress.get(email=addr, claimed_by_user_id=self._id)
diff --git a/Allura/allura/tests/model/test_auth.py 
b/Allura/allura/tests/model/test_auth.py
index bad3e1e86..86583af6d 100644
--- a/Allura/allura/tests/model/test_auth.py
+++ b/Allura/allura/tests/model/test_auth.py
@@ -441,7 +441,7 @@ def 
test_email_addresses_encrypted_is_populated_on_creation(self):
         ]
         assert user.email_addresses == ['[email protected]', None, 
'[email protected]']
         assert user.email_addresses_encrypted == expected_encrypted
-        assert state(user).document['email_addresses'] == 
['[email protected]', None, '[email protected]']
+        assert 'email_addresses' not in state(user).document
         assert state(user).document['email_addresses_encrypted'] == 
expected_encrypted
 
     def test_email_addresses_encrypted_is_synced_on_update(self):
@@ -460,7 +460,7 @@ def 
test_email_addresses_encrypted_is_synced_on_update(self):
         ]
         assert user.email_addresses == ['[email protected]', '[email protected]']
         assert user.email_addresses_encrypted == expected_encrypted
-        assert state(user).document['email_addresses'] == ['[email protected]', 
'[email protected]']
+        assert 'email_addresses' not in state(user).document
         assert state(user).document['email_addresses_encrypted'] == 
expected_encrypted
 
     def test_set_display_name_pref_updates_encrypted_field_and_cache(self):

Reply via email to