summaryrefslogtreecommitdiff
path: root/src/mailman/rest
diff options
context:
space:
mode:
authorJ08nY2017-08-07 19:00:49 +0200
committerJ08nY2017-08-07 19:00:49 +0200
commitee9da27283ffb7adc836f764f1442cd06e3fb2a5 (patch)
tree2b687f39714580b1de70baf9e3dd9957326c4989 /src/mailman/rest
parentd107fd41f03b57f7731b60bb7ba921febc3ce3b9 (diff)
parentb902d7858d8302d248add89a5983c521c3581c4c (diff)
downloadmailman-plugin.tar.gz
mailman-plugin.tar.zst
mailman-plugin.zip
Diffstat (limited to 'src/mailman/rest')
-rw-r--r--src/mailman/rest/docs/membership.rst2
-rw-r--r--src/mailman/rest/docs/sub-moderation.rst9
-rw-r--r--src/mailman/rest/listconf.py26
-rw-r--r--src/mailman/rest/members.py61
-rw-r--r--src/mailman/rest/sub_moderation.py14
-rw-r--r--src/mailman/rest/tests/test_listconf.py6
-rw-r--r--src/mailman/rest/tests/test_membership.py19
-rw-r--r--src/mailman/rest/tests/test_moderation.py7
-rw-r--r--src/mailman/rest/tests/test_users.py2
-rw-r--r--src/mailman/rest/tests/test_validator.py44
-rw-r--r--src/mailman/rest/validator.py49
11 files changed, 178 insertions, 61 deletions
diff --git a/src/mailman/rest/docs/membership.rst b/src/mailman/rest/docs/membership.rst
index b0b5e1254..6e24d14f9 100644
--- a/src/mailman/rest/docs/membership.rst
+++ b/src/mailman/rest/docs/membership.rst
@@ -642,7 +642,6 @@ won't have to approve her subscription request.
... 'display_name': 'Elly Person',
... 'pre_verified': True,
... 'pre_confirmed': True,
- ... 'pre_approved': True,
... })
content-length: 0
content-type: application/json; charset=UTF-8
@@ -699,7 +698,6 @@ list with her preferred address.
... 'subscriber': user_id,
... 'pre_verified': True,
... 'pre_confirmed': True,
- ... 'pre_approved': True,
... })
content-length: 0
content-type: application/json; charset=UTF-8
diff --git a/src/mailman/rest/docs/sub-moderation.rst b/src/mailman/rest/docs/sub-moderation.rst
index 92c0c8849..8bf95fcd2 100644
--- a/src/mailman/rest/docs/sub-moderation.rst
+++ b/src/mailman/rest/docs/sub-moderation.rst
@@ -13,8 +13,8 @@ A mailing list starts with no pending subscription or unsubscription requests.
>>> ant = create_list('ant@example.com')
>>> ant.admin_immed_notify = False
- >>> from mailman.interfaces.mailinglist import SubscriptionPolicy
- >>> ant.subscription_policy = SubscriptionPolicy.moderate
+ >>> from mailman.workflows.subscription import ModerationSubscriptionPolicy
+ >>> ant.subscription_policy = ModerationSubscriptionPolicy
>>> transaction.commit()
>>> dump_json('http://localhost:9001/3.0/lists/ant.example.com/requests')
http_etag: "..."
@@ -31,7 +31,6 @@ is returned to track her subscription request.
... 'subscriber': 'anne@example.com',
... 'display_name': 'Anne Person',
... 'pre_verified': True,
- ... 'pre_confirmed': True,
... })
http_etag: ...
token: 0000000000000000000000000000000000000001
@@ -48,7 +47,7 @@ The subscription request can be viewed in the REST API.
list_id: ant.example.com
token: 0000000000000000000000000000000000000001
token_owner: moderator
- type: subscription
+ type: sub-policy-moderate
when: 2005-08-01T07:49:23
http_etag: "..."
start: 0
@@ -69,7 +68,7 @@ You can view an individual membership change request by providing the token
list_id: ant.example.com
token: 0000000000000000000000000000000000000001
token_owner: moderator
- type: subscription
+ type: sub-policy-moderate
when: 2005-08-01T07:49:23
diff --git a/src/mailman/rest/listconf.py b/src/mailman/rest/listconf.py
index b62d34529..70f04999c 100644
--- a/src/mailman/rest/listconf.py
+++ b/src/mailman/rest/listconf.py
@@ -24,14 +24,17 @@ from mailman.interfaces.archiver import ArchivePolicy
from mailman.interfaces.autorespond import ResponseAction
from mailman.interfaces.digests import DigestFrequency
from mailman.interfaces.mailinglist import (
- DMARCMitigateAction, IAcceptableAliasSet, IMailingList, ReplyToMunging,
- SubscriptionPolicy)
+ DMARCMitigateAction, IAcceptableAliasSet, IMailingList, ReplyToMunging)
from mailman.interfaces.template import ITemplateManager
+from mailman.interfaces.workflows import ISubscriptionWorkflow
from mailman.rest.helpers import (
GetterSetter, bad_request, etag, no_content, not_found, okay)
from mailman.rest.validator import (
PatchValidator, ReadOnlyPATCHRequestError, UnknownPATCHRequestError,
- Validator, enum_validator, list_of_strings_validator)
+ Validator, enum_validator, list_of_strings_validator, policy_validator)
+from mailman.workflows.subscription import (
+ ConfirmModerationSubscriptionPolicy, ConfirmSubscriptionPolicy,
+ ModerationSubscriptionPolicy, OpenSubscriptionPolicy)
from public import public
from zope.component import getUtility
@@ -86,6 +89,20 @@ class URIAttributeMapper(GetterSetter):
getUtility(ITemplateManager).set(template_name, obj.list_id, value)
+class SubscriptionPolicyMapper(GetterSetter):
+
+ def get(self, obj, attribute):
+ assert IMailingList.providedBy(obj), obj
+ old_sub_map = {
+ OpenSubscriptionPolicy: 'open',
+ ConfirmSubscriptionPolicy: 'confirm',
+ ModerationSubscriptionPolicy: 'moderate',
+ ConfirmModerationSubscriptionPolicy: 'confirm_then_moderate'
+ }
+ cls = getattr(obj, attribute)
+ return old_sub_map.get(cls, cls.name)
+
+
# Additional validators for converting from web request strings to internal
# data types. See below for details.
@@ -179,7 +196,8 @@ ATTRIBUTES = dict(
request_address=GetterSetter(None),
send_welcome_message=GetterSetter(as_boolean),
subject_prefix=GetterSetter(str),
- subscription_policy=GetterSetter(enum_validator(SubscriptionPolicy)),
+ subscription_policy=SubscriptionPolicyMapper(
+ policy_validator(ISubscriptionWorkflow)),
volume=GetterSetter(None),
)
diff --git a/src/mailman/rest/members.py b/src/mailman/rest/members.py
index 3ff712259..2d5b95115 100644
--- a/src/mailman/rest/members.py
+++ b/src/mailman/rest/members.py
@@ -17,7 +17,6 @@
"""REST for members."""
-from lazr.config import as_boolean
from mailman.app.membership import add_member, delete_member
from mailman.interfaces.action import Action
from mailman.interfaces.address import IAddress
@@ -198,22 +197,43 @@ class AllMembers(_MemberBase):
def on_post(self, request, response):
"""Create a new member."""
- try:
- validator = Validator(
- list_id=str,
- subscriber=subscriber_validator(self.api),
- display_name=str,
- delivery_mode=enum_validator(DeliveryMode),
- role=enum_validator(MemberRole),
- pre_verified=as_boolean,
- pre_confirmed=as_boolean,
- pre_approved=as_boolean,
- _optional=('delivery_mode', 'display_name', 'role',
- 'pre_verified', 'pre_confirmed', 'pre_approved'))
- arguments = validator(request)
- except ValueError as error:
- bad_request(response, str(error))
+ # Validate the params manually as the subscription_policy workflow
+ # attributes are dynamic, so parse all known and optional attirbutes
+ # and leave the rest to policy_kwargs.
+ required_arguments = ['list_id', 'subscriber']
+ known_arguments = dict(list_id=str,
+ subscriber=subscriber_validator(self.api),
+ display_name=str,
+ delivery_mode=enum_validator(DeliveryMode),
+ role=enum_validator(MemberRole))
+
+ arguments = {}
+ policy_kwargs = {}
+
+ wrong = []
+ for key, value in request.params.items():
+ try:
+ if key in known_arguments:
+ converter = known_arguments[key]
+ arguments[key] = converter(value)
+ else:
+ policy_kwargs[key] = value
+ except ValueError:
+ wrong.append(key)
+
+ if len(wrong) > 0:
+ params = ', '.join(wrong)
+ bad_request(response,
+ 'Cannot convert parameters: {}'.format(params))
return
+
+ missing = [key for key in required_arguments if key not in arguments]
+ if len(missing) > 0:
+ bad_request(response, 'Missing parameters: {}'.format(missing))
+ return
+ # XXX policy_kwargs are string, while subscription workflows expects
+ # whatever.
+
# Dig the mailing list out of the arguments.
list_id = arguments.pop('list_id')
mlist = getUtility(IListManager).get_by_list_id(list_id)
@@ -247,20 +267,13 @@ class AllMembers(_MemberBase):
# nonmembers go through the legacy API for now.
role = arguments.pop('role', MemberRole.member)
if role is MemberRole.member:
- # Get the pre_ flags for the subscription workflow.
- pre_verified = arguments.pop('pre_verified', False)
- pre_confirmed = arguments.pop('pre_confirmed', False)
- pre_approved = arguments.pop('pre_approved', False)
# Now we can run the registration process until either the
# subscriber is subscribed, or the workflow is paused for
# verification, confirmation, or approval.
registrar = ISubscriptionManager(mlist)
try:
token, token_owner, member = registrar.register(
- subscriber,
- pre_verified=pre_verified,
- pre_confirmed=pre_confirmed,
- pre_approved=pre_approved)
+ subscriber, **policy_kwargs)
except AlreadySubscribedError:
conflict(response, b'Member already subscribed')
return
diff --git a/src/mailman/rest/sub_moderation.py b/src/mailman/rest/sub_moderation.py
index 47745b729..ad1c5751b 100644
--- a/src/mailman/rest/sub_moderation.py
+++ b/src/mailman/rest/sub_moderation.py
@@ -16,13 +16,16 @@
# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
"""REST API for held subscription requests."""
+from itertools import chain
from mailman.app.moderator import send_rejection
+from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.action import Action
from mailman.interfaces.member import AlreadySubscribedError
from mailman.interfaces.pending import IPendings
from mailman.interfaces.subscriptions import ISubscriptionManager
+from mailman.interfaces.workflows import ISubscriptionWorkflow
from mailman.rest.helpers import (
CollectionMixin, bad_request, child, conflict, etag, no_content,
not_found, okay)
@@ -122,8 +125,15 @@ class SubscriptionRequests(_ModerationBase, CollectionMixin):
self._mlist = mlist
def _get_collection(self, request):
- pendings = getUtility(IPendings).find(
- mlist=self._mlist, pend_type='subscription')
+ sub_workflows = [workflow_class
+ for workflow_class in config.workflows.values()
+ if ISubscriptionWorkflow.implementedBy(workflow_class)
+ ]
+ generators = [getUtility(IPendings).find(mlist=self._mlist,
+ pend_type=sub_workflow.name)
+ for
+ sub_workflow in sub_workflows]
+ pendings = chain.from_iterable(generators)
return [token for token, pendable in pendings]
def on_get(self, request, response):
diff --git a/src/mailman/rest/tests/test_listconf.py b/src/mailman/rest/tests/test_listconf.py
index 782effd29..bb88feb61 100644
--- a/src/mailman/rest/tests/test_listconf.py
+++ b/src/mailman/rest/tests/test_listconf.py
@@ -22,11 +22,11 @@ import unittest
from mailman.app.lifecycle import create_list
from mailman.database.transaction import transaction
from mailman.interfaces.digests import DigestFrequency
-from mailman.interfaces.mailinglist import (
- IAcceptableAliasSet, SubscriptionPolicy)
+from mailman.interfaces.mailinglist import IAcceptableAliasSet
from mailman.interfaces.template import ITemplateManager
from mailman.testing.helpers import call_api
from mailman.testing.layers import RESTLayer
+from mailman.workflows.subscription import ConfirmModerationSubscriptionPolicy
from urllib.error import HTTPError
from zope.component import getUtility
@@ -197,7 +197,7 @@ class TestConfiguration(unittest.TestCase):
self.assertEqual(response.status_code, 204)
# And now we verify that it has the requested setting.
self.assertEqual(self._mlist.subscription_policy,
- SubscriptionPolicy.confirm_then_moderate)
+ ConfirmModerationSubscriptionPolicy)
def test_patch_attribute_double(self):
with self.assertRaises(HTTPError) as cm:
diff --git a/src/mailman/rest/tests/test_membership.py b/src/mailman/rest/tests/test_membership.py
index e5a2ce283..bb0134ac5 100644
--- a/src/mailman/rest/tests/test_membership.py
+++ b/src/mailman/rest/tests/test_membership.py
@@ -23,7 +23,6 @@ from mailman.app.lifecycle import create_list
from mailman.config import config
from mailman.database.transaction import transaction
from mailman.interfaces.bans import IBanManager
-from mailman.interfaces.mailinglist import SubscriptionPolicy
from mailman.interfaces.member import DeliveryMode, MemberRole
from mailman.interfaces.subscriptions import ISubscriptionManager, TokenOwner
from mailman.interfaces.usermanager import IUserManager
@@ -33,6 +32,8 @@ from mailman.testing.helpers import (
set_preferred, subscribe, wait_for_webservice)
from mailman.testing.layers import ConfigLayer, RESTLayer
from mailman.utilities.datetime import now
+from mailman.workflows.subscription import (
+ ConfirmModerationSubscriptionPolicy, ModerationSubscriptionPolicy)
from urllib.error import HTTPError
from zope.component import getUtility
@@ -93,7 +94,6 @@ class TestMembership(unittest.TestCase):
'subscriber': 'anne@example.com',
'pre_verified': True,
'pre_confirmed': True,
- 'pre_approved': True,
})
self.assertEqual(cm.exception.code, 409)
self.assertEqual(cm.exception.reason, 'Member already subscribed')
@@ -108,7 +108,6 @@ class TestMembership(unittest.TestCase):
'subscriber': 'anne@example.com',
'pre_verified': False,
'pre_confirmed': False,
- 'pre_approved': False,
})
self.assertEqual(cm.exception.code, 409)
self.assertEqual(cm.exception.reason, 'Member already subscribed')
@@ -123,7 +122,6 @@ class TestMembership(unittest.TestCase):
'subscriber': '00000000000000000000000000000001',
'pre_verified': True,
'pre_confirmed': True,
- 'pre_approved': True,
})
self.assertEqual(cm.exception.code, 400)
self.assertEqual(cm.exception.reason, 'User has no preferred address')
@@ -135,7 +133,6 @@ class TestMembership(unittest.TestCase):
'subscriber': '00000000000000000000000000000801',
'pre_verified': True,
'pre_confirmed': True,
- 'pre_approved': True,
})
self.assertEqual(cm.exception.code, 400)
self.assertEqual(cm.exception.reason, 'No such user')
@@ -153,7 +150,6 @@ class TestMembership(unittest.TestCase):
'subscriber': 'ANNE@example.com',
'pre_verified': True,
'pre_confirmed': True,
- 'pre_approved': True,
})
self.assertEqual(cm.exception.code, 409)
self.assertEqual(cm.exception.reason, 'Member already subscribed')
@@ -171,7 +167,6 @@ class TestMembership(unittest.TestCase):
'subscriber': 'anne@example.com',
'pre_verified': True,
'pre_confirmed': True,
- 'pre_approved': True,
})
self.assertEqual(cm.exception.code, 409)
self.assertEqual(cm.exception.reason, 'Member already subscribed')
@@ -195,7 +190,6 @@ class TestMembership(unittest.TestCase):
'display_name': 'Hugh Person',
'pre_verified': True,
'pre_confirmed': True,
- 'pre_approved': True,
})
self.assertEqual(json, None)
self.assertEqual(response.status_code, 201)
@@ -231,10 +225,10 @@ class TestMembership(unittest.TestCase):
# to subscribe again.
registrar = ISubscriptionManager(self._mlist)
with transaction():
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
anne = self._usermanager.create_address('anne@example.com')
token, token_owner, member = registrar.register(
- anne, pre_verified=True, pre_confirmed=True)
+ anne, pre_verified=True)
self.assertEqual(token_owner, TokenOwner.moderator)
self.assertIsNone(member)
with self.assertRaises(HTTPError) as cm:
@@ -242,7 +236,6 @@ class TestMembership(unittest.TestCase):
'list_id': 'test.example.com',
'subscriber': 'anne@example.com',
'pre_verified': True,
- 'pre_confirmed': True,
})
self.assertEqual(cm.exception.code, 409)
self.assertEqual(cm.exception.reason,
@@ -255,7 +248,7 @@ class TestMembership(unittest.TestCase):
registrar = ISubscriptionManager(self._mlist)
with transaction():
self._mlist.subscription_policy = (
- SubscriptionPolicy.confirm_then_moderate)
+ ConfirmModerationSubscriptionPolicy)
anne = self._usermanager.create_address('anne@example.com')
token, token_owner, member = registrar.register(
anne, pre_verified=True)
@@ -645,7 +638,6 @@ class TestAPI31Members(unittest.TestCase):
'subscriber': '00000000000000000000000000000001',
'pre_verified': True,
'pre_confirmed': True,
- 'pre_approved': True,
})
self.assertEqual(response.status_code, 201)
self.assertEqual(
@@ -681,7 +673,6 @@ class TestAPI31Members(unittest.TestCase):
'subscriber': '1',
'pre_verified': True,
'pre_confirmed': True,
- 'pre_approved': True,
})
# This is a bad request because the `subscriber` value isn't something
# that's known to the system, in API 3.1. It's not technically a 404
diff --git a/src/mailman/rest/tests/test_moderation.py b/src/mailman/rest/tests/test_moderation.py
index 0a9bb2608..5b55eb575 100644
--- a/src/mailman/rest/tests/test_moderation.py
+++ b/src/mailman/rest/tests/test_moderation.py
@@ -24,7 +24,6 @@ from mailman.app.lifecycle import create_list
from mailman.app.moderator import hold_message
from mailman.database.transaction import transaction
from mailman.interfaces.bans import IBanManager
-from mailman.interfaces.mailinglist import SubscriptionPolicy
from mailman.interfaces.requests import IListRequests, RequestType
from mailman.interfaces.subscriptions import ISubscriptionManager
from mailman.interfaces.usermanager import IUserManager
@@ -32,6 +31,7 @@ from mailman.testing.helpers import (
call_api, get_queue_messages, set_preferred,
specialized_message_from_string as mfs)
from mailman.testing.layers import RESTLayer
+from mailman.workflows.subscription import ModerationSubscriptionPolicy
from pkg_resources import resource_filename
from urllib.error import HTTPError
from zope.component import getUtility
@@ -296,10 +296,9 @@ class TestSubscriptionModeration(unittest.TestCase):
# Anne tries to subscribe to a list that only requests moderator
# approval.
with transaction():
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
token, token_owner, member = self._registrar.register(
- self._anne,
- pre_verified=True, pre_confirmed=True)
+ self._anne, pre_verified=True)
# There's now one request in the queue, and it's waiting on moderator
# approval.
json, response = call_api(
diff --git a/src/mailman/rest/tests/test_users.py b/src/mailman/rest/tests/test_users.py
index 97f4b76d2..4c97e5c1d 100644
--- a/src/mailman/rest/tests/test_users.py
+++ b/src/mailman/rest/tests/test_users.py
@@ -437,7 +437,7 @@ class TestLP1074374(unittest.TestCase):
list_id='test.example.com',
subscriber='anne@example.com',
role='member',
- pre_verified=True, pre_confirmed=True, pre_approved=True))
+ pre_verified=True, pre_confirmed=True))
# This is not the Anne you're looking for. (IOW, the new Anne is a
# different user).
json, response = call_api(
diff --git a/src/mailman/rest/tests/test_validator.py b/src/mailman/rest/tests/test_validator.py
index 0d197032e..95855d170 100644
--- a/src/mailman/rest/tests/test_validator.py
+++ b/src/mailman/rest/tests/test_validator.py
@@ -22,9 +22,14 @@ import unittest
from mailman.core.api import API30, API31
from mailman.interfaces.action import Action
from mailman.interfaces.usermanager import IUserManager
+from mailman.interfaces.workflows import (ISubscriptionWorkflow,
+ IUnsubscriptionWorkflow)
from mailman.rest.validator import (
- enum_validator, list_of_strings_validator, subscriber_validator)
+ enum_validator, list_of_strings_validator, policy_validator,
+ subscriber_validator)
from mailman.testing.layers import RESTLayer
+from mailman.workflows.subscription import ConfirmSubscriptionPolicy
+from mailman.workflows.unsubscription import ConfirmUnsubscriptionPolicy
from zope.component import getUtility
@@ -91,3 +96,40 @@ class TestValidators(unittest.TestCase):
def test_enum_validator_blank(self):
self.assertEqual(enum_validator(Action, allow_blank=True)(''), None)
+
+ def test_policy_validator_wrong_policy_class(self):
+ self.assertRaises(ValueError, policy_validator, None)
+
+ def test_policy_validator_sub_name(self):
+ self.assertEqual(policy_validator(ISubscriptionWorkflow)(
+ ConfirmSubscriptionPolicy.name), ConfirmSubscriptionPolicy)
+
+ def test_policy_validator_sub_class(self):
+ self.assertEqual(policy_validator(ISubscriptionWorkflow)(
+ ConfirmSubscriptionPolicy), ConfirmSubscriptionPolicy)
+
+ def test_policy_validator_sub_backward_compat(self):
+ self.assertEqual(policy_validator(ISubscriptionWorkflow)('confirm'),
+ ConfirmSubscriptionPolicy)
+
+ def test_policy_validator_sub_wrong_policy(self):
+ validator = policy_validator(ISubscriptionWorkflow)
+ with self.assertRaises(ValueError):
+ validator('not a subscription policy')
+
+ def test_policy_validator_unsub_name(self):
+ self.assertEqual(policy_validator(IUnsubscriptionWorkflow)(
+ ConfirmUnsubscriptionPolicy.name), ConfirmUnsubscriptionPolicy)
+
+ def test_policy_validator_unsub_class(self):
+ self.assertEqual(policy_validator(IUnsubscriptionWorkflow)(
+ ConfirmUnsubscriptionPolicy), ConfirmUnsubscriptionPolicy)
+
+ def test_policy_validator_unsub_backward_compat(self):
+ self.assertEqual(policy_validator(IUnsubscriptionWorkflow)('confirm'),
+ ConfirmUnsubscriptionPolicy)
+
+ def test_policy_validator_unsub_wrong_policy(self):
+ validator = policy_validator(IUnsubscriptionWorkflow)
+ with self.assertRaises(ValueError):
+ validator('not an unsubscription policy')
diff --git a/src/mailman/rest/validator.py b/src/mailman/rest/validator.py
index b325fdc84..d5f684df9 100644
--- a/src/mailman/rest/validator.py
+++ b/src/mailman/rest/validator.py
@@ -16,15 +16,35 @@
# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
"""REST web form validation."""
-
+from mailman.config import config
from mailman.interfaces.address import IEmailValidator
from mailman.interfaces.errors import MailmanError
from mailman.interfaces.languages import ILanguageManager
+from mailman.interfaces.workflows import (ISubscriptionWorkflow,
+ IUnsubscriptionWorkflow)
+from mailman.workflows.subscription import (
+ ConfirmModerationSubscriptionPolicy, ConfirmSubscriptionPolicy,
+ ModerationSubscriptionPolicy, OpenSubscriptionPolicy)
+from mailman.workflows.unsubscription import (
+ ConfirmModerationUnsubscriptionPolicy, ConfirmUnsubscriptionPolicy,
+ ModerationUnsubscriptionPolicy, OpenUnsubscriptionPolicy)
from public import public
from zope.component import getUtility
COMMASPACE = ', '
+OLD_SUB_MAP = {
+ 'open': OpenSubscriptionPolicy,
+ 'confirm': ConfirmSubscriptionPolicy,
+ 'moderate': ModerationSubscriptionPolicy,
+ 'confirm_then_moderate': ConfirmModerationSubscriptionPolicy
+ }
+OLD_UNSUB_MAP = {
+ 'open': OpenUnsubscriptionPolicy,
+ 'confirm': ConfirmUnsubscriptionPolicy,
+ 'moderate': ModerationUnsubscriptionPolicy,
+ 'confirm_then_moderate': ConfirmModerationUnsubscriptionPolicy
+ }
@public
@@ -100,6 +120,33 @@ def list_of_strings_validator(values):
@public
+class policy_validator:
+ """"""
+
+ def __init__(self, policy_interface):
+ self._policy_interface = policy_interface
+ if policy_interface is ISubscriptionWorkflow:
+ self._old_map = OLD_SUB_MAP
+ elif policy_interface is IUnsubscriptionWorkflow:
+ self._old_map = OLD_UNSUB_MAP
+ else:
+ raise ValueError('Expected a workflow interface.')
+
+ def __call__(self, policy):
+ if self._policy_interface.implementedBy(policy):
+ return policy
+ if (policy in config.workflows and
+ self._policy_interface.implementedBy(
+ config.workflows[policy])):
+ return config.workflows[policy]
+ # For backwards compatibility.
+ policy = self._old_map.get(policy, None)
+ if policy is not None:
+ return policy
+ raise ValueError('Unknown policy: {}'.format(policy))
+
+
+@public
class Validator:
"""A validator of parameter input."""