summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAurélien Bompard2015-03-25 19:21:38 +0100
committerAurélien Bompard2015-03-25 19:21:38 +0100
commit035d023662e1347e7dc3a5347d17932bfbe8c7e3 (patch)
tree492ed913e0dd5df2c819261d358c73c4ea989873 /src
parent990f3c63814bcfddef2e661248c44e67e945de04 (diff)
downloadmailman-035d023662e1347e7dc3a5347d17932bfbe8c7e3.tar.gz
mailman-035d023662e1347e7dc3a5347d17932bfbe8c7e3.tar.zst
mailman-035d023662e1347e7dc3a5347d17932bfbe8c7e3.zip
Diffstat (limited to 'src')
-rw-r--r--src/mailman/app/subscriptions.py16
-rw-r--r--src/mailman/app/tests/test_subscriptions.py15
-rw-r--r--src/mailman/config/configure.zcml4
-rw-r--r--src/mailman/interfaces/workflowstate.py30
-rw-r--r--src/mailman/model/workflowstate.py27
5 files changed, 88 insertions, 4 deletions
diff --git a/src/mailman/app/subscriptions.py b/src/mailman/app/subscriptions.py
index ca84e091f..04e0955cb 100644
--- a/src/mailman/app/subscriptions.py
+++ b/src/mailman/app/subscriptions.py
@@ -44,6 +44,7 @@ from mailman.interfaces.subscriptions import (
ISubscriptionService, MissingUserError, RequestRecord)
from mailman.interfaces.user import IUser
from mailman.interfaces.usermanager import IUserManager
+from mailman.interfaces.workflowstate import IWorkflowStateManager
from mailman.model.member import Member
from mailman.utilities.datetime import now
@@ -74,6 +75,7 @@ class SubscriptionWorkflow:
self.pre_verified = pre_verified
self.pre_confirmed = pre_confirmed
self.pre_approved = pre_approved
+ self._save_key = "{}:{}".format(self.mlist.list_id, self.address.email)
# Prepare the state machine.
self._next = deque()
self._next.append("verification_check")
@@ -95,6 +97,20 @@ class SubscriptionWorkflow:
except:
raise
+ def save_state(self):
+ manager = getUtility(IWorkflowStateManager)
+ # Note: only the next step is saved, not the whole stack. Not an issue
+ # since there's never more than a single step in the queue anyway.
+ # Also: we don't save & restore the self.pre_* variables, but we could,
+ # using the data argument.
+ manager.save(self.__class__.__name__, self._save_key, self._next[0])
+
+ def restore_state(self):
+ manager = getUtility(IWorkflowStateManager)
+ state = manager.restore(self.__class__.__name__, self._save_key)
+ if state is not None:
+ self._next[0] = state.step
+
def _maybe_set_preferred_address(self):
if self.user is None:
# The address has no linked user so create one, link it, and set
diff --git a/src/mailman/app/tests/test_subscriptions.py b/src/mailman/app/tests/test_subscriptions.py
index 7bb59bb45..97dbd8382 100644
--- a/src/mailman/app/tests/test_subscriptions.py
+++ b/src/mailman/app/tests/test_subscriptions.py
@@ -82,6 +82,21 @@ class TestSubscriptionWorkflow(unittest.TestCase):
self._anne = 'anne@example.com'
self._user_manager = getUtility(IUserManager)
+ def test_save_restore(self):
+ anne = self._user_manager.create_address(self._anne, 'Anne Person')
+ workflow = SubscriptionWorkflow(
+ self._mlist, anne,
+ pre_verified=True, pre_confirmed=False, pre_approved=False)
+ next(workflow)
+ next_step = workflow._next[0]
+ workflow.save_state()
+ # Now create a new instance and restore
+ workflow = SubscriptionWorkflow(
+ self._mlist, anne,
+ pre_verified=True, pre_confirmed=False, pre_approved=False)
+ workflow.restore_state()
+ self.assertEqual(next_step, workflow._next[0])
+
def test_preverified_address_joins_open_list(self):
# The mailing list has an open subscription policy, so the subscriber
# becomes a member with no human intervention.
diff --git a/src/mailman/config/configure.zcml b/src/mailman/config/configure.zcml
index 6f5876aa8..f6cb6dac1 100644
--- a/src/mailman/config/configure.zcml
+++ b/src/mailman/config/configure.zcml
@@ -118,8 +118,8 @@
/>
<utility
- provides="mailman.interfaces.workflowstate.IWorkflowState"
- factory="mailman.model.workflowstate.WorkflowState"
+ provides="mailman.interfaces.workflowstate.IWorkflowStateManager"
+ factory="mailman.model.workflowstate.WorkflowStateManager"
/>
</configure>
diff --git a/src/mailman/interfaces/workflowstate.py b/src/mailman/interfaces/workflowstate.py
index bb08fef2d..186386170 100644
--- a/src/mailman/interfaces/workflowstate.py
+++ b/src/mailman/interfaces/workflowstate.py
@@ -19,6 +19,7 @@
__all__ = [
'IWorkflowState',
+ 'IWorkflowStateManager',
]
@@ -27,7 +28,7 @@ from zope.interface import Interface, Attribute
class IWorkflowState(Interface):
- """A basic user."""
+ """The state of a workflow."""
name = Attribute(
"""The name of the workflow.""")
@@ -40,3 +41,30 @@ class IWorkflowState(Interface):
data = Attribute(
"""Additional data (may be JSON-encodedeJSON .""")
+
+
+
+class IWorkflowStateManager(Interface):
+ """The workflow states manager."""
+
+ def save(name, key, step, data=None):
+ """Save the state of a workflow
+
+ :param name: The name of the workflow.
+ :type name: str
+ :param key: A unique key identifying this workflow instance.
+ :type key: str
+ :param step: The next step for this workflow.
+ :type step: str
+ :param data: Additional data (workflow-specific).
+ :type data: str
+ """
+
+ def restore(name, key):
+ """Get the saved state for a workflow or None if nothing was saved.
+
+ :param name: The name of the workflow.
+ :type name: str
+ :param key: A unique key identifying this workflow instance.
+ :type key: str
+ """
diff --git a/src/mailman/model/workflowstate.py b/src/mailman/model/workflowstate.py
index 5e3301dcf..ee0226d61 100644
--- a/src/mailman/model/workflowstate.py
+++ b/src/mailman/model/workflowstate.py
@@ -19,11 +19,14 @@
__all__ = [
'WorkflowState',
+ 'WorkflowStateManager',
]
from mailman.database.model import Model
-from mailman.interfaces.workflowstate import IWorkflowState
+from mailman.database.transaction import dbconnection
+from mailman.interfaces.workflowstate import (
+ IWorkflowState, IWorkflowStateManager)
from sqlalchemy import Column, Unicode
from zope.interface import implementer
@@ -39,3 +42,25 @@ class WorkflowState(Model):
key = Column(Unicode, primary_key=True)
step = Column(Unicode, nullable=False)
data = Column(Unicode)
+
+
+
+@implementer(IWorkflowStateManager)
+class WorkflowStateManager:
+ """See `IWorkflowStateManager`."""
+
+ @dbconnection
+ def save(self, store, name, key, step, data=None):
+ """See `IWorkflowStateManager`."""
+ state = store.query(WorkflowState).get((name, key))
+ if state is None:
+ state = store.add(WorkflowState(
+ name=name, key=key, step=step, data=data))
+ else:
+ state.step = step
+ state.data = data
+
+ @dbconnection
+ def restore(self, store, name, key):
+ """See `IWorkflowStateManager`."""
+ return store.query(WorkflowState).get((name, key))