summaryrefslogtreecommitdiff
path: root/src/mailman/model
diff options
context:
space:
mode:
authorBarry Warsaw2015-02-13 03:13:06 -0500
committerBarry Warsaw2015-02-13 03:13:06 -0500
commit6d2c66ce133cd2c119fcb462dff662621013631a (patch)
tree8ce6043cc9e95fc9bcb5ba5dab720e8b73a8c56b /src/mailman/model
parent7ffb6d2d43471486997c78c3cffa787a10560ecf (diff)
downloadmailman-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.py41
-rw-r--r--src/mailman/model/uid.py17
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)