diff options
| author | J08nY | 2017-07-05 01:07:37 +0200 |
|---|---|---|
| committer | J08nY | 2017-08-30 13:18:40 +0200 |
| commit | d173b42e5ff5d90167091e6a015d394c2ddd8678 (patch) | |
| tree | aa1f5da977690822e80ce61b7b4cfddd0375cb62 /src/mailman/app | |
| parent | 34bf9690fd808d1ece8f6c2d674605fc25018894 (diff) | |
| download | mailman-d173b42e5ff5d90167091e6a015d394c2ddd8678.tar.gz mailman-d173b42e5ff5d90167091e6a015d394c2ddd8678.tar.zst mailman-d173b42e5ff5d90167091e6a015d394c2ddd8678.zip | |
Migrate the [un]subscription_policy attribute.
- This is quite a huge commit, since it changes the type of the
MailingList.subscription_policy and unsubscription_policy
attributes to the new names of pluggable workflows, in all
occurences.
- Also adds a migration to migrate the attributes to the new types.
- Adds tests for the migration.
Diffstat (limited to 'src/mailman/app')
| -rw-r--r-- | src/mailman/app/docs/moderator.rst | 10 | ||||
| -rw-r--r-- | src/mailman/app/subscriptions.py | 25 | ||||
| -rw-r--r-- | src/mailman/app/tests/test_moderation.py | 2 | ||||
| -rw-r--r-- | src/mailman/app/tests/test_subscriptions.py | 226 | ||||
| -rw-r--r-- | src/mailman/app/tests/test_unsubscriptions.py | 152 | ||||
| -rw-r--r-- | src/mailman/app/tests/test_workflowmanager.py | 22 |
6 files changed, 217 insertions, 220 deletions
diff --git a/src/mailman/app/docs/moderator.rst b/src/mailman/app/docs/moderator.rst index ce25a4711..6fcaf0b08 100644 --- a/src/mailman/app/docs/moderator.rst +++ b/src/mailman/app/docs/moderator.rst @@ -224,7 +224,7 @@ Fred is a member of the mailing list... >>> from mailman.interfaces.subscriptions import ISubscriptionManager >>> registrar = ISubscriptionManager(mlist) >>> token, token_owner, member = registrar.register( - ... fred, pre_verified=True, pre_confirmed=True, pre_approved=True) + ... fred, pre_verified=True, pre_confirmed=True) >>> member <Member: Fred Person <fred@example.com> on ant@example.com as MemberRole.member> @@ -301,16 +301,16 @@ Usually, the list administrators want to be notified when there are membership change requests they need to moderate. These notifications are sent when the list is configured to send them. - >>> from mailman.interfaces.mailinglist import SubscriptionPolicy + >>> from mailman.workflows.subscription import ModerationSubscriptionPolicy >>> mlist.admin_immed_notify = True - >>> mlist.subscription_policy = SubscriptionPolicy.moderate + >>> mlist.subscription_policy = ModerationSubscriptionPolicy Gwen tries to subscribe to the mailing list. >>> gwen = getUtility(IUserManager).create_address( ... 'gwen@example.com', 'Gwen Person') >>> token, token_owner, member = registrar.register( - ... gwen, pre_verified=True, pre_confirmed=True) + ... gwen, pre_verified=True) Her subscription must be approved by the list administrator, so she is not yet a member of the mailing list. @@ -414,7 +414,7 @@ message. >>> herb = getUtility(IUserManager).create_address( ... 'herb@example.com', 'Herb Person') >>> token, token_owner, member = registrar.register( - ... herb, pre_verified=True, pre_confirmed=True, pre_approved=True) + ... herb, pre_verified=True, pre_approved=True) >>> messages = get_queue_messages('virgin') >>> len(messages) 1 diff --git a/src/mailman/app/subscriptions.py b/src/mailman/app/subscriptions.py index c89e1e79f..e1c1d8993 100644 --- a/src/mailman/app/subscriptions.py +++ b/src/mailman/app/subscriptions.py @@ -28,8 +28,6 @@ from mailman.interfaces.subscriptions import ( from mailman.interfaces.template import ITemplateLoader from mailman.interfaces.workflows import IWorkflowStateManager from mailman.utilities.string import expand -from mailman.workflows.builtin import (SubscriptionWorkflow, - UnSubscriptionWorkflow) from mailman.workflows.common import (PendableSubscription, PendableUnsubscription) from public import public @@ -43,23 +41,16 @@ class SubscriptionManager: def __init__(self, mlist): self._mlist = mlist - def register(self, subscriber=None, *, - pre_verified=False, pre_confirmed=False, pre_approved=False): + def register(self, subscriber=None, **kwargs): """See `ISubscriptionManager`.""" - workflow = SubscriptionWorkflow( - self._mlist, subscriber, - pre_verified=pre_verified, - pre_confirmed=pre_confirmed, - pre_approved=pre_approved) + workflow = self._mlist.subscription_policy(self._mlist, subscriber, + **kwargs) list(workflow) return workflow.token, workflow.token_owner, workflow.member - def unregister(self, subscriber=None, *, - pre_confirmed=False, pre_approved=False): - workflow = UnSubscriptionWorkflow( - self._mlist, subscriber, - pre_confirmed=pre_confirmed, - pre_approved=pre_approved) + def unregister(self, subscriber=None, **kwargs): + workflow = self._mlist.unsubscription_policy(self._mlist, subscriber, + **kwargs) list(workflow) return workflow.token, workflow.token_owner, workflow.member @@ -72,9 +63,9 @@ class SubscriptionManager: workflow_type = pendable.get('type') assert workflow_type in (PendableSubscription.PEND_TYPE, PendableUnsubscription.PEND_TYPE) - workflow = (SubscriptionWorkflow + workflow = (self._mlist.subscription_policy if workflow_type == PendableSubscription.PEND_TYPE - else UnSubscriptionWorkflow)(self._mlist) + else self._mlist.unsubscription_policy)(self._mlist) workflow.token = token workflow.restore() # In order to just run the whole workflow, all we need to do diff --git a/src/mailman/app/tests/test_moderation.py b/src/mailman/app/tests/test_moderation.py index 5448a1d79..7d7524a10 100644 --- a/src/mailman/app/tests/test_moderation.py +++ b/src/mailman/app/tests/test_moderation.py @@ -162,7 +162,7 @@ class TestUnsubscription(unittest.TestCase): user_manager = getUtility(IUserManager) anne = user_manager.create_address('anne@example.org', 'Anne Person') token, token_owner, member = self._manager.register( - anne, pre_verified=True, pre_confirmed=True, pre_approved=True) + anne, pre_verified=True, pre_confirmed=True) self.assertIsNone(token) self.assertEqual(member.address.email, 'anne@example.org') bart = user_manager.create_user('bart@example.com', 'Bart User') diff --git a/src/mailman/app/tests/test_subscriptions.py b/src/mailman/app/tests/test_subscriptions.py index 0519ec385..23487ab1c 100644 --- a/src/mailman/app/tests/test_subscriptions.py +++ b/src/mailman/app/tests/test_subscriptions.py @@ -21,9 +21,7 @@ import unittest from contextlib import suppress from mailman.app.lifecycle import create_list -from mailman.app.subscriptions import SubscriptionWorkflow from mailman.interfaces.bans import IBanManager -from mailman.interfaces.mailinglist import SubscriptionPolicy from mailman.interfaces.member import MemberRole, MembershipIsBannedError from mailman.interfaces.pending import IPendings from mailman.interfaces.subscriptions import TokenOwner @@ -32,6 +30,9 @@ from mailman.testing.helpers import ( LogFileMark, get_queue_messages, set_preferred) from mailman.testing.layers import ConfigLayer from mailman.utilities.datetime import now +from mailman.workflows.subscription import ( + ConfirmModerationSubscriptionPolicy, ConfirmSubscriptionPolicy, + ModerationSubscriptionPolicy, OpenSubscriptionPolicy) from unittest.mock import patch from zope.component import getUtility @@ -55,7 +56,7 @@ class TestSubscriptionWorkflow(unittest.TestCase): def test_start_state(self): # The workflow starts with no tokens or member. - workflow = SubscriptionWorkflow(self._mlist) + workflow = ConfirmSubscriptionPolicy(self._mlist) self.assertIsNone(workflow.token) self.assertEqual(workflow.token_owner, TokenOwner.no_one) self.assertIsNone(workflow.member) @@ -64,7 +65,7 @@ class TestSubscriptionWorkflow(unittest.TestCase): # There is a Pendable associated with the held request, and it has # some data associated with it. anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = ConfirmSubscriptionPolicy(self._mlist, anne) with suppress(StopIteration): workflow.run_thru('send_confirmation') self.assertIsNotNone(workflow.token) @@ -79,14 +80,14 @@ class TestSubscriptionWorkflow(unittest.TestCase): def test_user_or_address_required(self): # The `subscriber` attribute must be a user or address. - workflow = SubscriptionWorkflow(self._mlist) + workflow = ConfirmSubscriptionPolicy(self._mlist) self.assertRaises(AssertionError, list, workflow) def test_sanity_checks_address(self): # Ensure that the sanity check phase, when given an IAddress, ends up # with a linked user. anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = ConfirmSubscriptionPolicy(self._mlist, anne) self.assertIsNotNone(workflow.address) self.assertIsNone(workflow.user) workflow.run_thru('sanity_checks') @@ -99,7 +100,7 @@ class TestSubscriptionWorkflow(unittest.TestCase): # preferred address, ends up with an address. anne = self._user_manager.make_user(self._anne) address = set_preferred(anne) - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = ConfirmSubscriptionPolicy(self._mlist, anne) # The constructor sets workflow.address because the user has a # preferred address. self.assertEqual(workflow.address, address) @@ -113,7 +114,7 @@ class TestSubscriptionWorkflow(unittest.TestCase): # preferred address, but with at least one linked address, gets an # address. anne = self._user_manager.make_user(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = ConfirmSubscriptionPolicy(self._mlist, anne) self.assertIsNone(workflow.address) self.assertEqual(workflow.user, anne) workflow.run_thru('sanity_checks') @@ -127,7 +128,7 @@ class TestSubscriptionWorkflow(unittest.TestCase): anne = self._user_manager.make_user(self._anne) anne.link(self._user_manager.create_address('anne@example.net')) anne.link(self._user_manager.create_address('anne@example.org')) - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = ConfirmSubscriptionPolicy(self._mlist, anne) self.assertIsNone(workflow.address) self.assertEqual(workflow.user, anne) workflow.run_thru('sanity_checks') @@ -139,21 +140,21 @@ class TestSubscriptionWorkflow(unittest.TestCase): def test_sanity_checks_user_without_addresses(self): # It is an error to try to subscribe a user with no linked addresses. user = self._user_manager.create_user() - workflow = SubscriptionWorkflow(self._mlist, user) + workflow = ConfirmSubscriptionPolicy(self._mlist, user) self.assertRaises(AssertionError, workflow.run_thru, 'sanity_checks') def test_sanity_checks_globally_banned_address(self): # An exception is raised if the address is globally banned. anne = self._user_manager.create_address(self._anne) IBanManager(None).ban(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = ConfirmSubscriptionPolicy(self._mlist, anne) self.assertRaises(MembershipIsBannedError, list, workflow) def test_sanity_checks_banned_address(self): # An exception is raised if the address is banned by the mailing list. anne = self._user_manager.create_address(self._anne) IBanManager(self._mlist).ban(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = ConfirmSubscriptionPolicy(self._mlist, anne) self.assertRaises(MembershipIsBannedError, list, workflow) def test_verification_checks_with_verified_address(self): @@ -161,7 +162,7 @@ class TestSubscriptionWorkflow(unittest.TestCase): # confirmation checks. anne = self._user_manager.create_address(self._anne) anne.verified_on = now() - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = ConfirmSubscriptionPolicy(self._mlist, anne) workflow.run_thru('verification_checks') with patch.object(workflow, '_step_confirmation_checks') as step: next(workflow) @@ -171,7 +172,8 @@ class TestSubscriptionWorkflow(unittest.TestCase): # When the address is not yet verified, but the pre-verified flag is # passed to the workflow, we skip to the confirmation checks. anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True) + workflow = ConfirmSubscriptionPolicy(self._mlist, anne, + pre_verified=True) workflow.run_thru('verification_checks') with patch.object(workflow, '_step_confirmation_checks') as step: next(workflow) @@ -184,7 +186,7 @@ class TestSubscriptionWorkflow(unittest.TestCase): # A confirmation message must be sent to the user which will also # verify their address. anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = ConfirmSubscriptionPolicy(self._mlist, anne) workflow.run_thru('verification_checks') with patch.object(workflow, '_step_send_confirmation') as step: next(workflow) @@ -195,10 +197,11 @@ class TestSubscriptionWorkflow(unittest.TestCase): def test_confirmation_checks_open_list(self): # A subscription to an open list does not need to be confirmed or # moderated. - self._mlist.subscription_policy = SubscriptionPolicy.open + self._mlist.subscription_policy = OpenSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True) - workflow.run_thru('confirmation_checks') + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) + workflow.run_thru('verification_checks') with patch.object(workflow, '_step_do_subscription') as step: next(workflow) step.assert_called_once_with() @@ -206,10 +209,11 @@ class TestSubscriptionWorkflow(unittest.TestCase): def test_confirmation_checks_no_user_confirmation_needed(self): # A subscription to a list which does not need user confirmation skips # to the moderation checks. - self._mlist.subscription_policy = SubscriptionPolicy.moderate + self._mlist.subscription_policy = ModerationSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True) - workflow.run_thru('confirmation_checks') + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) + workflow.run_thru('verification_checks') with patch.object(workflow, '_step_moderation_checks') as step: next(workflow) step.assert_called_once_with() @@ -218,11 +222,11 @@ class TestSubscriptionWorkflow(unittest.TestCase): # The subscription policy requires user confirmation, but their # subscription is pre-confirmed. Since moderation is not required, # the user will be immediately subscribed. - self._mlist.subscription_policy = SubscriptionPolicy.confirm + self._mlist.subscription_policy = ConfirmSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, - pre_verified=True, - pre_confirmed=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True, + pre_confirmed=True) workflow.run_thru('confirmation_checks') with patch.object(workflow, '_step_do_subscription') as step: next(workflow) @@ -233,11 +237,11 @@ class TestSubscriptionWorkflow(unittest.TestCase): # subscription is pre-confirmed. Since moderation is required, that # check will be performed. self._mlist.subscription_policy = ( - SubscriptionPolicy.confirm_then_moderate) + ConfirmModerationSubscriptionPolicy) anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, - pre_verified=True, - pre_confirmed=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True, + pre_confirmed=True) workflow.run_thru('confirmation_checks') with patch.object(workflow, '_step_moderation_checks') as step: next(workflow) @@ -247,11 +251,11 @@ class TestSubscriptionWorkflow(unittest.TestCase): # The subscription policy requires user confirmation and moderation, # but their subscription is pre-confirmed. self._mlist.subscription_policy = ( - SubscriptionPolicy.confirm_then_moderate) + ConfirmModerationSubscriptionPolicy) anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, - pre_verified=True, - pre_confirmed=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True, + pre_confirmed=True) workflow.run_thru('confirmation_checks') with patch.object(workflow, '_step_moderation_checks') as step: next(workflow) @@ -260,9 +264,10 @@ class TestSubscriptionWorkflow(unittest.TestCase): def test_confirmation_checks_confirmation_needed(self): # The subscription policy requires confirmation and the subscription # is not pre-confirmed. - self._mlist.subscription_policy = SubscriptionPolicy.confirm + self._mlist.subscription_policy = ConfirmSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) workflow.run_thru('confirmation_checks') with patch.object(workflow, '_step_send_confirmation') as step: next(workflow) @@ -272,9 +277,10 @@ class TestSubscriptionWorkflow(unittest.TestCase): # The subscription policy requires confirmation and moderation, and the # subscription is not pre-confirmed. self._mlist.subscription_policy = ( - SubscriptionPolicy.confirm_then_moderate) + ConfirmModerationSubscriptionPolicy) anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) workflow.run_thru('confirmation_checks') with patch.object(workflow, '_step_send_confirmation') as step: next(workflow) @@ -282,11 +288,11 @@ class TestSubscriptionWorkflow(unittest.TestCase): def test_moderation_checks_pre_approved(self): # The subscription is pre-approved by the moderator. - self._mlist.subscription_policy = SubscriptionPolicy.moderate + self._mlist.subscription_policy = ModerationSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, - pre_verified=True, - pre_approved=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True, + pre_approved=True) workflow.run_thru('moderation_checks') with patch.object(workflow, '_step_do_subscription') as step: next(workflow) @@ -294,9 +300,10 @@ class TestSubscriptionWorkflow(unittest.TestCase): def test_moderation_checks_approval_required(self): # The moderator must approve the subscription. - self._mlist.subscription_policy = SubscriptionPolicy.moderate + self._mlist.subscription_policy = ModerationSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) workflow.run_thru('moderation_checks') with patch.object(workflow, '_step_get_moderator_approval') as step: next(workflow) @@ -306,9 +313,10 @@ class TestSubscriptionWorkflow(unittest.TestCase): # An open subscription policy plus a pre-verified address means the # user gets subscribed to the mailing list without any further # confirmations or approvals. - self._mlist.subscription_policy = SubscriptionPolicy.open + self._mlist.subscription_policy = OpenSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) # Consume the entire state machine. list(workflow) # Anne is now a member of the mailing list. @@ -323,11 +331,11 @@ class TestSubscriptionWorkflow(unittest.TestCase): # An moderation-requiring subscription policy plus a pre-verified and # pre-approved address means the user gets subscribed to the mailing # list without any further confirmations or approvals. - self._mlist.subscription_policy = SubscriptionPolicy.moderate + self._mlist.subscription_policy = ModerationSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, - pre_verified=True, - pre_approved=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True, + pre_approved=True) # Consume the entire state machine. list(workflow) # Anne is now a member of the mailing list. @@ -343,12 +351,12 @@ class TestSubscriptionWorkflow(unittest.TestCase): # pre-approved address means the user gets subscribed to the mailing # list without any further confirmations or approvals. self._mlist.subscription_policy = ( - SubscriptionPolicy.confirm_then_moderate) + ConfirmModerationSubscriptionPolicy) anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, - pre_verified=True, - pre_confirmed=True, - pre_approved=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True, + pre_confirmed=True, + pre_approved=True) # Consume the entire state machine. list(workflow) # Anne is now a member of the mailing list. @@ -362,12 +370,10 @@ class TestSubscriptionWorkflow(unittest.TestCase): def test_do_subscription_cleanups(self): # Once the user is subscribed, the token, and its associated pending # database record will be removed from the database. - self._mlist.subscription_policy = SubscriptionPolicy.open + self._mlist.subscription_policy = OpenSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, - pre_verified=True, - pre_confirmed=True, - pre_approved=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) # Consume the entire state machine. list(workflow) # Anne is now a member of the mailing list. @@ -382,11 +388,10 @@ class TestSubscriptionWorkflow(unittest.TestCase): # The workflow runs until moderator approval is required, at which # point the workflow is saved. Once the moderator approves, the # workflow resumes and the user is subscribed. - self._mlist.subscription_policy = SubscriptionPolicy.moderate + self._mlist.subscription_policy = ModerationSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, - pre_verified=True, - pre_confirmed=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) # Consume the entire state machine. list(workflow) # The user is not currently subscribed to the mailing list. @@ -399,7 +404,7 @@ class TestSubscriptionWorkflow(unittest.TestCase): # Create a new workflow with the previous workflow's save token, and # restore its state. This models an approved subscription and should # result in the user getting subscribed. - approved_workflow = SubscriptionWorkflow(self._mlist) + approved_workflow = self._mlist.subscription_policy(self._mlist) approved_workflow.token = workflow.token approved_workflow.restore() list(approved_workflow) @@ -415,11 +420,10 @@ class TestSubscriptionWorkflow(unittest.TestCase): # When the subscription is held for moderator approval, a message is # logged. mark = LogFileMark('mailman.subscribe') - self._mlist.subscription_policy = SubscriptionPolicy.moderate + self._mlist.subscription_policy = ModerationSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, - pre_verified=True, - pre_confirmed=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) # Consume the entire state machine. list(workflow) self.assertIn( @@ -434,14 +438,13 @@ class TestSubscriptionWorkflow(unittest.TestCase): # When the subscription is held for moderator approval, and the list # is so configured, a notification is sent to the list moderators. self._mlist.admin_immed_notify = True - self._mlist.subscription_policy = SubscriptionPolicy.moderate + self._mlist.subscription_policy = ModerationSubscriptionPolicy anne = self._user_manager.create_address(self._anne) bart = self._user_manager.create_user('bart@example.com', 'Bart User') address = set_preferred(bart) self._mlist.subscribe(address, MemberRole.moderator) - workflow = SubscriptionWorkflow(self._mlist, anne, - pre_verified=True, - pre_confirmed=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) # Consume the entire state machine. list(workflow) # Find the moderator message. @@ -452,13 +455,13 @@ class TestSubscriptionWorkflow(unittest.TestCase): else: raise AssertionError('No moderator email found') self.assertEqual( - item.msgdata['recipients'], {'test-owner@example.com'}) + item.msgdata['recipients'], {'test-owner@example.com'}) message = items[0].msg self.assertEqual(message['From'], 'test-owner@example.com') self.assertEqual(message['To'], 'test-owner@example.com') self.assertEqual( - message['Subject'], - 'New subscription request to Test from anne@example.com') + message['Subject'], + 'New subscription request to Test from anne@example.com') self.assertEqual(message.get_payload(), """\ Your authorization is required for a mailing list subscription request approval: @@ -474,11 +477,10 @@ approval: # When the subscription is held for moderator approval, and the list # is so configured, a notification is sent to the list moderators. self._mlist.admin_immed_notify = False - self._mlist.subscription_policy = SubscriptionPolicy.moderate + self._mlist.subscription_policy = ModerationSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, - pre_verified=True, - pre_confirmed=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) # Consume the entire state machine. list(workflow) get_queue_messages('virgin', expected_count=0) @@ -491,14 +493,14 @@ approval: anne = self._user_manager.create_address(self._anne) self.assertIsNone(anne.verified_on) # Run the workflow to model the confirmation step. - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = self._mlist.subscription_policy(self._mlist, anne) list(workflow) items = get_queue_messages('virgin', expected_count=1) message = items[0].msg token = workflow.token self.assertEqual(message['Subject'], 'confirm {}'.format(token)) self.assertEqual( - message['From'], 'test-confirm+{}@example.com'.format(token)) + message['From'], 'test-confirm+{}@example.com'.format(token)) # The confirmation message is not `Precedence: bulk`. self.assertIsNone(message['precedence']) # The state machine stopped at the moderator approval so there will be @@ -511,15 +513,16 @@ approval: anne = self._user_manager.create_address(self._anne) self.assertIsNone(anne.verified_on) # Run the workflow to model the confirmation step. - workflow = SubscriptionWorkflow(self._mlist, anne, pre_confirmed=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_confirmed=True) list(workflow) items = get_queue_messages('virgin', expected_count=1) message = items[0].msg token = workflow.token self.assertEqual( - message['Subject'], 'confirm {}'.format(workflow.token)) + message['Subject'], 'confirm {}'.format(workflow.token)) self.assertEqual( - message['From'], 'test-confirm+{}@example.com'.format(token)) + message['From'], 'test-confirm+{}@example.com'.format(token)) # The state machine stopped at the moderator approval so there will be # one token still in the database. self._expected_pendings_count = 1 @@ -527,19 +530,20 @@ approval: def test_send_confirmation_pre_verified(self): # A confirmation message gets sent even when the address is verified # when the subscription must be confirmed. - self._mlist.subscription_policy = SubscriptionPolicy.confirm + self._mlist.subscription_policy = ConfirmSubscriptionPolicy anne = self._user_manager.create_address(self._anne) self.assertIsNone(anne.verified_on) # Run the workflow to model the confirmation step. - workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) list(workflow) items = get_queue_messages('virgin', expected_count=1) message = items[0].msg token = workflow.token self.assertEqual( - message['Subject'], 'confirm {}'.format(workflow.token)) + message['Subject'], 'confirm {}'.format(workflow.token)) self.assertEqual( - message['From'], 'test-confirm+{}@example.com'.format(token)) + message['From'], 'test-confirm+{}@example.com'.format(token)) # The state machine stopped at the moderator approval so there will be # one token still in the database. self._expected_pendings_count = 1 @@ -551,11 +555,11 @@ approval: anne = self._user_manager.create_address(self._anne) self.assertIsNone(anne.verified_on) # Run the workflow to model the confirmation step. - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = self._mlist.subscription_policy(self._mlist, anne) list(workflow) # The address is still not verified. self.assertIsNone(anne.verified_on) - confirm_workflow = SubscriptionWorkflow(self._mlist) + confirm_workflow = self._mlist.subscription_policy(self._mlist) confirm_workflow.token = workflow.token confirm_workflow.restore() confirm_workflow.run_thru('do_confirm_verify') @@ -569,11 +573,11 @@ approval: set_preferred(anne) # Run the workflow to model the confirmation step. There is no # subscriber attribute yet. - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = self._mlist.subscription_policy(self._mlist, anne) list(workflow) self.assertEqual(workflow.subscriber, anne) # Do a confirmation workflow, which should now set the subscriber. - confirm_workflow = SubscriptionWorkflow(self._mlist) + confirm_workflow = self._mlist.subscription_policy(self._mlist) confirm_workflow.token = workflow.token confirm_workflow.restore() confirm_workflow.run_thru('do_confirm_verify') @@ -584,10 +588,10 @@ approval: # Subscriptions to the mailing list must be confirmed. Once that's # done, the user's address (which is not initially verified) gets # subscribed to the mailing list. - self._mlist.subscription_policy = SubscriptionPolicy.confirm + self._mlist.subscription_policy = ConfirmSubscriptionPolicy anne = self._user_manager.create_address(self._anne) self.assertIsNone(anne.verified_on) - workflow = SubscriptionWorkflow(self._mlist, anne) + workflow = self._mlist.subscription_policy(self._mlist, anne) list(workflow) # Anne is not yet a member. member = self._mlist.regular_members.get_member(self._anne) @@ -597,7 +601,7 @@ approval: self.assertIsNotNone(workflow.token) self.assertEqual(workflow.token_owner, TokenOwner.subscriber) # Confirm. - confirm_workflow = SubscriptionWorkflow(self._mlist) + confirm_workflow = self._mlist.subscription_policy(self._mlist) confirm_workflow.token = workflow.token confirm_workflow.restore() list(confirm_workflow) @@ -615,9 +619,10 @@ approval: # the user confirming their subscription, and then the moderator # approving it, that different tokens are used in these two cases. self._mlist.subscription_policy = ( - SubscriptionPolicy.confirm_then_moderate) + ConfirmModerationSubscriptionPolicy) anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) # Run the state machine up to the first confirmation, and cache the # confirmation token. list(workflow) @@ -630,7 +635,7 @@ approval: self.assertIsNotNone(workflow.token) self.assertEqual(workflow.token_owner, TokenOwner.subscriber) # The old token will not work for moderator approval. - moderator_workflow = SubscriptionWorkflow(self._mlist) + moderator_workflow = self._mlist.subscription_policy(self._mlist) moderator_workflow.token = token moderator_workflow.restore() list(moderator_workflow) @@ -641,7 +646,7 @@ approval: # that there's a new token for the next steps. self.assertNotEqual(token, moderator_workflow.token) # The old token won't work. - final_workflow = SubscriptionWorkflow(self._mlist) + final_workflow = self._mlist.subscription_policy(self._mlist) final_workflow.token = token self.assertRaises(LookupError, final_workflow.restore) # Running this workflow will fail. @@ -666,11 +671,11 @@ approval: def test_confirmation_needed_and_pre_confirmed(self): # The subscription policy is 'confirm' but the subscription is # pre-confirmed so the moderation checks can be skipped. - self._mlist.subscription_policy = SubscriptionPolicy.confirm + self._mlist.subscription_policy = ConfirmSubscriptionPolicy anne = self._user_manager.create_address(self._anne) - workflow = SubscriptionWorkflow( - self._mlist, anne, - pre_verified=True, pre_confirmed=True, pre_approved=True) + workflow = self._mlist.subscription_policy( + self._mlist, anne, + pre_verified=True, pre_confirmed=True) list(workflow) # Anne was subscribed. self.assertIsNone(workflow.token) @@ -680,17 +685,18 @@ approval: def test_restore_user_absorbed(self): # The subscribing user is absorbed (and thus deleted) before the # moderator approves the subscription. - self._mlist.subscription_policy = SubscriptionPolicy.moderate + self._mlist.subscription_policy = ModerationSubscriptionPolicy anne = self._user_manager.create_user(self._anne) bill = self._user_manager.create_user('bill@example.com') set_preferred(bill) # anne subscribes. - workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True) + workflow = self._mlist.subscription_policy(self._mlist, anne, + pre_verified=True) list(workflow) # bill absorbs anne. bill.absorb(anne) # anne's subscription request is approved. - approved_workflow = SubscriptionWorkflow(self._mlist) + approved_workflow = self._mlist.subscription_policy(self._mlist) approved_workflow.token = workflow.token approved_workflow.restore() self.assertEqual(approved_workflow.user, bill) @@ -700,19 +706,19 @@ approval: def test_restore_address_absorbed(self): # The subscribing user is absorbed (and thus deleted) before the # moderator approves the subscription. - self._mlist.subscription_policy = SubscriptionPolicy.moderate + self._mlist.subscription_policy = ModerationSubscriptionPolicy anne = self._user_manager.create_user(self._anne) anne_address = anne.addresses[0] bill = self._user_manager.create_user('bill@example.com') # anne subscribes. - workflow = SubscriptionWorkflow( - self._mlist, anne_address, pre_verified=True) + workflow = self._mlist.subscription_policy( + self._mlist, anne_address, pre_verified=True) list(workflow) # bill absorbs anne. bill.absorb(anne) self.assertIn(anne_address, bill.addresses) # anne's subscription request is approved. - approved_workflow = SubscriptionWorkflow(self._mlist) + approved_workflow = self._mlist.subscription_policy(self._mlist) approved_workflow.token = workflow.token approved_workflow.restore() self.assertEqual(approved_workflow.user, bill) diff --git a/src/mailman/app/tests/test_unsubscriptions.py b/src/mailman/app/tests/test_unsubscriptions.py index 4ca657190..2e210e90b 100644 --- a/src/mailman/app/tests/test_unsubscriptions.py +++ b/src/mailman/app/tests/test_unsubscriptions.py @@ -21,14 +21,15 @@ import unittest from contextlib import suppress from mailman.app.lifecycle import create_list -from mailman.app.subscriptions import UnSubscriptionWorkflow -from mailman.interfaces.mailinglist import SubscriptionPolicy from mailman.interfaces.pending import IPendings from mailman.interfaces.subscriptions import TokenOwner from mailman.interfaces.usermanager import IUserManager from mailman.testing.helpers import LogFileMark, get_queue_messages from mailman.testing.layers import ConfigLayer from mailman.utilities.datetime import now +from mailman.workflows.unsubscription import ( + ConfirmModerationUnsubscriptionPolicy, ConfirmUnsubscriptionPolicy, + ModerationUnsubscriptionPolicy, OpenUnsubscriptionPolicy) from unittest.mock import patch from zope.component import getUtility @@ -40,7 +41,7 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): def setUp(self): self._mlist = create_list('test@example.com') self._mlist.admin_immed_notify = False - self._mlist.unsubscription_policy = SubscriptionPolicy.open + self._mlist.unsubscription_policy = OpenUnsubscriptionPolicy self._mlist.send_welcome_message = False self._anne = 'anne@example.com' self._user_manager = getUtility(IUserManager) @@ -58,7 +59,7 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): def test_start_state(self): # Test the workflow starts with no tokens or members. - workflow = UnSubscriptionWorkflow(self._mlist) + workflow = self._mlist.unsubscription_policy(self._mlist) self.assertEqual(workflow.token_owner, TokenOwner.no_one) self.assertIsNone(workflow.token) self.assertIsNone(workflow.member) @@ -67,8 +68,8 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): # Test there is a Pendable object associated with a held # unsubscription request and it has some valid data associated with # it. - self._mlist.unsubscription_policy = SubscriptionPolicy.confirm - workflow = UnSubscriptionWorkflow(self._mlist, self.anne) + self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) with suppress(StopIteration): workflow.run_thru('send_confirmation') self.assertIsNotNone(workflow.token) @@ -84,23 +85,23 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): def test_user_or_address_required(self): # The `subscriber` attribute must be a user or address that is provided # to the workflow. - workflow = UnSubscriptionWorkflow(self._mlist) + workflow = OpenUnsubscriptionPolicy(self._mlist) self.assertRaises(AssertionError, list, workflow) def test_user_is_subscribed_to_unsubscribe(self): # A user must be subscribed to a list when trying to unsubscribe. addr = self._user_manager.create_address('aperson@example.org') addr.verfied_on = now() - workflow = UnSubscriptionWorkflow(self._mlist, addr) + workflow = self._mlist.unsubscription_policy(self._mlist, addr) self.assertRaises(AssertionError, workflow.run_thru, 'subscription_checks') def test_confirmation_checks_open_list(self): # An unsubscription from an open list does not need to be confirmed or # moderated. - self._mlist.unsubscription_policy = SubscriptionPolicy.open - workflow = UnSubscriptionWorkflow(self._mlist, self.anne) - workflow.run_thru('confirmation_checks') + self._mlist.unsubscription_policy = OpenUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) + workflow.run_thru('subscription_checks') with patch.object(workflow, '_step_do_unsubscription') as step: next(workflow) step.assert_called_once_with() @@ -108,10 +109,9 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): def test_confirmation_checks_no_user_confirmation_needed(self): # An unsubscription from a list which does not need user confirmation # skips to the moderation checks. - self._mlist.unsubscription_policy = SubscriptionPolicy.moderate - workflow = UnSubscriptionWorkflow(self._mlist, self.anne, - pre_confirmed=True) - workflow.run_thru('confirmation_checks') + self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) + workflow.run_thru('subscription_checks') with patch.object(workflow, '_step_moderation_checks') as step: next(workflow) step.assert_called_once_with() @@ -120,8 +120,8 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): # The unsubscription policy requires user-confirmation, but their # unsubscription is pre-confirmed. Since moderation is not reuqired, # the user will be immediately unsubscribed. - self._mlist.unsubscription_policy = SubscriptionPolicy.confirm - workflow = UnSubscriptionWorkflow( + self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy( self._mlist, self.anne, pre_confirmed=True) workflow.run_thru('confirmation_checks') with patch.object(workflow, '_step_do_unsubscription') as step: @@ -133,19 +133,19 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): # unsubscription is pre-confirmed. Since moderation is required, that # check will be performed. self._mlist.unsubscription_policy = ( - SubscriptionPolicy.confirm_then_moderate) - workflow = UnSubscriptionWorkflow( + ConfirmModerationUnsubscriptionPolicy) + workflow = self._mlist.unsubscription_policy( self._mlist, self.anne, pre_confirmed=True) workflow.run_thru('confirmation_checks') - with patch.object(workflow, '_step_do_unsubscription') as step: + with patch.object(workflow, '_step_moderation_checks') as step: next(workflow) step.assert_called_once_with() def test_send_confirmation_checks_confirm_list(self): # The unsubscription policy requires user confirmation and the # unsubscription is not pre-confirmed. - self._mlist.unsubscription_policy = SubscriptionPolicy.confirm - workflow = UnSubscriptionWorkflow(self._mlist, self.anne) + self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) workflow.run_thru('confirmation_checks') with patch.object(workflow, '_step_send_confirmation') as step: next(workflow) @@ -153,17 +153,17 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): def test_moderation_checks_moderated_list(self): # The unsubscription policy requires moderation. - self._mlist.unsubscription_policy = SubscriptionPolicy.moderate - workflow = UnSubscriptionWorkflow(self._mlist, self.anne) - workflow.run_thru('confirmation_checks') + self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) + workflow.run_thru('subscription_checks') with patch.object(workflow, '_step_moderation_checks') as step: next(workflow) step.assert_called_once_with() def test_moderation_checks_approval_required(self): # The moderator must approve the subscription request. - self._mlist.unsubscription_policy = SubscriptionPolicy.moderate - workflow = UnSubscriptionWorkflow(self._mlist, self.anne) + self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) workflow.run_thru('moderation_checks') with patch.object(workflow, '_step_get_moderator_approval') as step: next(workflow) @@ -172,8 +172,8 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): def test_do_unsusbcription(self): # An open unsubscription policy means the user gets unsubscribed to # the mailing list without any further confirmations or approvals. - self._mlist.unsubscription_policy = SubscriptionPolicy.open - workflow = UnSubscriptionWorkflow(self._mlist, self.anne) + self._mlist.unsubscription_policy = OpenUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) list(workflow) member = self._mlist.regular_members.get_member(self._anne) self.assertIsNone(member) @@ -182,9 +182,9 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): # A moderation-requiring subscription policy plus a pre-approved # address means the user gets unsubscribed from the mailing list # without any further confirmation or approvals. - self._mlist.unsubscription_policy = SubscriptionPolicy.moderate - workflow = UnSubscriptionWorkflow(self._mlist, self.anne, - pre_approved=True) + self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne, + pre_approved=True) list(workflow) # Anne is now unsubscribed form the mailing list. member = self._mlist.regular_members.get_member(self._anne) @@ -198,10 +198,10 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): # address means the user gets unsubscribed to the mailing list without # any further confirmations or approvals. self._mlist.unsubscription_policy = ( - SubscriptionPolicy.confirm_then_moderate) - workflow = UnSubscriptionWorkflow(self._mlist, self.anne, - pre_approved=True, - pre_confirmed=True) + ConfirmModerationUnsubscriptionPolicy) + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne, + pre_approved=True, + pre_confirmed=True) list(workflow) member = self._mlist.regular_members.get_member(self._anne) self.assertIsNone(member) @@ -212,10 +212,8 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): def test_do_unsubscription_cleanups(self): # Once the user is unsubscribed, the token and its associated pending # database record will be removed from the database. - self._mlist.unsubscription_policy = SubscriptionPolicy.open - workflow = UnSubscriptionWorkflow(self._mlist, self.anne, - pre_approved=True, - pre_confirmed=True) + self._mlist.unsubscription_policy = OpenUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) # Run the workflow. list(workflow) # Anne is now unsubscribed from the list. @@ -229,9 +227,9 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): # The workflow runs until moderator approval is required, at which # point the workflow is saved. Once the moderator approves, the # workflow resumes and the user is unsubscribed. - self._mlist.unsubscription_policy = SubscriptionPolicy.moderate - workflow = UnSubscriptionWorkflow( - self._mlist, self.anne, pre_confirmed=True) + self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy( + self._mlist, self.anne) # Run the entire workflow. list(workflow) # The user is currently subscribed to the mailing list. @@ -244,7 +242,7 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): # Create a new workflow with the previous workflow's save token, and # restore its state. This models an approved un-sunscription request # and should result in the user getting subscribed. - approved_workflow = UnSubscriptionWorkflow(self._mlist) + approved_workflow = self._mlist.unsubscription_policy(self._mlist) approved_workflow.token = workflow.token approved_workflow.restore() list(approved_workflow) @@ -260,9 +258,9 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): # When the unsubscription is held for moderator approval, a message is # logged. mark = LogFileMark('mailman.subscribe') - self._mlist.unsubscription_policy = SubscriptionPolicy.moderate - workflow = UnSubscriptionWorkflow( - self._mlist, self.anne, pre_confirmed=True) + self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy( + self._mlist, self.anne) # Run the entire workflow. list(workflow) self.assertIn( @@ -277,9 +275,9 @@ class TestUnSubscriptionWorkflow(unittest.TestCase): # When the unsubscription is held for moderator approval, and the list # is so configured, a notification is sent to the list moderators. self._mlist.admin_immed_notify = True - self._mlist.unsubscription_policy = SubscriptionPolicy.moderate - workflow = UnSubscriptionWorkflow( - self._mlist, self.anne, pre_confirmed=True) + self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy( + self._mlist, self.anne) # Consume the entire state machine. list(workflow) items = get_queue_messages('virgin', expected_count=1) @@ -305,9 +303,9 @@ request approval: # the list is so configured, a notification is sent to the list # moderators. self._mlist.admin_immed_notify = False - self._mlist.unsubscription_policy = SubscriptionPolicy.moderate - workflow = UnSubscriptionWorkflow( - self._mlist, self.anne, pre_confirmed=True) + self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy( + self._mlist, self.anne) # Consume the entire state machine. list(workflow) get_queue_messages('virgin', expected_count=0) @@ -318,9 +316,9 @@ request approval: def test_send_confirmation(self): # A confirmation message gets sent when the unsubscription must be # confirmed. - self._mlist.unsubscription_policy = SubscriptionPolicy.confirm + self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy # Run the workflow to model the confirmation step. - workflow = UnSubscriptionWorkflow(self._mlist, self.anne) + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) list(workflow) items = get_queue_messages('virgin', expected_count=1) message = items[0].msg @@ -336,8 +334,8 @@ request approval: def test_do_confirmation_unsubscribes_user(self): # Unsubscriptions to the mailing list must be confirmed. Once that's # done, the user's address is unsubscribed. - self._mlist.unsubscription_policy = SubscriptionPolicy.confirm - workflow = UnSubscriptionWorkflow(self._mlist, self.anne) + self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) list(workflow) # Anne is a member. member = self._mlist.regular_members.get_member(self._anne) @@ -347,7 +345,7 @@ request approval: self.assertIsNotNone(workflow.token) self.assertEqual(workflow.token_owner, TokenOwner.subscriber) # Confirm. - confirm_workflow = UnSubscriptionWorkflow(self._mlist) + confirm_workflow = self._mlist.unsubscription_policy(self._mlist) confirm_workflow.token = workflow.token confirm_workflow.restore() list(confirm_workflow) @@ -363,8 +361,8 @@ request approval: # done, the address is unsubscribed. address = self.anne.register('anne.person@example.com') self._mlist.subscribe(address) - self._mlist.unsubscription_policy = SubscriptionPolicy.confirm - workflow = UnSubscriptionWorkflow(self._mlist, address) + self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, address) list(workflow) # Bart is a member. member = self._mlist.regular_members.get_member( @@ -375,7 +373,7 @@ request approval: self.assertIsNotNone(workflow.token) self.assertEqual(workflow.token_owner, TokenOwner.subscriber) # Confirm. - confirm_workflow = UnSubscriptionWorkflow(self._mlist) + confirm_workflow = self._mlist.unsubscription_policy(self._mlist) confirm_workflow.token = workflow.token confirm_workflow.restore() list(confirm_workflow) @@ -390,8 +388,8 @@ request approval: def test_do_confirmation_nonmember(self): # Attempt to confirm the unsubscription of a member who has already # been unsubscribed. - self._mlist.unsubscription_policy = SubscriptionPolicy.confirm - workflow = UnSubscriptionWorkflow(self._mlist, self.anne) + self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) list(workflow) # Anne is a member. member = self._mlist.regular_members.get_member(self._anne) @@ -403,7 +401,7 @@ request approval: # Unsubscribe Anne out of band. member.unsubscribe() # Confirm. - confirm_workflow = UnSubscriptionWorkflow(self._mlist) + confirm_workflow = self._mlist.unsubscription_policy(self._mlist) confirm_workflow.token = workflow.token confirm_workflow.restore() list(confirm_workflow) @@ -414,8 +412,8 @@ request approval: def test_do_confirmation_nonmember_final_step(self): # Attempt to confirm the unsubscription of a member who has already # been unsubscribed. - self._mlist.unsubscription_policy = SubscriptionPolicy.confirm - workflow = UnSubscriptionWorkflow(self._mlist, self.anne) + self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) list(workflow) # Anne is a member. member = self._mlist.regular_members.get_member(self._anne) @@ -425,7 +423,7 @@ request approval: self.assertIsNotNone(workflow.token) self.assertEqual(workflow.token_owner, TokenOwner.subscriber) # Confirm. - confirm_workflow = UnSubscriptionWorkflow(self._mlist) + confirm_workflow = self._mlist.unsubscription_policy(self._mlist) confirm_workflow.token = workflow.token confirm_workflow.restore() confirm_workflow.run_until('do_unsubscription') @@ -443,8 +441,8 @@ request approval: # the user confirming their subscription, and then the moderator # approving it, that different tokens are used in these two cases. self._mlist.unsubscription_policy = ( - SubscriptionPolicy.confirm_then_moderate) - workflow = UnSubscriptionWorkflow(self._mlist, self.anne) + ConfirmModerationUnsubscriptionPolicy) + workflow = self._mlist.unsubscription_policy(self._mlist, self.anne) # Run the state machine up to the first confirmation, and cache the # confirmation token. list(workflow) @@ -457,7 +455,7 @@ request approval: self.assertIsNotNone(workflow.token) self.assertEqual(workflow.token_owner, TokenOwner.subscriber) # The old token will not work for moderator approval. - moderator_workflow = UnSubscriptionWorkflow(self._mlist) + moderator_workflow = self._mlist.unsubscription_policy(self._mlist) moderator_workflow.token = token moderator_workflow.restore() list(moderator_workflow) @@ -468,7 +466,7 @@ request approval: # that there's a new token for the next steps. self.assertNotEqual(token, moderator_workflow.token) # The old token won't work. - final_workflow = UnSubscriptionWorkflow(self._mlist) + final_workflow = self._mlist.unsubscription_policy(self._mlist) final_workflow.token = token self.assertRaises(LookupError, final_workflow.restore) # Running this workflow will fail. @@ -492,9 +490,9 @@ request approval: def test_confirmation_needed_and_pre_confirmed(self): # The subscription policy is 'confirm' but the subscription is # pre-confirmed so the moderation checks can be skipped. - self._mlist.unsubscription_policy = SubscriptionPolicy.confirm - workflow = UnSubscriptionWorkflow( - self._mlist, self.anne, pre_confirmed=True, pre_approved=True) + self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy( + self._mlist, self.anne, pre_confirmed=True) list(workflow) # Anne was unsubscribed. self.assertIsNone(workflow.token) @@ -504,11 +502,11 @@ request approval: def test_confirmation_needed_moderator_address(self): address = self.anne.register('anne.person@example.com') self._mlist.subscribe(address) - self._mlist.unsubscription_policy = SubscriptionPolicy.moderate - workflow = UnSubscriptionWorkflow(self._mlist, address) + self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy + workflow = self._mlist.unsubscription_policy(self._mlist, address) # Get moderator approval. list(workflow) - approved_workflow = UnSubscriptionWorkflow(self._mlist) + approved_workflow = self._mlist.unsubscription_policy(self._mlist) approved_workflow.token = workflow.token approved_workflow.restore() list(approved_workflow) diff --git a/src/mailman/app/tests/test_workflowmanager.py b/src/mailman/app/tests/test_workflowmanager.py index 38ed2e468..e21e428f6 100644 --- a/src/mailman/app/tests/test_workflowmanager.py +++ b/src/mailman/app/tests/test_workflowmanager.py @@ -20,7 +20,6 @@ import unittest from mailman.app.lifecycle import create_list -from mailman.interfaces.mailinglist import SubscriptionPolicy from mailman.interfaces.member import MemberRole from mailman.interfaces.pending import IPendings from mailman.interfaces.subscriptions import ISubscriptionManager, TokenOwner @@ -28,6 +27,9 @@ from mailman.interfaces.usermanager import IUserManager from mailman.testing.helpers import get_queue_messages from mailman.testing.layers import ConfigLayer from mailman.utilities.datetime import now +from mailman.workflows.subscription import ( + ConfirmModerationSubscriptionPolicy, ConfirmSubscriptionPolicy, + ModerationSubscriptionPolicy, OpenSubscriptionPolicy) from zope.component import getUtility @@ -60,7 +62,7 @@ class TestRegistrar(unittest.TestCase): # Registering a subscription request where no confirmation or # moderation steps are needed, leaves us with no token or owner, since # there's nothing more to do. - self._mlist.subscription_policy = SubscriptionPolicy.open + self._mlist.subscription_policy = OpenSubscriptionPolicy self._anne.verified_on = now() token, token_owner, rmember = self._registrar.register(self._anne) self.assertIsNone(token) @@ -82,7 +84,7 @@ class TestRegistrar(unittest.TestCase): # (because she does not have a verified address), but not the moderator # to approve. Running the workflow gives us a token. Confirming the # token subscribes the user. - self._mlist.subscription_policy = SubscriptionPolicy.open + self._mlist.subscription_policy = OpenSubscriptionPolicy token, token_owner, rmember = self._registrar.register(self._anne) self.assertIsNotNone(token) self.assertEqual(token_owner, TokenOwner.subscriber) @@ -102,7 +104,7 @@ class TestRegistrar(unittest.TestCase): # (because of list policy), but not the moderator to approve. Running # the workflow gives us a token. Confirming the token subscribes the # user. - self._mlist.subscription_policy = SubscriptionPolicy.confirm + self._mlist.subscription_policy = ConfirmSubscriptionPolicy self._anne.verified_on = now() token, token_owner, rmember = self._registrar.register(self._anne) self.assertIsNotNone(token) @@ -122,7 +124,7 @@ class TestRegistrar(unittest.TestCase): # We have a subscription request which requires the moderator to # approve. Running the workflow gives us a token. Confirming the # token subscribes the user. - self._mlist.subscription_policy = SubscriptionPolicy.moderate + self._mlist.subscription_policy = ModerationSubscriptionPolicy self._anne.verified_on = now() token, token_owner, rmember = self._registrar.register(self._anne) self.assertIsNotNone(token) @@ -145,7 +147,7 @@ class TestRegistrar(unittest.TestCase): # token runs the workflow a little farther, but still gives us a # token. Confirming again subscribes the user. self._mlist.subscription_policy = ( - SubscriptionPolicy.confirm_then_moderate) + ConfirmModerationSubscriptionPolicy) self._anne.verified_on = now() # Runs until subscription confirmation. token, token_owner, rmember = self._registrar.register(self._anne) @@ -180,7 +182,7 @@ class TestRegistrar(unittest.TestCase): # sees when they approve the subscription. This prevents the user # from using a replay attack to subvert moderator approval. self._mlist.subscription_policy = ( - SubscriptionPolicy.confirm_then_moderate) + ConfirmModerationSubscriptionPolicy) self._anne.verified_on = now() # Runs until subscription confirmation. token, token_owner, rmember = self._registrar.register(self._anne) @@ -216,7 +218,7 @@ class TestRegistrar(unittest.TestCase): def test_discard_waiting_for_confirmation(self): # While waiting for a user to confirm their subscription, we discard # the workflow. - self._mlist.subscription_policy = SubscriptionPolicy.confirm + self._mlist.subscription_policy = ConfirmSubscriptionPolicy self._anne.verified_on = now() # Runs until subscription confirmation. token, token_owner, rmember = self._registrar.register(self._anne) @@ -233,7 +235,7 @@ class TestRegistrar(unittest.TestCase): def test_admin_notify_mchanges(self): # When a user gets subscribed via the subscription policy workflow, # the list administrators get an email notification. - self._mlist.subscription_policy = SubscriptionPolicy.open + self._mlist.subscription_policy = OpenSubscriptionPolicy self._mlist.admin_notify_mchanges = True self._mlist.send_welcome_message = False token, token_owner, member = self._registrar.register( @@ -253,7 +255,7 @@ anne@example.com has been successfully subscribed to Ant. # Even when a user gets subscribed via the subscription policy # workflow, the list administrators won't get an email notification if # they don't want one. - self._mlist.subscription_policy = SubscriptionPolicy.open + self._mlist.subscription_policy = OpenSubscriptionPolicy self._mlist.admin_notify_mchanges = False self._mlist.send_welcome_message = False # Bart is an administrator of the mailing list. |
