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):
