summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2016-10-18 21:03:59 -0400
committerBarry Warsaw2016-10-18 21:03:59 -0400
commit763025ce10c87cce654ce04a48a496e02732e1b4 (patch)
treed4f013cdb33e75dba5a7008770fc3f553d5ada7c
parentd45af03c4f2a560d51631fdfa7c55cd1a98e722c (diff)
downloadmailman-763025ce10c87cce654ce04a48a496e02732e1b4.tar.gz
mailman-763025ce10c87cce654ce04a48a496e02732e1b4.tar.zst
mailman-763025ce10c87cce654ce04a48a496e02732e1b4.zip
-rw-r--r--src/mailman/app/events.py2
-rw-r--r--src/mailman/app/subscriptions.py141
-rw-r--r--src/mailman/interfaces/subscriptions.py4
3 files changed, 40 insertions, 107 deletions
diff --git a/src/mailman/app/events.py b/src/mailman/app/events.py
index e29eee35c..f3323b6ce 100644
--- a/src/mailman/app/events.py
+++ b/src/mailman/app/events.py
@@ -38,7 +38,7 @@ def initialize():
passwords.handle_ConfigurationUpdatedEvent,
style_manager.handle_ConfigurationUpdatedEvent,
subscriptions.handle_ListDeletingEvent,
- subscriptions.handle_RegistrationConfirmationNeededEvent,
+ subscriptions.handle_SubscriptionConfirmationNeededEvent,
subscriptions.handle_UnsubscriptionConfirmationNeededEvent,
switchboard.handle_ConfigurationUpdatedEvent,
])
diff --git a/src/mailman/app/subscriptions.py b/src/mailman/app/subscriptions.py
index 15df6b3f3..63aebbecb 100644
--- a/src/mailman/app/subscriptions.py
+++ b/src/mailman/app/subscriptions.py
@@ -37,7 +37,7 @@ from mailman.interfaces.member import MembershipIsBannedError, NotAMemberError
from mailman.interfaces.pending import IPendable, IPendings
from mailman.interfaces.subscriptions import (
ISubscriptionManager, ISubscriptionService,
- RegistrationConfirmationNeededEvent, SubscriptionPendingError, TokenOwner,
+ SubscriptionConfirmationNeededEvent, SubscriptionPendingError, TokenOwner,
UnsubscriptionConfirmationNeededEvent)
from mailman.interfaces.template import ITemplateLoader
from mailman.interfaces.user import IUser
@@ -68,23 +68,12 @@ class PendableUnsubscription(dict):
PEND_TYPE = 'unsubscription'
-@public
-class SubscriptionWorkflow(Workflow):
- """Workflow of a subscription request."""
+class _SubscriptionWorkflowCommon(Workflow):
+ """Common support between subscription and unsubscription."""
- INITIAL_STATE = 'sanity_checks'
- SAVE_ATTRIBUTES = (
- 'pre_approved',
- 'pre_confirmed',
- 'pre_verified',
- 'address_key',
- 'subscriber_key',
- 'user_key',
- 'token_owner_key',
- )
+ PENDABLE_CLASS = None
- def __init__(self, mlist, subscriber=None, *,
- pre_verified=False, pre_confirmed=False, pre_approved=False):
+ def __init__(self, mlist, subscriber):
super().__init__()
self.mlist = mlist
self.address = None
@@ -102,9 +91,6 @@ class SubscriptionWorkflow(Workflow):
self.user = subscriber
self.which = WhichSubscriber.user
self.subscriber = subscriber
- self.pre_verified = pre_verified
- self.pre_confirmed = pre_confirmed
- self.pre_approved = pre_approved
@property
def user_key(self):
@@ -158,7 +144,7 @@ class SubscriptionWorkflow(Workflow):
if token_owner is TokenOwner.no_one:
self.token = None
return
- pendable = PendableSubscription(
+ pendable = self.PENDABLE_CLASS(
list_id=self.mlist.list_id,
email=self.address.email,
display_name=self.address.display_name,
@@ -167,6 +153,30 @@ class SubscriptionWorkflow(Workflow):
)
self.token = pendings.add(pendable, timedelta(days=3650))
+
+@public
+class SubscriptionWorkflow(_SubscriptionWorkflowCommon):
+ """Workflow of a subscription request."""
+
+ PENDABLE_CLASS = PendableSubscription
+ INITIAL_STATE = 'sanity_checks'
+ SAVE_ATTRIBUTES = (
+ 'pre_approved',
+ 'pre_confirmed',
+ 'pre_verified',
+ 'address_key',
+ 'subscriber_key',
+ 'user_key',
+ 'token_owner_key',
+ )
+
+ def __init__(self, mlist, subscriber=None, *,
+ pre_verified=False, pre_confirmed=False, pre_approved=False):
+ super().__init__(mlist, subscriber)
+ self.pre_verified = pre_verified
+ self.pre_confirmed = pre_confirmed
+ self.pre_approved = pre_approved
+
def _step_sanity_checks(self):
# Ensure that we have both an address and a user, even if the address
# is not verified. We can't set the preferred address until it is
@@ -306,7 +316,7 @@ class SubscriptionWorkflow(Workflow):
self.push('do_confirm_verify')
self.save()
# Triggering this event causes the confirmation message to be sent.
- notify(RegistrationConfirmationNeededEvent(
+ notify(SubscriptionConfirmationNeededEvent(
self.mlist, self.token, self.address.email))
# Now we wait for the confirmation.
raise StopIteration
@@ -339,9 +349,10 @@ class SubscriptionWorkflow(Workflow):
@public
-class UnSubscriptionWorkflow(Workflow):
+class UnSubscriptionWorkflow(_SubscriptionWorkflowCommon):
"""Workflow of a unsubscription request."""
+ PENDABLE_CLASS = PendableUnsubscription
INITIAL_STATE = 'subscription_checks'
SAVE_ATTRIBUTES = (
'pre_approved',
@@ -354,91 +365,13 @@ class UnSubscriptionWorkflow(Workflow):
def __init__(self, mlist, subscriber=None, *,
pre_approved=False, pre_confirmed=False):
- super().__init__()
- self.mlist = mlist
- self.address = None
- self.user = None
- self.which = None
- self.member = None
- self._set_token(TokenOwner.no_one)
- # `subscriber` should be an implementer of IAddress.
- if IAddress.providedBy(subscriber):
- self.address = subscriber
- self.user = self.address.user
- self.which = WhichSubscriber.address
- self.member = self.mlist.regular_members.get_member(
- self.address.email)
- elif IUser.providedBy(subscriber):
- self.address = subscriber.preferred_address
- self.user = subscriber
- self.which = WhichSubscriber.address
+ super().__init__(mlist, subscriber)
+ if IAddress.providedBy(subscriber) or IUser.providedBy(subscriber):
self.member = self.mlist.regular_members.get_member(
self.address.email)
- self.subscriber = subscriber
self.pre_confirmed = pre_confirmed
self.pre_approved = pre_approved
- @property
- def user_key(self):
- # For save.
- return self.user.user_id.hex
-
- @user_key.setter
- def user_key(self, hex_key):
- # For restore.
- uid = uuid.UUID(hex_key)
- self.user = getUtility(IUserManager).get_user_by_id(uid)
- assert self.user is not None
-
- @property
- def address_key(self):
- # For save.
- return self.address.email
-
- @address_key.setter
- def address_key(self, email):
- # For restore.
- self.address = getUtility(IUserManager).get_address(email)
- assert self.address is not None
-
- @property
- def subscriber_key(self):
- return self.which.value
-
- @subscriber_key.setter
- def subscriber_key(self, key):
- self.which = WhichSubscriber(key)
-
- @property
- def token_owner_key(self):
- return self.token_owner.value
-
- @token_owner_key.setter
- def token_owner_key(self, value):
- self.token_owner = TokenOwner(value)
-
- def _set_token(self, token_owner):
- assert isinstance(token_owner, TokenOwner)
- pendings = getUtility(IPendings)
- # Clear out the previous pending token if there is one.
- if self.token is not None:
- pendings.confirm(self.token)
- # Create a new token to prevent replay attacks. It seems like this
- # would produce the same token, but it won't because the pending adds a
- # bit of randomization.
- self.token_owner = token_owner
- if token_owner is TokenOwner.no_one:
- self.token = None
- return
- pendable = PendableUnsubscription(
- list_id=self.mlist.list_id,
- email=self.address.email,
- display_name=self.address.display_name,
- when=now().replace(microsecond=0).isoformat(),
- token_owner=token_owner.name,
- )
- self.token = pendings.add(pendable, timedelta(days=3650))
-
def _step_subscription_checks(self):
assert self.mlist.is_subscribed(self.subscriber)
self.push('confirmation_checks')
@@ -625,8 +558,8 @@ def _handle_confirmation_needed_events(event, template_name):
@public
-def handle_RegistrationConfirmationNeededEvent(event):
- if not isinstance(event, RegistrationConfirmationNeededEvent):
+def handle_SubscriptionConfirmationNeededEvent(event):
+ if not isinstance(event, SubscriptionConfirmationNeededEvent):
return
_handle_confirmation_needed_events(event, 'list:user:action:subscribe')
diff --git a/src/mailman/interfaces/subscriptions.py b/src/mailman/interfaces/subscriptions.py
index fb13d3d42..e707cf706 100644
--- a/src/mailman/interfaces/subscriptions.py
+++ b/src/mailman/interfaces/subscriptions.py
@@ -78,8 +78,8 @@ class TokenOwner(Enum):
@public
-class RegistrationConfirmationNeededEvent:
- """Triggered when an address needs confirmation.
+class SubscriptionConfirmationNeededEvent:
+ """Triggered when a subscription needs confirmation.
Addresses must be verified before they can receive messages or post
to mailing list. The confirmation message is sent to the user when