diff options
Diffstat (limited to 'src/mailman/interfaces')
| -rw-r--r-- | src/mailman/interfaces/bans.py | 9 | ||||
| -rw-r--r-- | src/mailman/interfaces/listmanager.py | 10 | ||||
| -rw-r--r-- | src/mailman/interfaces/mailinglist.py | 18 | ||||
| -rw-r--r-- | src/mailman/interfaces/registrar.py | 112 | ||||
| -rw-r--r-- | src/mailman/interfaces/subscriptions.py | 170 | ||||
| -rw-r--r-- | src/mailman/interfaces/template.py | 3 | ||||
| -rw-r--r-- | src/mailman/interfaces/workflow.py | 14 |
7 files changed, 203 insertions, 133 deletions
diff --git a/src/mailman/interfaces/bans.py b/src/mailman/interfaces/bans.py index 2e320965a..055ad69a3 100644 --- a/src/mailman/interfaces/bans.py +++ b/src/mailman/interfaces/bans.py @@ -46,6 +46,9 @@ class IBanManager(Interface): to an `IBanManager`. To manage global bans, adapt ``None``. """ + bans = Attribute( + """A `QuerySequence` over all the banned emails.""") + def ban(email): """Ban an email address from subscribing to a mailing list. @@ -94,8 +97,6 @@ class IBanManager(Interface): """ def __iter__(): - """Iterate over all banned addresses. + """An iterator over all the banned email addresses. - :return: The list of all banned addresses. - :rtype: list of `IBan` - """ + :return: iterator over `IBan`""" diff --git a/src/mailman/interfaces/listmanager.py b/src/mailman/interfaces/listmanager.py index fddec06c8..2c7208496 100644 --- a/src/mailman/interfaces/listmanager.py +++ b/src/mailman/interfaces/listmanager.py @@ -142,3 +142,13 @@ class IListManager(Interface): name_components = Attribute( """An iterator over the 2-tuple of (list_name, mail_host) for all mailing lists managed by this list manager.""") + + def find(*, advertised=None, mail_host=None): + """Search for mailing lists matching some criteria. + + The keyword arguments are mailing list properties that will be + filtered upon. + + :return: The list of filtered mailing lists. + :rtype: list of `IMailingList` + """ diff --git a/src/mailman/interfaces/mailinglist.py b/src/mailman/interfaces/mailinglist.py index 19db025d1..877016f41 100644 --- a/src/mailman/interfaces/mailinglist.py +++ b/src/mailman/interfaces/mailinglist.py @@ -46,6 +46,7 @@ class ReplyToMunging(Enum): @public class SubscriptionPolicy(Enum): + """All subscription/unsubscription policies for a mailing list.""" # Neither confirmation, nor moderator approval is required. open = 0 # The user must confirm the subscription. @@ -256,6 +257,9 @@ class IMailingList(Interface): subscription_policy = Attribute( """The policy for subscribing new members to the list.""") + unsubscription_policy = Attribute( + """The policy for unsubscribing members from the list.""") + subscribers = Attribute( """An iterator over all IMembers subscribed to this list, with any role. @@ -270,6 +274,18 @@ class IMailingList(Interface): :rtype: Roster """ + def is_subscribed(subscriber, role=MemberRole.member): + """Is the given address or user subscribed to the mailing list? + + :param subscriber: The address or user to check. + :type subscriber: `IUser` or `IAddress` + :param role: The role being checked (e.g. a member, owner, or + moderator of a mailing list). + :type role: `MemberRole` + :return: A flag indicating whether the subscriber is already + subscribed to the mailing list or not. + """ + def subscribe(subscriber, role=MemberRole.member): """Subscribe the given address or user to the mailing list. @@ -278,7 +294,7 @@ class IMailingList(Interface): has one, otherwise no address for the user appears in the rosters. :type subscriber: `IUser` or `IAddress` :param role: The role being subscribed to (e.g. a member, owner, or - moderator of a mailing list. + moderator of a mailing list). :type role: `MemberRole` :return: The member object representing the subscription. :rtype: `IMember` diff --git a/src/mailman/interfaces/registrar.py b/src/mailman/interfaces/registrar.py deleted file mode 100644 index e2cec5fbb..000000000 --- a/src/mailman/interfaces/registrar.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright (C) 2007-2016 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 <http://www.gnu.org/licenses/>. - -"""Interface describing a user registration service. - -This is a higher level interface to user registration, address confirmation, -etc. than the IUserManager. The latter does no validation, syntax checking, -or confirmation, while this interface does. -""" - -from mailman import public -from zope.interface import Interface - - -@public -class ConfirmationNeededEvent: - """Triggered when an address 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 - this event is triggered. - """ - def __init__(self, mlist, token, email): - self.mlist = mlist - self.token = token - self.email = email - - -@public -class IRegistrar(Interface): - """Interface for subscribing addresses and users. - - This is a higher level interface to user registration, email address - confirmation, etc. than the IUserManager. The latter does no validation, - syntax checking, or confirmation, while this interface does. - - To use this, adapt an ``IMailingList`` to this interface. - """ - - def register(subscriber=None, *, - pre_verified=False, pre_confirmed=False, pre_approved=False): - """Subscribe an address or user according to subscription policies. - - The mailing list's subscription policy is used to subscribe - `subscriber` to the given mailing list. The subscriber can be - an ``IUser``, in which case the user must have a preferred - address, and that preferred address will be subscribed. The - subscriber can also be an ``IAddress``, in which case the - address will be subscribed. - - The workflow may pause (i.e. be serialized, saved, and - suspended) when some out-of-band confirmation step is required. - For example, if the user must confirm, or the moderator must - approve the subscription. Use the ``confirm(token)`` method to - resume the workflow. - - :param subscriber: The user or address to subscribe. - :type email: ``IUser`` or ``IAddress`` - :return: A 3-tuple is returned where the first element is the token - hash, the second element is a ``TokenOwner`, and the third element - is the subscribed member. If the subscriber got subscribed - immediately, the token will be None and the member will be - an ``IMember``. If the subscription got held, the token - will be a hash and the member will be None. - :rtype: (str-or-None, ``TokenOwner``, ``IMember``-or-None) - :raises MembershipIsBannedError: when the address being subscribed - appears in the global or list-centric bans. - """ - - def confirm(token): - """Continue any paused workflow. - - Confirmation may occur after the user confirms their - subscription request, or their email address must be verified, - or the moderator must approve the subscription request. - - :param token: A token matching a workflow. - :type token: string - :return: A 3-tuple is returned where the first element is the token - hash, the second element is a ``TokenOwner`, and the third element - is the subscribed member. If the subscriber got subscribed - immediately, the token will be None and the member will be - an ``IMember``. If the subscription is still being held, the token - will be a hash and the member will be None. - :rtype: (str-or-None, ``TokenOwner``, ``IMember``-or-None) - :raises LookupError: when no workflow is associated with the token. - """ - - def discard(token): - """Discard the workflow matched to the given `token`. - - :param token: A token matching a pending event with a type of - 'registration'. - :raises LookupError: when no workflow is associated with the token. - """ - - def evict(): - """Evict all saved workflows which have expired.""" diff --git a/src/mailman/interfaces/subscriptions.py b/src/mailman/interfaces/subscriptions.py index 382a23ac0..284261de5 100644 --- a/src/mailman/interfaces/subscriptions.py +++ b/src/mailman/interfaces/subscriptions.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License along with # GNU Mailman. If not, see <http://www.gnu.org/licenses/>. -"""Membership interface for REST.""" +"""Subscription management.""" from collections import namedtuple from enum import Enum @@ -78,8 +78,35 @@ class TokenOwner(Enum): @public +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 + this event is triggered. + """ + def __init__(self, mlist, token, email): + self.mlist = mlist + self.token = token + self.email = email + + +@public +class UnsubscriptionConfirmationNeededEvent: + """Triggered when an unsubscription request needs confirmation. + + The confirmation message is sent to the user when this event is + triggered. + """ + def __init__(self, mlist, token, email): + self.mlist = mlist + self.token = token + self.email = email + + +@public class ISubscriptionService(Interface): - """General Subscription services.""" + """General subscription services.""" def get_members(): """Return a sequence of all members of all mailing lists. @@ -121,8 +148,8 @@ class ISubscriptionService(Interface): :type list_id: string :param role: The member role. :type role: `MemberRole` - :return: The list of all memberships, which may be empty. - :rtype: list of `IMember` + :return: A sequence of all memberships, which may be empty. + :rtype: A `QuerySequence` of `IMember` """ def find_member(subscriber=None, list_id=None, role=None): @@ -178,3 +205,138 @@ class ISubscriptionService(Interface): :rtype: 2-tuple of (set-of-strings, set-of-strings) :raises NoSuchListError: if the named mailing list does not exist. """ + + +@public +class ISubscriptionManager(Interface): + """Handling subscription and unsubscription of addresses and users. + + This is a higher level interface to user registration and + unregistration, email address confirmation, etc. than the + `IUserManager`. The latter does no validation, syntax checking, or + confirmation, while this interface does. + + To use this, adapt an ``IMailingList`` to this interface. + """ + def register(subscriber=None, *, + pre_verified=False, pre_confirmed=False, pre_approved=False): + """Subscribe an address or user according to subscription policies. + + The mailing list's subscription policy is used to subscribe + `subscriber` to the given mailing list. The subscriber can be + an ``IUser``, in which case the user must have a preferred + address, and that preferred address will be subscribed. The + subscriber can also be an ``IAddress``, in which case the + address will be subscribed. + + The workflow may pause (i.e. be serialized, saved, and + suspended) when some out-of-band confirmation step is required. + For example, if the user must confirm, or the moderator must + approve the subscription. Use the ``confirm(token)`` method to + resume the workflow. + + :param subscriber: The user or address to subscribe. + :type email: ``IUser`` or ``IAddress`` + :param pre_verified: A flag indicating whether the subscriber's email + address should be considered pre-verified. Normally a never + before seen email address must be verified by mail-back + confirmation. Setting this flag to True automatically verifies + such addresses without the mail-back. (A confirmation message may + still be sent under other conditions.) + :type pre_verified: bool + :param pre_confirmed: A flag indicating whether, when required by the + subscription policy, a subscription request should be considered + pre-confirmed. Normally in such cases, a mail-back confirmation + message is sent to the subscriber, which must be positively + acknowledged by some manner. Setting this flag to True + automatically confirms the subscription request. (A confirmation + message may still be sent under other conditions.) + :type pre_confirmed: bool + :param pre_approved: A flag indicating whether, when required by the + subscription policy, a subscription request should be considered + pre-approved. Normally in such cases, the list administrator is + notified that an approval is necessary, which must be positively + acknowledged in some manner. Setting this flag to True + automatically approves the subscription request. + :type pre_approved: bool + :return: A 3-tuple is returned where the first element is the token + hash, the second element is a ``TokenOwner`, and the third element + is the subscribed member. If the subscriber got subscribed + immediately, the token will be None and the member will be + an ``IMember``. If the subscription got held, the token + will be a hash and the member will be None. + :rtype: (str-or-None, ``TokenOwner``, ``IMember``-or-None) + :raises MembershipIsBannedError: when the address being subscribed + appears in the global or list-centric bans. + """ + + def unregister(subscriber=None, *, + pre_confirmed=False, pre_approved=False): + """Unsubscribe an address or user according to subscription policies. + + The mailing list's unsubscription policy is used to unsubscribe + `subscriber` from the given mailing list. The subscriber can be + an ``IUser`` or an ``IAddress``, and must already be subscribed to the + mailing list. + + The workflow may pause (i.e. be serialized, saved, and + suspended) when some out-of-band confirmation step is required. + For example, if the user must confirm, or the moderator must + approve the unsubscription. Use the ``confirm(token)`` method to + resume the workflow. + + :param subscriber: The user or address to unsubscribe. + :type email: ``IUser`` or ``IAddress`` + :param pre_confirmed: A flag indicating whether, when required by the + unsubscription policy, an unsubscription request should be + considered pre-confirmed. Normally in such cases, a mail-back + confirmation message is sent to the subscriber, which must be + positively acknowledged by some manner. Setting this flag to True + automatically confirms the unsubscription request. (A confirmation + message may still be sent under other conditions.) + :type pre_confirmed: bool + :param pre_approved: A flag indicating whether, when required by the + unsubscription policy, an unsubscription request should be + considered pre-approved. Normally in such cases, the list + administrator is notified that an approval is necessary, which + must be positively acknowledged in some manner. Setting this flag + to True automatically approves the unsubscription request. + :type pre_approved: bool + :return: A 3-tuple is returned where the first element is the token + hash, the second element is a ``TokenOwner`, and the third element + is the unsubscribing member. If the subscriber got unsubscribed + immediately, the token will be None and the member will be + an ``IMember``. If the unsubscription got held, the token + will be a hash and the member will be None. + :rtype: (str-or-None, ``TokenOwner``, ``IMember``-or-None) + """ + + def confirm(token): + """Continue any paused workflow. + + Confirmation may occur after the user confirms their + subscription request, or their email address must be verified, + or the moderator must approve the subscription request. + + :param token: A token matching a workflow. + :type token: string + :return: A 3-tuple is returned where the first element is the token + hash, the second element is a ``TokenOwner`, and the third element + is the subscribed member. If the subscriber got subscribed + immediately, the token will be None and the member will be + an ``IMember``. If the subscription is still being held, the token + will be a hash and the member will be None. + :rtype: (str-or-None, ``TokenOwner``, ``IMember``-or-None) + :raises LookupError: when no workflow is associated with the token. + """ + + def discard(token): + """Discard the workflow matched to the given `token`. + + :param token: A token matching a pending event with a type of + 'registration'. + :raises LookupError: when no workflow is associated with the token. + """ + + def evict(): + """Evict all saved workflows which have expired.""" diff --git a/src/mailman/interfaces/template.py b/src/mailman/interfaces/template.py index 442f1eeda..24f956b78 100644 --- a/src/mailman/interfaces/template.py +++ b/src/mailman/interfaces/template.py @@ -157,6 +157,7 @@ class ITemplateManager(Interface): :type context: str """ + # Mapping of template names to their in-source file names. A None value means # that there is no file in the tree for that template. @@ -171,7 +172,7 @@ ALL_TEMPLATES = { 'list:admin:notice:unrecognized', 'list:admin:notice:unsubscribe', 'list:member:digest:masthead', - 'list:user:action:confirm', + 'list:user:action:subscribe', 'list:user:action:unsubscribe', 'list:user:notice:hold', 'list:user:notice:no-more-today', diff --git a/src/mailman/interfaces/workflow.py b/src/mailman/interfaces/workflow.py index bf2138959..9846f4683 100644 --- a/src/mailman/interfaces/workflow.py +++ b/src/mailman/interfaces/workflow.py @@ -25,8 +25,6 @@ from zope.interface import Attribute, Interface class IWorkflowState(Interface): """The state of a workflow.""" - name = Attribute('The name of the workflow.') - token = Attribute('A unique key identifying the workflow instance.') step = Attribute("This workflow's next step.") @@ -38,11 +36,9 @@ class IWorkflowState(Interface): class IWorkflowStateManager(Interface): """The workflow states manager.""" - def save(name, token, step, data=None): + def save(token, step, data=None): """Save the state of a workflow. - :param name: The name of the workflow. - :type name: str :param token: A unique token identifying this workflow instance. :type token: str :param step: The next step for this workflow. @@ -51,11 +47,9 @@ class IWorkflowStateManager(Interface): :type data: str """ - def restore(name, token): + def restore(token): """Get the saved state for a workflow or None if nothing was saved. - :param name: The name of the workflow. - :type name: str :param token: A unique token identifying this workflow instance. :type token: str :return: The saved state associated with this name/token pair, or None @@ -63,11 +57,9 @@ class IWorkflowStateManager(Interface): :rtype: ``IWorkflowState`` """ - def discard(name, token): + def discard(token): """Throw away the saved state for a workflow. - :param name: The name of the workflow. - :type name: str :param token: A unique token identifying this workflow instance. :type token: str """ |
