summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbhilash Raj2015-03-28 18:57:55 +0530
committerAbhilash Raj2015-03-28 18:57:55 +0530
commit583d0ff8d46555c2ac2a72d9affd7c0e8e236161 (patch)
tree10b567c642d29e292eddb8a641389de42d58e450
parent381f7ceb2d55179365809bf3b8f98313d9e86099 (diff)
downloadmailman-583d0ff8d46555c2ac2a72d9affd7c0e8e236161.tar.gz
mailman-583d0ff8d46555c2ac2a72d9affd7c0e8e236161.tar.zst
mailman-583d0ff8d46555c2ac2a72d9affd7c0e8e236161.zip
-rw-r--r--src/mailman/commands/docs/create.rst3
-rw-r--r--src/mailman/interfaces/domain.py13
-rw-r--r--src/mailman/model/docs/domains.rst49
-rw-r--r--src/mailman/model/domain.py15
-rw-r--r--src/mailman/model/tests/test_domain.py34
-rw-r--r--src/mailman/rest/docs/addresses.rst1
-rw-r--r--src/mailman/rest/docs/domains.rst33
-rw-r--r--src/mailman/rest/docs/users.rst17
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