diff options
| author | Barry Warsaw | 2015-02-13 03:13:06 -0500 |
|---|---|---|
| committer | Barry Warsaw | 2015-02-13 03:13:06 -0500 |
| commit | 6d2c66ce133cd2c119fcb462dff662621013631a (patch) | |
| tree | 8ce6043cc9e95fc9bcb5ba5dab720e8b73a8c56b /src/mailman/model | |
| parent | 7ffb6d2d43471486997c78c3cffa787a10560ecf (diff) | |
| download | mailman-6d2c66ce133cd2c119fcb462dff662621013631a.tar.gz mailman-6d2c66ce133cd2c119fcb462dff662621013631a.tar.zst mailman-6d2c66ce133cd2c119fcb462dff662621013631a.zip | |
* A new API is provided to support non-production testing infrastructures,
allowing a client to cull all orphaned UIDs via ``DELETE`` on
``<api>/reserved/uids/orphans``. Note that *no guarantees* of API
stability will ever be made for resources under ``reserved``.
(LP: #1420083)
Also:
- Allow @dbconnection methods to be @staticmethods taking only one argument,
the store to perform the query on.
Diffstat (limited to 'src/mailman/model')
| -rw-r--r-- | src/mailman/model/tests/test_uid.py | 41 | ||||
| -rw-r--r-- | src/mailman/model/uid.py | 17 |
2 files changed, 58 insertions, 0 deletions
diff --git a/src/mailman/model/tests/test_uid.py b/src/mailman/model/tests/test_uid.py index d36fa4c3b..8f3b4af70 100644 --- a/src/mailman/model/tests/test_uid.py +++ b/src/mailman/model/tests/test_uid.py @@ -25,8 +25,11 @@ __all__ = [ import uuid import unittest +from mailman.config import config +from mailman.interfaces.usermanager import IUserManager from mailman.model.uid import UID from mailman.testing.layers import ConfigLayer +from zope.component import getUtility @@ -44,3 +47,41 @@ class TestUID(unittest.TestCase): my_uuid = uuid.uuid4() UID.record(my_uuid) self.assertRaises(ValueError, UID.record, my_uuid) + + def test_get_total_uid_count(self): + # The reserved REST API needs this. + for i in range(10): + UID.record(uuid.uuid4()) + self.assertEqual(UID.get_total_uid_count(), 10) + + def test_cull_orphan_uids(self): + # The reserved REST API needs to cull entries from the uid table that + # are not associated with actual entries in the user table. + manager = getUtility(IUserManager) + uids = set() + for i in range(10): + user = manager.create_user() + uids.add(user.user_id) + # The testing infrastructure does not record the UIDs for new user + # objects, so do that now to mimic the real system. + UID.record(user.user_id) + self.assertEqual(len(uids), 10) + # Now add some orphan uids. + orphans = set() + for i in range(100, 113): + uid = UID.record(uuid.UUID(int=i)) + orphans.add(uid.uid) + self.assertEqual(len(orphans), 13) + # Normally we wouldn't do a query in a test, since we'd want the model + # object to expose this, but we actually don't support exposing all + # the UIDs to the rest of Mailman. + all_uids = set(row[0] for row in config.db.store.query(UID.uid)) + self.assertEqual(all_uids, uids | orphans) + # Now, cull all the UIDs that aren't associated with users. Do use + # the model API for this. + UID.cull_orphans() + non_orphans = set(row[0] for row in config.db.store.query(UID.uid)) + self.assertEqual(uids, non_orphans) + # And all the users still exist. + non_orphans = set(user.user_id for user in manager.users) + self.assertEqual(uids, non_orphans) diff --git a/src/mailman/model/uid.py b/src/mailman/model/uid.py index c0d3e4d4d..0ff22438c 100644 --- a/src/mailman/model/uid.py +++ b/src/mailman/model/uid.py @@ -74,3 +74,20 @@ class UID(Model): if existing.count() != 0: raise ValueError(uid) return UID(uid) + + @staticmethod + @dbconnection + def get_total_uid_count(store): + return store.query(UID).count() + + @staticmethod + @dbconnection + def cull_orphans(store): + # Avoid circular imports. + from mailman.model.user import User + # Delete all uids in this table that are not associated with user + # rows. + results = store.query(UID).filter( + ~UID.uid.in_(store.query(User._user_id))) + for uid in results.all(): + store.delete(uid) |
