summaryrefslogtreecommitdiff
path: root/src/mailman/app
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/app')
-rw-r--r--src/mailman/app/docs/moderator.rst4
-rw-r--r--src/mailman/app/subscriptions.py86
-rw-r--r--src/mailman/app/tests/test_moderation.py5
-rw-r--r--src/mailman/app/tests/test_subscriptions.py9
-rw-r--r--src/mailman/app/tests/test_unsubscriptions.py13
-rw-r--r--src/mailman/app/tests/test_workflowmanager.py5
-rw-r--r--src/mailman/app/workflow.py8
7 files changed, 45 insertions, 85 deletions
diff --git a/src/mailman/app/docs/moderator.rst b/src/mailman/app/docs/moderator.rst
index e183d050c..ce25a4711 100644
--- a/src/mailman/app/docs/moderator.rst
+++ b/src/mailman/app/docs/moderator.rst
@@ -217,12 +217,12 @@ the unsubscribing address is required.
Fred is a member of the mailing list...
>>> from mailman.interfaces.usermanager import IUserManager
- >>> from zope.component import getAdapter, getUtility
+ >>> from zope.component import getUtility
>>> mlist.send_welcome_message = False
>>> fred = getUtility(IUserManager).create_address(
... 'fred@example.com', 'Fred Person')
>>> from mailman.interfaces.subscriptions import ISubscriptionManager
- >>> registrar = getAdapter(mlist, ISubscriptionManager, name='subscribe')
+ >>> registrar = ISubscriptionManager(mlist)
>>> token, token_owner, member = registrar.register(
... fred, pre_verified=True, pre_confirmed=True, pre_approved=True)
>>> member
diff --git a/src/mailman/app/subscriptions.py b/src/mailman/app/subscriptions.py
index 2790a6751..15df6b3f3 100644
--- a/src/mailman/app/subscriptions.py
+++ b/src/mailman/app/subscriptions.py
@@ -297,7 +297,9 @@ class SubscriptionWorkflow(Workflow):
# We can immediately subscribe the user to the mailing list.
self.member = self.mlist.subscribe(self.subscriber)
# This workflow is done so throw away any associated state.
- getUtility(IWorkflowStateManager).restore(self.name, self.token)
+ if self.token is not None:
+ getUtility(IWorkflowStateManager).discard(self.token)
+ self._set_token(TokenOwner.no_one)
def _step_send_confirmation(self):
self._set_token(TokenOwner.subscriber)
@@ -533,7 +535,9 @@ class UnSubscriptionWorkflow(Workflow):
pass
self.member = None
# This workflow is done so throw away any associated state.
- getUtility(IWorkflowStateManager).restore(self.name, self.token)
+ if self.token is not None:
+ getUtility(IWorkflowStateManager).discard(self.token)
+ self._set_token(TokenOwner.no_one)
def _step_unsubscribe_from_restored(self):
# Prevent replay attacks.
@@ -546,48 +550,11 @@ class UnSubscriptionWorkflow(Workflow):
self.push('do_unsubscription')
-class BaseSubscriptionManager:
- """Base class to handle registration and un-registration workflows."""
-
- def __init__(self, mlist):
- self._mlist = mlist
-
- def _get_workflow(self):
- raise NotImplementedError
-
- def register(self, subscriber=None, *,
- pre_verified=False, pre_confirmed=False, pre_approved=False):
- raise NotImplementedError
-
- def unregister(self, subscriber=None, *,
- pre_confirmed=False, pre_approved=False):
- raise NotImplementedError
-
- def confirm(self, token):
- workflow = self._get_workflow()
- workflow.token = token
- workflow.restore()
- # In order to just run the whole workflow, all we need to do
- # is iterate over the workflow object. On calling the __next__
- # over the workflow iterator it automatically executes the steps
- # that needs to be done.
- list(workflow)
- return workflow.token, workflow.token_owner, workflow.member
-
- def discard(self, token):
- with flush():
- getUtility(IPendings).confirm(token)
- getUtility(IWorkflowStateManager).discard(
- self._get_workflow().name, token)
-
-
@public
@implementer(ISubscriptionManager)
-class SubscriptionManager(BaseSubscriptionManager):
- """Handle registrations and confirmations for subscriptions."""
-
- def _get_workflow(self):
- return SubscriptionWorkflow(self._mlist)
+class SubscriptionManager:
+ def __init__(self, mlist):
+ self._mlist = mlist
def register(self, subscriber=None, *,
pre_verified=False, pre_confirmed=False, pre_approved=False):
@@ -600,15 +567,6 @@ class SubscriptionManager(BaseSubscriptionManager):
list(workflow)
return workflow.token, workflow.token_owner, workflow.member
-
-@public
-@implementer(ISubscriptionManager)
-class UnsubscriptionManager(BaseSubscriptionManager):
- """Handle un-subscriptions and confirmations for un-subscriptions."""
-
- def _get_workflow(self):
- return UnSubscriptionWorkflow(self._mlist)
-
def unregister(self, subscriber=None, *,
pre_confirmed=False, pre_approved=False):
workflow = UnSubscriptionWorkflow(
@@ -618,6 +576,32 @@ class UnsubscriptionManager(BaseSubscriptionManager):
list(workflow)
return workflow.token, workflow.token_owner, workflow.member
+ def confirm(self, token):
+ if token is None:
+ raise LookupError
+ pendable = getUtility(IPendings).confirm(token, expunge=False)
+ if pendable is None:
+ raise LookupError
+ workflow_type = pendable.get('type')
+ assert workflow_type in (PendableSubscription.PEND_TYPE,
+ PendableUnsubscription.PEND_TYPE)
+ workflow = (SubscriptionWorkflow
+ if workflow_type == PendableSubscription.PEND_TYPE
+ else UnSubscriptionWorkflow)(self._mlist)
+ workflow.token = token
+ workflow.restore()
+ # In order to just run the whole workflow, all we need to do
+ # is iterate over the workflow object. On calling the __next__
+ # over the workflow iterator it automatically executes the steps
+ # that needs to be done.
+ list(workflow)
+ return workflow.token, workflow.token_owner, workflow.member
+
+ def discard(self, token):
+ with flush():
+ getUtility(IPendings).confirm(token)
+ getUtility(IWorkflowStateManager).discard(token)
+
def _handle_confirmation_needed_events(event, template_name):
subject = 'confirm {}'.format(event.token)
diff --git a/src/mailman/app/tests/test_moderation.py b/src/mailman/app/tests/test_moderation.py
index 63b665948..90485bfad 100644
--- a/src/mailman/app/tests/test_moderation.py
+++ b/src/mailman/app/tests/test_moderation.py
@@ -35,7 +35,7 @@ from mailman.testing.helpers import (
specialized_message_from_string as mfs)
from mailman.testing.layers import SMTPLayer
from mailman.utilities.datetime import now
-from zope.component import getAdapter, getUtility
+from zope.component import getUtility
class TestModeration(unittest.TestCase):
@@ -153,8 +153,7 @@ class TestUnsubscription(unittest.TestCase):
def setUp(self):
self._mlist = create_list('test@example.com')
- self._registrar = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe')
+ self._registrar = ISubscriptionManager(self._mlist)
def test_unsubscribe_defer(self):
# When unsubscriptions must be approved by the moderator, but the
diff --git a/src/mailman/app/tests/test_subscriptions.py b/src/mailman/app/tests/test_subscriptions.py
index 9f02593a9..a6a00d80e 100644
--- a/src/mailman/app/tests/test_subscriptions.py
+++ b/src/mailman/app/tests/test_subscriptions.py
@@ -359,8 +359,6 @@ class TestSubscriptionWorkflow(unittest.TestCase):
pre_verified=True,
pre_confirmed=True,
pre_approved=True)
- # Cache the token.
- token = workflow.token
# Consume the entire state machine.
list(workflow)
# Anne is now a member of the mailing list.
@@ -370,13 +368,6 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# The workflow is done, so it has no token.
self.assertIsNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.no_one)
- # The pendable associated with the token has been evicted.
- self.assertIsNone(getUtility(IPendings).confirm(token, expunge=False))
- # There is no saved workflow associated with the token. This shows up
- # as an exception when we try to restore the workflow.
- new_workflow = SubscriptionWorkflow(self._mlist)
- new_workflow.token = token
- self.assertRaises(LookupError, new_workflow.restore)
def test_moderator_approves(self):
# The workflow runs until moderator approval is required, at which
diff --git a/src/mailman/app/tests/test_unsubscriptions.py b/src/mailman/app/tests/test_unsubscriptions.py
index b7693f774..d8dbc18cb 100644
--- a/src/mailman/app/tests/test_unsubscriptions.py
+++ b/src/mailman/app/tests/test_unsubscriptions.py
@@ -184,7 +184,7 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
self.assertIsNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.no_one)
- def test_do_unsubscription_pre_approved_pre_onfirmed(self):
+ def test_do_unsubscription_pre_approved_pre_confirmed(self):
# A moderation-requiring un-subscription policy plus a pre-appvoed
# address means the user gets un-subscribed to the mailing list without
# any further confirmations or approvals.
@@ -201,14 +201,12 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
self.assertEqual(workflow.token_owner, TokenOwner.no_one)
def test_do_unsubscription_cleanups(self):
- # Once the user is un-subscribed, the token and its associated pending
+ # 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)
- # Cache the token.
- token = workflow.token
# Run the workflow.
list(workflow)
# Anne is now un-subscribed from the list.
@@ -217,13 +215,6 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
# Workflow is done, so it has no token.
self.assertIsNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.no_one)
- # The pendable associated with the token as been evicted.
- self.assertIsNone(getUtility(IPendings).confirm(token, expunge=False))
- # There is no workflow associated with the token. This shows up as an
- # exception when trying to restore the workflow.
- new_workflow = UnSubscriptionWorkflow(self._mlist)
- new_workflow.token = token
- self.assertRaises(LookupError, new_workflow.restore)
def test_moderator_approves(self):
# The workflow runs until moderator approval is required, at which
diff --git a/src/mailman/app/tests/test_workflowmanager.py b/src/mailman/app/tests/test_workflowmanager.py
index f72486111..4193beefe 100644
--- a/src/mailman/app/tests/test_workflowmanager.py
+++ b/src/mailman/app/tests/test_workflowmanager.py
@@ -28,7 +28,7 @@ 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 zope.component import getAdapter, getUtility
+from zope.component import getUtility
class TestRegistrar(unittest.TestCase):
@@ -38,8 +38,7 @@ class TestRegistrar(unittest.TestCase):
def setUp(self):
self._mlist = create_list('ant@example.com')
- self._registrar = getAdapter(
- self._mlist, ISubscriptionManager, name='subscribe')
+ self._registrar = ISubscriptionManager(self._mlist)
self._pendings = getUtility(IPendings)
self._anne = getUtility(IUserManager).create_address(
'anne@example.com')
diff --git a/src/mailman/app/workflow.py b/src/mailman/app/workflow.py
index eec8a14a8..762b0fd91 100644
--- a/src/mailman/app/workflow.py
+++ b/src/mailman/app/workflow.py
@@ -132,15 +132,11 @@ class Workflow:
raise AssertionError(
"Can't save a workflow state with more than one step "
"in the queue")
- state_manager.save(
- self.__class__.__name__,
- self.token,
- step,
- json.dumps(data))
+ state_manager.save(self.token, step, json.dumps(data))
def restore(self):
state_manager = getUtility(IWorkflowStateManager)
- state = state_manager.restore(self.__class__.__name__, self.token)
+ state = state_manager.restore(self.token)
if state is None:
# The token doesn't exist in the database.
raise LookupError(self.token)