summaryrefslogtreecommitdiff
path: root/src/mailman/model
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mailman/model/docs/addresses.txt2
-rw-r--r--src/mailman/model/docs/membership.txt4
-rw-r--r--src/mailman/model/docs/registration.txt8
-rw-r--r--src/mailman/model/docs/usermanager.txt17
-rw-r--r--src/mailman/model/docs/users.txt18
-rw-r--r--src/mailman/model/user.py9
-rw-r--r--src/mailman/model/usermanager.py26
7 files changed, 67 insertions, 17 deletions
diff --git a/src/mailman/model/docs/addresses.txt b/src/mailman/model/docs/addresses.txt
index 0ddacb321..fdcc993b5 100644
--- a/src/mailman/model/docs/addresses.txt
+++ b/src/mailman/model/docs/addresses.txt
@@ -89,7 +89,7 @@ And now you can find the associated user.
>>> print user_manager.get_user('bperson@example.com')
None
>>> user_manager.get_user('cperson@example.com')
- <User "Claire Person" at ...>
+ <User "Claire Person" (...) at ...>
Deleting addresses
diff --git a/src/mailman/model/docs/membership.txt b/src/mailman/model/docs/membership.txt
index 00e79d733..2fb66ca82 100644
--- a/src/mailman/model/docs/membership.txt
+++ b/src/mailman/model/docs/membership.txt
@@ -44,7 +44,7 @@ in the user database yet.
>>> user_manager = getUtility(IUserManager)
>>> user_1 = user_manager.create_user('aperson@example.com', 'Anne Person')
>>> print user_1
- <User "Anne Person" at ...>
+ <User "Anne Person" (...) at ...>
We can add Anne as an owner of the mailing list, by creating a member role for
her.
@@ -71,7 +71,7 @@ Bart becomes a moderator of the list.
>>> user_2 = user_manager.create_user('bperson@example.com', 'Bart Person')
>>> print user_2
- <User "Bart Person" at ...>
+ <User "Bart Person" (...) at ...>
>>> address_2 = list(user_2.addresses)[0]
>>> address_2.subscribe(mlist, MemberRole.moderator)
<Member: Bart Person <bperson@example.com>
diff --git a/src/mailman/model/docs/registration.txt b/src/mailman/model/docs/registration.txt
index e92c63f52..d0827d37b 100644
--- a/src/mailman/model/docs/registration.txt
+++ b/src/mailman/model/docs/registration.txt
@@ -186,7 +186,7 @@ an `IUser` linked to this address. The `IAddress` is verified.
<Address: Anne Person <aperson@example.com> [verified] at ...>
>>> found_user = user_manager.get_user('aperson@example.com')
>>> found_user
- <User "Anne Person" at ...>
+ <User "Anne Person" (...) at ...>
>>> found_user.controls(found_address.email)
True
>>> from datetime import datetime
@@ -231,7 +231,7 @@ confirmation step is completed.
>>> registrar.confirm(sent_token)
True
>>> user_manager.get_user('cperson@example.com')
- <User "Claire Person" at ...>
+ <User "Claire Person" (...) at ...>
>>> user_manager.get_address('cperson@example.com')
<Address: cperson@example.com [verified] at ...>
@@ -276,7 +276,7 @@ can be used.
>>> dperson = user_manager.create_user(
... 'dperson@example.com', 'Dave Person')
>>> dperson
- <User "Dave Person" at ...>
+ <User "Dave Person" (...) at ...>
>>> address = user_manager.get_address('dperson@example.com')
>>> address.verified_on = datetime.now()
@@ -297,7 +297,7 @@ can be used.
>>> user is dperson
True
>>> user
- <User "Dave Person" at ...>
+ <User "Dave Person" (...) at ...>
>>> dump_list(repr(address) for address in user.addresses)
<Address: Dave Person <dperson@example.com> [verified] at ...>
<Address: David Person <david.person@example.com> [verified] at ...>
diff --git a/src/mailman/model/docs/usermanager.txt b/src/mailman/model/docs/usermanager.txt
index 7b333248c..8304e659c 100644
--- a/src/mailman/model/docs/usermanager.txt
+++ b/src/mailman/model/docs/usermanager.txt
@@ -118,7 +118,7 @@ that the ``.get_user()`` method takes a string email address, not an
>>> address = list(user_4.addresses)[0]
>>> found_user = user_manager.get_user(address.email)
>>> found_user
- <User "Dan Person" at ...>
+ <User "Dan Person" (...) at ...>
>>> found_user is user_4
True
@@ -130,3 +130,18 @@ with it, you will get ``None`` back.
>>> user_4.unlink(address)
>>> print user_manager.get_user(address.email)
None
+
+Users can also be found by their unique user id.
+
+ >>> found_user = user_manager.get_user_by_id(user_4.user_id)
+ >>> user_4
+ <User "Dan Person" (...) at ...>
+ >>> found_user
+ <User "Dan Person" (...) at ...>
+ >>> user_4.user_id == found_user.user_id
+ True
+
+If a non-existent user id is given, None is returned.
+
+ >>> print user_manager.get_user_by_id('missing')
+ None
diff --git a/src/mailman/model/docs/users.txt b/src/mailman/model/docs/users.txt
index bbfef8391..1703db1ee 100644
--- a/src/mailman/model/docs/users.txt
+++ b/src/mailman/model/docs/users.txt
@@ -36,6 +36,24 @@ The password and real name can be changed at any time.
another password
+User id
+=======
+
+Although rarely visible to users, every user has a unique ID in Mailman, which
+never changes. This ID is generated randomly at the time the user is
+created.
+
+ >>> print len(user_1.user_id)
+ 40
+
+The user id cannot change.
+
+ >>> user_1.user_id = 'foo'
+ Traceback (most recent call last):
+ ...
+ AttributeError: can't set attribute
+
+
Users addresses
===============
diff --git a/src/mailman/model/user.py b/src/mailman/model/user.py
index f2a7c9d18..f037bdd48 100644
--- a/src/mailman/model/user.py
+++ b/src/mailman/model/user.py
@@ -46,13 +46,20 @@ class User(Model):
id = Int(primary=True)
real_name = Unicode()
password = Unicode()
+ _user_id = Unicode()
addresses = ReferenceSet(id, 'Address.user_id')
preferences_id = Int()
preferences = Reference(preferences_id, 'Preferences.id')
def __repr__(self):
- return '<User "{0}" at {1:#x}>'.format(self.real_name, id(self))
+ return '<User "{0.real_name}" ({0.user_id}) at {1:#x}>'.format(
+ self, id(self))
+
+ @property
+ def user_id(self):
+ """See `IUser`."""
+ return self._user_id
def link(self, address):
"""See `IUser`."""
diff --git a/src/mailman/model/usermanager.py b/src/mailman/model/usermanager.py
index 067ed7795..3294b3e7f 100644
--- a/src/mailman/model/usermanager.py
+++ b/src/mailman/model/usermanager.py
@@ -25,6 +25,10 @@ __all__ = [
]
+import os
+import time
+import hashlib
+
from zope.interface import implements
from mailman.config import config
@@ -33,6 +37,7 @@ from mailman.interfaces.usermanager import IUserManager
from mailman.model.address import Address
from mailman.model.preferences import Preferences
from mailman.model.user import User
+from mailman.utilities.passwords import SALT_LENGTH
@@ -46,6 +51,11 @@ class UserManager:
address = self.create_address(email, real_name)
user.link(address)
user.preferences = Preferences()
+ # Generate a unique random SHA1 hash for the user id.
+ salt = os.urandom(SALT_LENGTH)
+ h = hashlib.sha1(repr(time.time()))
+ h.update(salt)
+ user._user_id = unicode(h.hexdigest(), 'us-ascii')
config.db.store.add(user)
return user
@@ -56,10 +66,13 @@ class UserManager:
addresses = config.db.store.find(Address, email=email.lower())
if addresses.count() == 0:
return None
- elif addresses.count() == 1:
- return addresses[0].user
- else:
- raise AssertionError('Unexpected query count')
+ return addresses.one().user
+
+ def get_user_by_id(self, user_id):
+ users = config.db.store.find(User, _user_id=user_id)
+ if users.count() == 0:
+ return None
+ return users.one()
@property
def users(self):
@@ -92,10 +105,7 @@ class UserManager:
addresses = config.db.store.find(Address, email=email.lower())
if addresses.count() == 0:
return None
- elif addresses.count() == 1:
- return addresses[0]
- else:
- raise AssertionError('Unexpected query count')
+ return addresses.one()
@property
def addresses(self):