diff options
| author | Abhilash Raj | 2015-03-28 18:57:55 +0530 |
|---|---|---|
| committer | Abhilash Raj | 2015-03-28 18:57:55 +0530 |
| commit | 583d0ff8d46555c2ac2a72d9affd7c0e8e236161 (patch) | |
| tree | 10b567c642d29e292eddb8a641389de42d58e450 | |
| parent | 381f7ceb2d55179365809bf3b8f98313d9e86099 (diff) | |
| download | mailman-583d0ff8d46555c2ac2a72d9affd7c0e8e236161.tar.gz mailman-583d0ff8d46555c2ac2a72d9affd7c0e8e236161.tar.zst mailman-583d0ff8d46555c2ac2a72d9affd7c0e8e236161.zip | |
| -rw-r--r-- | src/mailman/commands/docs/create.rst | 3 | ||||
| -rw-r--r-- | src/mailman/interfaces/domain.py | 13 | ||||
| -rw-r--r-- | src/mailman/model/docs/domains.rst | 49 | ||||
| -rw-r--r-- | src/mailman/model/domain.py | 15 | ||||
| -rw-r--r-- | src/mailman/model/tests/test_domain.py | 34 | ||||
| -rw-r--r-- | src/mailman/rest/docs/addresses.rst | 1 | ||||
| -rw-r--r-- | src/mailman/rest/docs/domains.rst | 33 | ||||
| -rw-r--r-- | src/mailman/rest/docs/users.rst | 17 |
8 files changed, 102 insertions, 63 deletions
diff --git a/src/mailman/commands/docs/create.rst b/src/mailman/commands/docs/create.rst index bec4ea8b6..1a5d2a3ab 100644 --- a/src/mailman/commands/docs/create.rst +++ b/src/mailman/commands/docs/create.rst @@ -44,8 +44,7 @@ Now both the domain and the mailing list exist in the database. >>> from mailman.interfaces.domain import IDomainManager >>> getUtility(IDomainManager).get('example.xx') - <Domain example.xx, base_url: http://example.xx, - contact_address: postmaster@example.xx> + <Domain example.xx, base_url: http://example.xx> You can also create mailing lists in existing domains without the auto-creation flag. diff --git a/src/mailman/interfaces/domain.py b/src/mailman/interfaces/domain.py index 3ebfb0d6e..fd889a720 100644 --- a/src/mailman/interfaces/domain.py +++ b/src/mailman/interfaces/domain.py @@ -88,9 +88,8 @@ class IDomain(Interface): description = Attribute( 'The human readable description of the domain name.') - contact_address = Attribute("""\ - The contact address for the human at this domain. - E.g. postmaster@example.com""") + owners = Attribute("""\ + The relationship with the user database representing domain owners""") mailing_lists = Attribute( """All mailing lists for this domain. @@ -112,7 +111,7 @@ class IDomain(Interface): class IDomainManager(Interface): """The manager of domains.""" - def add(mail_host, description=None, base_url=None, contact_address=None): + def add(mail_host, description=None, base_url=None, owner_id=None): """Add a new domain. :param mail_host: The email host name for the domain. @@ -123,10 +122,8 @@ class IDomainManager(Interface): interface of the domain. If not given, it defaults to http://`mail_host`/ :type base_url: string - :param contact_address: The email contact address for the human - managing the domain. If not given, defaults to - postmaster@`mail_host` - :type contact_address: string + :param owner_id: Owner of the domain, defaults to None + :type owner_id: integer :return: The new domain object :rtype: `IDomain` :raises `BadDomainSpecificationError`: when the `mail_host` is diff --git a/src/mailman/model/docs/domains.rst b/src/mailman/model/docs/domains.rst index abb594a62..491c0e612 100644 --- a/src/mailman/model/docs/domains.rst +++ b/src/mailman/model/docs/domains.rst @@ -9,6 +9,10 @@ Domains >>> manager = getUtility(IDomainManager) >>> manager.remove('example.com') <Domain example.com...> + >>> from mailman.interfaces.usermanager import IUserManager + >>> user_manager = getUtility(IUserManager) + >>> user = user_manager.create_user('test@example.org') + >>> config.db.commit() Domains are how Mailman interacts with email host names and web host names. :: @@ -28,17 +32,14 @@ Adding a domain requires some basic information, of which the email host name is the only required piece. The other parts are inferred from that. >>> manager.add('example.org') - <Domain example.org, base_url: http://example.org, - contact_address: postmaster@example.org> + <Domain example.org, base_url: http://example.org> >>> show_domains() - <Domain example.org, base_url: http://example.org, - contact_address: postmaster@example.org> + <Domain example.org, base_url: http://example.org> We can remove domains too. >>> manager.remove('example.org') - <Domain example.org, base_url: http://example.org, - contact_address: postmaster@example.org> + <Domain example.org, base_url: http://example.org> >>> show_domains() no domains @@ -46,30 +47,34 @@ Sometimes the email host name is different than the base url for hitting the web interface for the domain. >>> manager.add('example.com', base_url='https://mail.example.com') - <Domain example.com, base_url: https://mail.example.com, - contact_address: postmaster@example.com> + <Domain example.com, base_url: https://mail.example.com> >>> show_domains() - <Domain example.com, base_url: https://mail.example.com, - contact_address: postmaster@example.com> + <Domain example.com, base_url: https://mail.example.com> -Domains can have explicit descriptions and contact addresses. +Domains can have explicit descriptions. :: >>> manager.add( ... 'example.net', ... base_url='http://lists.example.net', - ... contact_address='postmaster@example.com', - ... description='The example domain') + ... description='The example domain', + ... owner_id=1) <Domain example.net, The example domain, - base_url: http://lists.example.net, - contact_address: postmaster@example.com> + base_url: http://lists.example.net> >>> show_domains() - <Domain example.com, base_url: https://mail.example.com, - contact_address: postmaster@example.com> + <Domain example.com, base_url: https://mail.example.com> <Domain example.net, The example domain, - base_url: http://lists.example.net, - contact_address: postmaster@example.com> + base_url: http://lists.example.net> + +Domains can have multiple number of owners, ideally one of the owners +should have a verified preferred address. However this is not checked +right now and contact_address from config is used as a fallback. +:: + + >>> net_domain = manager['example.net'] + >>> net_domain.add_owner(user_manager.get_user('test@example.org')) + Domains can list all associated mailing lists with the mailing_lists property. :: @@ -105,8 +110,7 @@ In the global domain manager, domains are indexed by their email host name. >>> print(manager['example.net']) <Domain example.net, The example domain, - base_url: http://lists.example.net, - contact_address: postmaster@example.com> + base_url: http://lists.example.net> As with dictionaries, you can also get the domain. If the domain does not exist, ``None`` or a default is returned. @@ -114,8 +118,7 @@ exist, ``None`` or a default is returned. >>> print(manager.get('example.net')) <Domain example.net, The example domain, - base_url: http://lists.example.net, - contact_address: postmaster@example.com> + base_url: http://lists.example.net> >>> print(manager.get('doesnotexist.com')) None diff --git a/src/mailman/model/domain.py b/src/mailman/model/domain.py index 7167d211e..a3a059cb9 100644 --- a/src/mailman/model/domain.py +++ b/src/mailman/model/domain.py @@ -29,7 +29,7 @@ from mailman.interfaces.domain import ( BadDomainSpecificationError, DomainCreatedEvent, DomainCreatingEvent, DomainDeletedEvent, DomainDeletingEvent, IDomain, IDomainManager) from mailman.model.mailinglist import MailingList -from mailman.model.user import User +from mailman.model.user import User, Owner from urllib.parse import urljoin, urlparse from sqlalchemy import Column, Integer, Unicode from sqlalchemy.orm import relationship, backref @@ -105,14 +105,20 @@ class Domain(Model): def __repr__(self): """repr(a_domain)""" if self.description is None: - return ('<Domain {0.mail_host}, base_url: {0.base_url}').format(self) + return ('<Domain {0.mail_host}, base_url: {0.base_url}>').format(self) else: return ('<Domain {0.mail_host}, {0.description}, ' - 'base_url: {0.base_url}, ').format(self) + 'base_url: {0.base_url}>').format(self) def add_owner(self, owner): - """ Add an owner to a domain""" + """ Add a domain owner""" self.owners.append(owner) + + @dbconnection + def remove_owner(self, store, owner): + """ Remove a domain owner""" + self.owners.remove(owner) + @implementer(IDomainManager) class DomainManager: @@ -137,6 +143,7 @@ class DomainManager: if owner is None: raise BadDomainSpecificationError( 'Owner of this domain does not exist') + notify(DomainCreatingEvent(mail_host)) domain = Domain(mail_host, description, base_url, owner) store.add(domain) diff --git a/src/mailman/model/tests/test_domain.py b/src/mailman/model/tests/test_domain.py index b4a6dd75c..ffa79e32e 100644 --- a/src/mailman/model/tests/test_domain.py +++ b/src/mailman/model/tests/test_domain.py @@ -26,9 +26,11 @@ __all__ = [ import unittest from mailman.app.lifecycle import create_list +from mailman.config import config from mailman.interfaces.domain import ( DomainCreatedEvent, DomainCreatingEvent, DomainDeletedEvent, - DomainDeletingEvent, IDomainManager) + DomainDeletingEvent, IDomainManager, BadDomainSpecificationError) +from mailman.interfaces.usermanager import IUserManager from mailman.interfaces.listmanager import IListManager from mailman.testing.helpers import event_subscribers from mailman.testing.layers import ConfigLayer @@ -78,6 +80,32 @@ class TestDomainManager(unittest.TestCase): # Trying to delete a missing domain gives you a KeyError. self.assertRaises(KeyError, self._manager.remove, 'doesnotexist.com') + def test_domain_create_with_owner(self): + user = getUtility(IUserManager).create_user('someuser@somedomain.org') + config.db.commit() + domain = self._manager.add('example.org', owner_id=user.id) + self.assertEqual(len(domain.owners), 1) + self.assertEqual(domain.owners[0].id, user.id) + + def test_domain_create_with_non_existent_owner(self): + with self.assertRaises(BadDomainSpecificationError): + self._manager.add('testdomain.org', owner_id=100) + + def test_add_domain_owner(self): + user = getUtility(IUserManager).create_user('someuser@somedomain.org') + config.db.commit() + domain = self._manager.add('example.org') + domain.add_owner(user) + self.assertEqual(len(domain.owners), 1) + self.assertEqual(domain.owners[0].id, user.id) + + def test_remove_domain_owner(self): + user = getUtility(IUserManager).create_user('someuser@somedomain.org') + config.db.commit() + domain = self._manager.add('example.org', owner_id=user.id) + domain.remove_owner(user) + self.assertEqual(len(domain.owners), 0) + class TestDomainLifecycleEvents(unittest.TestCase): @@ -110,3 +138,7 @@ class TestDomainLifecycleEvents(unittest.TestCase): self.assertEqual(listmanager.get('dog@example.org'), None) self.assertEqual(listmanager.get('ewe@example.com'), ewe) self.assertEqual(listmanager.get('fly@example.com'), fly) + + def test_owners_are_deleted_when_domain_is(self): + #TODO: Complete this + pass diff --git a/src/mailman/rest/docs/addresses.rst b/src/mailman/rest/docs/addresses.rst index fd3520be9..f70b64a39 100644 --- a/src/mailman/rest/docs/addresses.rst +++ b/src/mailman/rest/docs/addresses.rst @@ -190,6 +190,7 @@ representation: created_on: 2005-08-01T07:49:23 display_name: Cris X. Person http_etag: "..." + is_server_owner: False password: ... self_link: http://localhost:9001/3.0/users/1 user_id: 1 diff --git a/src/mailman/rest/docs/domains.rst b/src/mailman/rest/docs/domains.rst index a78dacd85..16204548c 100644 --- a/src/mailman/rest/docs/domains.rst +++ b/src/mailman/rest/docs/domains.rst @@ -29,14 +29,12 @@ Once a domain is added, it is accessible through the API. >>> domain_manager.add( ... 'example.com', 'An example domain', 'http://lists.example.com') <Domain example.com, An example domain, - base_url: http://lists.example.com, - contact_address: postmaster@example.com> + base_url: http://lists.example.com> >>> transaction.commit() >>> dump_json('http://localhost:9001/3.0/domains') entry 0: base_url: http://lists.example.com - contact_address: postmaster@example.com description: An example domain http_etag: "..." mail_host: example.com @@ -51,24 +49,19 @@ At the top level, all domains are returned as separate entries. >>> domain_manager.add( ... 'example.org', - ... base_url='http://mail.example.org', - ... contact_address='listmaster@example.org') - <Domain example.org, base_url: http://mail.example.org, - contact_address: listmaster@example.org> + ... base_url='http://mail.example.org') + <Domain example.org, base_url: http://mail.example.org> >>> domain_manager.add( ... 'lists.example.net', ... 'Porkmasters', - ... 'http://example.net', - ... 'porkmaster@example.net') + ... 'http://example.net') <Domain lists.example.net, Porkmasters, - base_url: http://example.net, - contact_address: porkmaster@example.net> + base_url: http://example.net> >>> transaction.commit() >>> dump_json('http://localhost:9001/3.0/domains') entry 0: base_url: http://lists.example.com - contact_address: postmaster@example.com description: An example domain http_etag: "..." mail_host: example.com @@ -76,7 +69,6 @@ At the top level, all domains are returned as separate entries. url_host: lists.example.com entry 1: base_url: http://mail.example.org - contact_address: listmaster@example.org description: None http_etag: "..." mail_host: example.org @@ -84,7 +76,6 @@ At the top level, all domains are returned as separate entries. url_host: mail.example.org entry 2: base_url: http://example.net - contact_address: porkmaster@example.net description: Porkmasters http_etag: "..." mail_host: lists.example.net @@ -103,7 +94,6 @@ The information for a single domain is available by following one of the >>> dump_json('http://localhost:9001/3.0/domains/lists.example.net') base_url: http://example.net - contact_address: porkmaster@example.net description: Porkmasters http_etag: "..." mail_host: lists.example.net @@ -165,7 +155,6 @@ Now the web service knows about our new domain. >>> dump_json('http://localhost:9001/3.0/domains/lists.example.com') base_url: http://lists.example.com - contact_address: postmaster@lists.example.com description: None http_etag: "..." mail_host: lists.example.com @@ -176,9 +165,7 @@ And the new domain is in our database. :: >>> domain_manager['lists.example.com'] - <Domain lists.example.com, - base_url: http://lists.example.com, - contact_address: postmaster@lists.example.com> + <Domain lists.example.com, base_url: http://lists.example.com> # Unlock the database. >>> transaction.abort() @@ -190,8 +177,7 @@ address. >>> dump_json('http://localhost:9001/3.0/domains', { ... 'mail_host': 'my.example.com', ... 'description': 'My new domain', - ... 'base_url': 'http://allmy.example.com', - ... 'contact_address': 'helpme@example.com' + ... 'base_url': 'http://allmy.example.com' ... }) content-length: 0 date: ... @@ -200,7 +186,6 @@ address. >>> dump_json('http://localhost:9001/3.0/domains/my.example.com') base_url: http://allmy.example.com - contact_address: helpme@example.com description: My new domain http_etag: "..." mail_host: my.example.com @@ -208,9 +193,7 @@ address. url_host: allmy.example.com >>> domain_manager['my.example.com'] - <Domain my.example.com, My new domain, - base_url: http://allmy.example.com, - contact_address: helpme@example.com> + <Domain my.example.com, My new domain, base_url: http://allmy.example.com> # Unlock the database. >>> transaction.abort() diff --git a/src/mailman/rest/docs/users.rst b/src/mailman/rest/docs/users.rst index 824492333..343598518 100644 --- a/src/mailman/rest/docs/users.rst +++ b/src/mailman/rest/docs/users.rst @@ -34,6 +34,7 @@ Anne's user record is returned as an entry into the collection of all users. created_on: 2005-08-01T07:49:23 display_name: Anne Person http_etag: "..." + is_server_owner: False self_link: http://localhost:9001/3.0/users/1 user_id: 1 http_etag: "..." @@ -50,11 +51,13 @@ returned in the REST API. created_on: 2005-08-01T07:49:23 display_name: Anne Person http_etag: "..." + is_server_owner: False self_link: http://localhost:9001/3.0/users/1 user_id: 1 entry 1: created_on: 2005-08-01T07:49:23 http_etag: "..." + is_server_owner: False self_link: http://localhost:9001/3.0/users/2 user_id: 2 http_etag: "..." @@ -76,6 +79,7 @@ page. created_on: 2005-08-01T07:49:23 display_name: Anne Person http_etag: "..." + is_server_owner: False self_link: http://localhost:9001/3.0/users/1 user_id: 1 http_etag: "..." @@ -86,6 +90,7 @@ page. entry 0: created_on: 2005-08-01T07:49:23 http_etag: "..." + is_server_owner: False self_link: http://localhost:9001/3.0/users/2 user_id: 2 http_etag: "..." @@ -120,6 +125,7 @@ one was assigned to her. >>> dump_json('http://localhost:9001/3.0/users/3') created_on: 2005-08-01T07:49:23 http_etag: "..." + is_server_owner: False password: {plaintext}... self_link: http://localhost:9001/3.0/users/3 user_id: 3 @@ -131,6 +137,7 @@ address. >>> dump_json('http://localhost:9001/3.0/users/cris@example.com') created_on: 2005-08-01T07:49:23 http_etag: "..." + is_server_owner: False password: {plaintext}... self_link: http://localhost:9001/3.0/users/3 user_id: 3 @@ -158,6 +165,7 @@ Dave's user record includes his display name. created_on: 2005-08-01T07:49:23 display_name: Dave Person http_etag: "..." + is_server_owner: False password: {plaintext}... self_link: http://localhost:9001/3.0/users/4 user_id: 4 @@ -190,6 +198,7 @@ because it has the hash algorithm prefix (i.e. the *{plaintext}* marker). created_on: 2005-08-01T07:49:23 display_name: Elly Person http_etag: "..." + is_server_owner: False password: {plaintext}supersekrit self_link: http://localhost:9001/3.0/users/5 user_id: 5 @@ -214,6 +223,7 @@ Dave's display name has been updated. created_on: 2005-08-01T07:49:23 display_name: David Person http_etag: "..." + is_server_owner: False password: {plaintext}... self_link: http://localhost:9001/3.0/users/4 user_id: 4 @@ -238,6 +248,7 @@ addition of the algorithm prefix. created_on: 2005-08-01T07:49:23 display_name: David Person http_etag: "..." + is_server_owner: False password: {plaintext}clockwork angels self_link: http://localhost:9001/3.0/users/4 user_id: 4 @@ -260,6 +271,7 @@ Dave's user record has been updated. created_on: 2005-08-01T07:49:23 display_name: David Personhood http_etag: "..." + is_server_owner: False password: {plaintext}the garden self_link: http://localhost:9001/3.0/users/4 user_id: 4 @@ -343,6 +355,7 @@ addresses can be used to look up Fred's user record. created_on: 2005-08-01T07:49:23 display_name: Fred Person http_etag: "..." + is_server_owner: False self_link: http://localhost:9001/3.0/users/6 user_id: 6 @@ -350,6 +363,7 @@ addresses can be used to look up Fred's user record. created_on: 2005-08-01T07:49:23 display_name: Fred Person http_etag: "..." + is_server_owner: False self_link: http://localhost:9001/3.0/users/6 user_id: 6 @@ -357,6 +371,7 @@ addresses can be used to look up Fred's user record. created_on: 2005-08-01T07:49:23 display_name: Fred Person http_etag: "..." + is_server_owner: False self_link: http://localhost:9001/3.0/users/6 user_id: 6 @@ -364,6 +379,7 @@ addresses can be used to look up Fred's user record. created_on: 2005-08-01T07:49:23 display_name: Fred Person http_etag: "..." + is_server_owner: False self_link: http://localhost:9001/3.0/users/6 user_id: 6 @@ -382,6 +398,7 @@ password is hashed and getting her user record returns the hashed password. created_on: 2005-08-01T07:49:23 display_name: Elly Person http_etag: "..." + is_server_owner: False password: {plaintext}supersekrit self_link: http://localhost:9001/3.0/users/5 user_id: 5 |
