From 6a2de987622aad67ea3929d9a1b6a347a748b30d Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 6 Jul 2017 19:30:22 +0200 Subject: Move workflows from app.subscriptions to workflows.builtin. --- src/mailman/workflows/common.py | 123 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/mailman/workflows/common.py (limited to 'src/mailman/workflows/common.py') diff --git a/src/mailman/workflows/common.py b/src/mailman/workflows/common.py new file mode 100644 index 000000000..940152272 --- /dev/null +++ b/src/mailman/workflows/common.py @@ -0,0 +1,123 @@ +# Copyright (C) 2015-2017 by the Free Software Foundation, Inc. +# +# This file is part of GNU Mailman. +# +# GNU Mailman is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) +# any later version. +# +# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along with +# GNU Mailman. If not, see . + +"""Common support between subscription and unsubscription.""" + +import uuid + +from datetime import timedelta +from enum import Enum +from mailman.interfaces.address import IAddress +from mailman.interfaces.pending import IPendings +from mailman.interfaces.subscriptions import TokenOwner +from mailman.interfaces.user import IUser +from mailman.interfaces.usermanager import IUserManager +from mailman.utilities.datetime import now +from mailman.workflows.base import Workflow +from zope.component import getUtility + + +class WhichSubscriber(Enum): + address = 1 + user = 2 + + +class SubscriptionWorkflowCommon(Workflow): + """Common support between subscription and unsubscription.""" + + PENDABLE_CLASS = None + + def __init__(self, mlist, subscriber): + super().__init__() + self.mlist = mlist + self.address = None + self.user = None + self.which = None + self.member = None + self._set_token(TokenOwner.no_one) + # The subscriber must be either an IUser or IAddress. + if IAddress.providedBy(subscriber): + self.address = subscriber + self.user = self.address.user + self.which = WhichSubscriber.address + elif IUser.providedBy(subscriber): + self.address = subscriber.preferred_address + self.user = subscriber + self.which = WhichSubscriber.user + self.subscriber = subscriber + + @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) + if self.user is None: + self.user = self.address.user + + @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 = self.PENDABLE_CLASS( + 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)) -- cgit v1.2.3-70-g09d2