From c63906e0bfc83fdb9fb0ddfbb54120508b7d0109 Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Tue, 6 Dec 2016 18:13:27 -0800 Subject: Delete all pendings when mailing list is deleted --- src/mailman/model/listmanager.py | 2 ++ src/mailman/model/pending.py | 7 +++++-- src/mailman/model/requests.py | 8 ++++++++ src/mailman/model/tests/test_listmanager.py | 18 ++++++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/mailman/model/listmanager.py b/src/mailman/model/listmanager.py index 25848aabf..885e5c284 100644 --- a/src/mailman/model/listmanager.py +++ b/src/mailman/model/listmanager.py @@ -22,6 +22,7 @@ from mailman.interfaces.address import InvalidEmailAddressError from mailman.interfaces.listmanager import ( IListManager, ListAlreadyExistsError, ListCreatedEvent, ListCreatingEvent, ListDeletedEvent, ListDeletingEvent) +from mailman.interfaces.requests import IListRequests from mailman.model.autorespond import AutoResponseRecord from mailman.model.bans import Ban from mailman.model.mailinglist import ( @@ -76,6 +77,7 @@ class ListManager: notify(ListDeletingEvent(mlist)) # First delete information associated with the mailing list. IAcceptableAliasSet(mlist).clear() + IListRequests(mlist).clear() store.query(AutoResponseRecord).filter_by(mailing_list=mlist).delete() store.query(ContentFilter).filter_by(mailing_list=mlist).delete() store.query(ListArchiver).filter_by(mailing_list=mlist).delete() diff --git a/src/mailman/model/pending.py b/src/mailman/model/pending.py index dfcc6ea4f..023baf8de 100644 --- a/src/mailman/model/pending.py +++ b/src/mailman/model/pending.py @@ -151,7 +151,7 @@ class Pendings: store.delete(pending) @dbconnection - def find(self, store, mlist=None, pend_type=None): + def find(self, store, mlist=None, pend_type=None, confirm=True): query = store.query(Pended) if mlist is not None: pkv_alias_mlist = aliased(PendedKeyValue) @@ -166,7 +166,10 @@ class Pendings: pkv_alias_type.value == pend_type )) for pending in query: - yield pending.token, self.confirm(pending.token, expunge=False) + if confirm: + yield pending.token, self.confirm(pending.token, expunge=False) + else: + yield pending.token @dbconnection def __iter__(self, store): diff --git a/src/mailman/model/requests.py b/src/mailman/model/requests.py index c177388af..440b977a1 100644 --- a/src/mailman/model/requests.py +++ b/src/mailman/model/requests.py @@ -23,6 +23,7 @@ from mailman.database.transaction import dbconnection from mailman.database.types import Enum, SAUnicode from mailman.interfaces.pending import IPendable, IPendings from mailman.interfaces.requests import IListRequests, RequestType +from mailman.model.pending import Pended from mailman.utilities.queries import QuerySequence from pickle import dumps, loads from public import public @@ -139,6 +140,13 @@ class ListRequests: getUtility(IPendings).confirm(request.data_hash) store.delete(request) + @dbconnection + def clear(self, store): + for pended_token in getUtility(IPendings).find( + mlist=self.mailing_list, + confirm=False): + store.query(Pended).filter_by(token=pended_token).delete() + class _Request(Model): """Table for mailing list hold requests.""" diff --git a/src/mailman/model/tests/test_listmanager.py b/src/mailman/model/tests/test_listmanager.py index 914c0c185..cdd13ced3 100644 --- a/src/mailman/model/tests/test_listmanager.py +++ b/src/mailman/model/tests/test_listmanager.py @@ -30,6 +30,7 @@ from mailman.interfaces.listmanager import ( ListDeletedEvent, ListDeletingEvent) from mailman.interfaces.mailinglist import IListArchiverSet from mailman.interfaces.messages import IMessageStore +from mailman.interfaces.pending import IPendable, IPendings from mailman.interfaces.requests import IListRequests from mailman.interfaces.subscriptions import ISubscriptionService from mailman.interfaces.usermanager import IUserManager @@ -38,6 +39,12 @@ from mailman.testing.helpers import ( event_subscribers, specialized_message_from_string) from mailman.testing.layers import ConfigLayer from zope.component import getUtility +from zope.interface import implementer + + +@implementer(IPendable) +class SimplePendable(dict): + PEND_TYPE = 'simple' class TestListManager(unittest.TestCase): @@ -190,6 +197,17 @@ Message-ID: mailing_list=self._ant) self.assertEqual(filters.count(), 0) + def test_pendings_are_deleted_when_mailing_list_is_deleted(self): + pendingdb = getUtility(IPendings) + test1_list = create_list('test@example.com') + subscription_1 = SimplePendable( + type='subscription', + list_id='test.example.com') + pendingdb.add(subscription_1) + self.assertEqual(pendingdb.count, 1) + getUtility(IListManager).delete(test1_list) + self.assertEqual(pendingdb.count, 0) + class TestListCreation(unittest.TestCase): layer = ConfigLayer -- cgit v1.3.1 From 7b3b9d37f94f744c863b6b96f2d75a558357e397 Mon Sep 17 00:00:00 2001 From: Abhilash Raj Date: Tue, 6 Dec 2016 19:27:31 -0800 Subject: Delete PendedKeyValue before deleting Pended. --- src/mailman/model/requests.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mailman/model/requests.py b/src/mailman/model/requests.py index 440b977a1..0c164172d 100644 --- a/src/mailman/model/requests.py +++ b/src/mailman/model/requests.py @@ -23,7 +23,7 @@ from mailman.database.transaction import dbconnection from mailman.database.types import Enum, SAUnicode from mailman.interfaces.pending import IPendable, IPendings from mailman.interfaces.requests import IListRequests, RequestType -from mailman.model.pending import Pended +from mailman.model.pending import Pended, PendedKeyValue from mailman.utilities.queries import QuerySequence from pickle import dumps, loads from public import public @@ -145,7 +145,9 @@ class ListRequests: for pended_token in getUtility(IPendings).find( mlist=self.mailing_list, confirm=False): - store.query(Pended).filter_by(token=pended_token).delete() + pended = store.query(Pended).filter_by(token=pended_token).first() + store.query(PendedKeyValue).filter_by(pended_id=pended.id).delete() + store.delete(pended) class _Request(Model): -- cgit v1.3.1 From a01ef2bac4d52da67e4be1fccc2634086aaa03e3 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Sun, 8 Jan 2017 23:21:15 -0500 Subject: Delete subscription requests when a mailing list is deleted. Closes #214 --- src/mailman/docs/NEWS.rst | 2 ++ src/mailman/interfaces/pending.py | 18 ++++++++++++------ src/mailman/model/pending.py | 7 +++---- src/mailman/model/requests.py | 4 ++-- src/mailman/model/tests/test_listmanager.py | 16 +++++++++++----- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst index d8b8bb75f..0259d967d 100644 --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -101,6 +101,8 @@ Bugs ``reason`` attribute. Given by Aurélien Bompard. * Don't return a 500 error from the REST API when trying to handle a held message with defective content. Given by Abhilash Raj. (Closes: #256) + * Delete subscription requests when a mailing list is deleted. Given by + Abhilash Raj. (Closes: #214) Configuration ------------- diff --git a/src/mailman/interfaces/pending.py b/src/mailman/interfaces/pending.py index 841d195f5..aef18bcb4 100644 --- a/src/mailman/interfaces/pending.py +++ b/src/mailman/interfaces/pending.py @@ -96,14 +96,20 @@ class IPendings(Interface): def evict(): """Remove all pended items whose lifetime has expired.""" - def find(mlist=None, pend_type=None): + def find(mlist=None, pend_type=None, confirm=True): """Search for the pendables matching the given criteria. - :param mlist: The MailingList object that the pendables must be - related to. - :param pend_type: The type of the pendables that are looked for, this - corresponds to the `PEND_TYPE` attribute. - :return: An iterator over 2-tuples of the form (token, dict). + :param mlist: The mailing list object that the pendables must be + related to, or None. The default returns all pendables regardless + of which mailing list they are related to. + :type mlist: IMailingList or None. + :param pend_type: The type of the pendables that are looked for, or + None. This corresponds to the `PEND_TYPE` attribute. The default + returns all pending types. + :param confirm: A flag indicating whether the found pendings should be + "confirmed" or not. See ``confirm()`` for details. + :return: An iterator over 2-tuples of the form (token, pendable). + When ``confirm`` is False, ``pendable`` is None. """ def __iter__(): diff --git a/src/mailman/model/pending.py b/src/mailman/model/pending.py index 023baf8de..5e5a2af83 100644 --- a/src/mailman/model/pending.py +++ b/src/mailman/model/pending.py @@ -166,10 +166,9 @@ class Pendings: pkv_alias_type.value == pend_type )) for pending in query: - if confirm: - yield pending.token, self.confirm(pending.token, expunge=False) - else: - yield pending.token + pendable = (self.confirm(pending.token, expunge=False) + if confirm else None) + yield pending.token, pendable @dbconnection def __iter__(self, store): diff --git a/src/mailman/model/requests.py b/src/mailman/model/requests.py index 0c164172d..90d1c686c 100644 --- a/src/mailman/model/requests.py +++ b/src/mailman/model/requests.py @@ -142,10 +142,10 @@ class ListRequests: @dbconnection def clear(self, store): - for pended_token in getUtility(IPendings).find( + for token, pendable in getUtility(IPendings).find( mlist=self.mailing_list, confirm=False): - pended = store.query(Pended).filter_by(token=pended_token).first() + pended = store.query(Pended).filter_by(token=token).first() store.query(PendedKeyValue).filter_by(pended_id=pended.id).delete() store.delete(pended) diff --git a/src/mailman/model/tests/test_listmanager.py b/src/mailman/model/tests/test_listmanager.py index cdd13ced3..da65f88ce 100644 --- a/src/mailman/model/tests/test_listmanager.py +++ b/src/mailman/model/tests/test_listmanager.py @@ -199,13 +199,19 @@ Message-ID: def test_pendings_are_deleted_when_mailing_list_is_deleted(self): pendingdb = getUtility(IPendings) - test1_list = create_list('test@example.com') - subscription_1 = SimplePendable( + pendable_1 = SimplePendable( type='subscription', - list_id='test.example.com') - pendingdb.add(subscription_1) + list_id='ant.example.com') + pendingdb.add(pendable_1) + pendable_2 = SimplePendable( + type='subscription', + list_id='bee.example.com') + pendingdb.add(pendable_2) + self.assertEqual(pendingdb.count, 2) + list_manager = getUtility(IListManager) + list_manager.delete(self._ant) self.assertEqual(pendingdb.count, 1) - getUtility(IListManager).delete(test1_list) + list_manager.delete(self._bee) self.assertEqual(pendingdb.count, 0) -- cgit v1.3.1