diff options
| -rw-r--r-- | mailman/database/roster.py | 58 | ||||
| -rw-r--r-- | mailman/database/user.py | 5 | ||||
| -rw-r--r-- | mailman/docs/users.txt | 48 | ||||
| -rw-r--r-- | mailman/interfaces/user.py | 3 |
4 files changed, 112 insertions, 2 deletions
diff --git a/mailman/database/roster.py b/mailman/database/roster.py index 2b237df97..41271dc36 100644 --- a/mailman/database/roster.py +++ b/mailman/database/roster.py @@ -22,6 +22,19 @@ the ones that fit a particular role. These are used as the member, owner, moderator, and administrator roster filters. """ +__metaclass__ = type +__all__ = [ + 'AdministratorRoster', + 'DigestMemberRoster', + 'MemberRoster', + 'Memberships', + 'ModeratorRoster', + 'OwnerRoster', + 'RegularMemberRoster', + 'Subscribers', + ] + + from storm.locals import * from zope.interface import implements @@ -33,7 +46,7 @@ from mailman.interfaces import DeliveryMode, IRoster, MemberRole -class AbstractRoster(object): +class AbstractRoster: """An abstract IRoster class. This class takes the simple approach of implemented the 'users' and @@ -208,3 +221,46 @@ class Subscribers(AbstractRoster): Member, mailing_list=self._mlist.fqdn_listname): yield member + + + +class Memberships: + """A roster of a single user's memberships.""" + + implements(IRoster) + + name = 'memberships' + + def __init__(self, user): + self._user = user + + @property + def members(self): + results = config.db.store.find( + Member, + Address.user_id == self._user.id, + Member.address_id == Address.id) + for member in results: + yield member + + @property + def users(self): + yield self._user + + @property + def addresses(self): + for address in self._user.addresses: + yield address + + def get_member(self, address): + results = config.db.store.find( + Member, + Member.address_id == Address.id, + Address.user_id == self._user.id) + if results.count() == 0: + return None + elif results.count() == 1: + return results[0] + else: + raise AssertionError('Too many matching member results: %s' % + results.count()) diff --git a/mailman/database/user.py b/mailman/database/user.py index 308eeb10d..9f8d8b812 100644 --- a/mailman/database/user.py +++ b/mailman/database/user.py @@ -23,6 +23,7 @@ from mailman.configuration import config from mailman.database.model import Model from mailman.database.address import Address from mailman.database.preferences import Preferences +from mailman.database.roster import Memberships from mailman.interfaces import ( AddressAlreadyLinkedError, AddressNotLinkedError, IUser) @@ -78,3 +79,7 @@ class User(Model): raise AddressAlreadyLinkedError(addrobj) addrobj.user = self return addrobj + + @property + def memberships(self): + return Memberships(self) diff --git a/mailman/docs/users.txt b/mailman/docs/users.txt index 032f0720b..e9ee4ca50 100644 --- a/mailman/docs/users.txt +++ b/mailman/docs/users.txt @@ -3,7 +3,7 @@ Users Users are entities that represent people. A user has a real name and a password. Optionally a user may have some preferences and a set of addresses -they control. +they control. A user also knows which mailing lists they are subscribed to. See usermanager.txt for examples of how to create, delete, and find users. @@ -146,3 +146,49 @@ Some of these preferences are booleans and they can be set to True or False. receive_list_copy : False receive_own_postings : False delivery_mode : DeliveryMode.regular + + +Subscriptions +------------- + +Users know which mailing lists they are subscribed to, regardless of +membership role. + + >>> user_1.link(address_1) + >>> sorted(address.address for address in user_1.addresses) + [u'zperson@example.com', u'zperson@example.net', u'zperson@example.org'] + >>> com = usermgr.get_address(u'zperson@example.com') + >>> org = usermgr.get_address(u'zperson@example.org') + >>> net = usermgr.get_address(u'zperson@example.net') + + >>> from mailman.app.lifecycle import create_list + >>> mlist_1 = create_list(u'xtest_1@example.com') + >>> mlist_2 = create_list(u'xtest_2@example.com') + >>> mlist_3 = create_list(u'xtest_3@example.com') + >>> from mailman.interfaces import MemberRole + + >>> com.subscribe(mlist_1, MemberRole.member) + <Member: Zoe Person <zperson@example.com> on xtest_1@example.com as + MemberRole.member> + >>> org.subscribe(mlist_2, MemberRole.member) + <Member: zperson@example.org on xtest_2@example.com as MemberRole.member> + >>> org.subscribe(mlist_2, MemberRole.owner) + <Member: zperson@example.org on xtest_2@example.com as MemberRole.owner> + >>> net.subscribe(mlist_3, MemberRole.moderator) + <Member: zperson@example.net on xtest_3@example.com as + MemberRole.moderator> + + >>> memberships = user_1.memberships + >>> from mailman.interfaces import IRoster + >>> from zope.interface.verify import verifyObject + >>> verifyObject(IRoster, memberships) + True + >>> members = sorted(memberships.members) + >>> len(members) + 4 + >>> for member in sorted(members, key=lambda m: m.address.address): + ... print member.address.address, member.mailing_list, member.role + zperson@example.com xtest_1@example.com MemberRole.member + zperson@example.net xtest_3@example.com MemberRole.moderator + zperson@example.org xtest_2@example.com MemberRole.member + zperson@example.org xtest_2@example.com MemberRole.owner diff --git a/mailman/interfaces/user.py b/mailman/interfaces/user.py index 25703bd17..0e84f1ab0 100644 --- a/mailman/interfaces/user.py +++ b/mailman/interfaces/user.py @@ -33,6 +33,9 @@ class IUser(Interface): addresses = Attribute( """An iterator over all the IAddresses controlled by this user.""") + memberships = Attribute( + """A roster of this user's membership.""") + def register(address, real_name=None): """Register the given email address and link it to this user. |
