Index: main/waeup.sirp/trunk/src/waeup/sirp/authentication.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/authentication.py	(revision 7232)
+++ main/waeup.sirp/trunk/src/waeup/sirp/authentication.py	(revision 7233)
@@ -24,11 +24,15 @@
 from zope.securitypolicy.interfaces import (
     IPrincipalRoleMap, IPrincipalRoleManager)
+from zope.pluggableauth.factories import Principal
 from zope.pluggableauth.plugins.session import SessionCredentialsPlugin
 from zope.pluggableauth.interfaces import (
-        ICredentialsPlugin, IAuthenticatorPlugin, IPrincipalInfo)
+        ICredentialsPlugin, IAuthenticatorPlugin,
+        IAuthenticatedPrincipalFactory, AuthenticatedPrincipalCreated)
+from zope.publisher.interfaces import IRequest
 from zope.password.interfaces import IPasswordManager
 from zope.securitypolicy.principalrole import principalRoleManager
 from waeup.sirp.interfaces import (ILocalRoleSetEvent,
-    IUserAccount, IAuthPluginUtility, IPasswordValidator)
+    IUserAccount, IAuthPluginUtility, IPasswordValidator,
+    ISIRPPrincipal, ISIRPPrincipalInfo)
 
 def setup_authentication(pau):
@@ -68,14 +72,70 @@
     passwordfield = 'form.password'
 
-class PrincipalInfo(object):
-    grok.implements(IPrincipalInfo)
-
-    def __init__(self, id, title, description):
+class SIRPPrincipalInfo(object):
+    """An implementation of ISIRPPrincipalInfo.
+
+    A SIRP principal info is created with id, login, title, description,
+    phone and email.
+    """
+    grok.implements(ISIRPPrincipalInfo)
+
+    def __init__(self, id, title, description, email, phone):
         self.id = id
         self.title = title
         self.description = description
+        self.email = email
+        self.phone = phone
         self.credentialsPlugin = None
         self.authenticatorPlugin = None
 
+class SIRPPrincipal(Principal):
+    """A portal principal.
+
+    SIRP principals provide an extra `email` and `phone`
+    attribute extending ordinary principals.
+    """
+
+    grok.implements(ISIRPPrincipal)
+
+    def __init__(self, id, title=u'', description=u'', email=u'',
+                 phone=None, prefix=None):
+        self.id = id
+        self.title = title
+        self.description = description
+        self.groups = []
+        self.email = email
+        self.phone = phone
+
+    def __repr__(self):
+        return 'SIRPPrincipal(%r)' % self.id
+
+class AuthenticatedSIRPPrincipalFactory(grok.MultiAdapter):
+    """Creates 'authenticated' SIRP principals.
+
+    Adapts (principal info, request) to a SIRPPrincipal instance.
+
+    This adapter is used by the standard PAU to transform
+    PrincipalInfos into Principal instances.
+    """
+    grok.adapts(ISIRPPrincipalInfo, IRequest)
+    grok.implements(IAuthenticatedPrincipalFactory)
+
+    def __init__(self, info, request):
+        self.info = info
+        self.request = request
+
+    def __call__(self, authentication):
+        principal = SIRPPrincipal(
+            self.info.id,
+            self.info.title,
+            self.info.description,
+            self.info.email,
+            self.info.phone,
+            )
+        notify(
+            AuthenticatedPrincipalCreated(
+                authentication, principal, self.info, self.request))
+        return principal
+
 class Account(grok.Model):
     grok.implements(IUserAccount)
@@ -84,5 +144,5 @@
 
     def __init__(self, name, password, title=None, description=None,
-                 email=None, roles = []):
+                 email=None, phone=None, roles = []):
         self.name = name
         if title is None:
@@ -93,4 +153,5 @@
         self.description = description
         self.email = email
+        self.phone = phone
         self.setPassword(password)
         #self.setSiteRolesForPrincipal(roles)
@@ -155,7 +216,9 @@
         if not account.checkPassword(credentials['password']):
             return None
-        return PrincipalInfo(id=account.name,
+        return SIRPPrincipalInfo(id=account.name,
                              title=account.title,
-                             description=account.description)
+                             description=account.description,
+                             email=account.email,
+                             phone=account.phone)
 
     def principalInfo(self, id):
@@ -163,7 +226,9 @@
         if account is None:
             return None
-        return PrincipalInfo(id=account.name,
+        return SIRPPrincipalInfo(id=account.name,
                              title=account.title,
-                             description=account.description)
+                             description=account.description,
+                             email=account.email,
+                             phone=account.phone)
 
     def getAccount(self, login):
Index: main/waeup.sirp/trunk/src/waeup/sirp/browser/browser.txt
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/browser/browser.txt	(revision 7232)
+++ main/waeup.sirp/trunk/src/waeup/sirp/browser/browser.txt	(revision 7233)
@@ -128,4 +128,5 @@
   >>> browser.getControl(name="control_password").value = 'secret'
   >>> browser.getControl(name="form.email").value = 'xx@yy.zz'
+  >>> browser.getControl(name="form.phone").value = '1234'
   >>> browser.getControl("Add user").click()
   >>> print browser.contents
@@ -162,4 +163,5 @@
   >>> browser.getControl(name="control_password").value = 'secret'
   >>> browser.getControl(name="form.email").value = 'xx@yy.zz'
+  >>> browser.getControl(name="form.phone").value = '1234'
   >>> browser.getControl("Add user").click()
   >>> 'The userid chosen already exists' in browser.contents
Index: main/waeup.sirp/trunk/src/waeup/sirp/browser/pages.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/browser/pages.py	(revision 7232)
+++ main/waeup.sirp/trunk/src/waeup/sirp/browser/pages.py	(revision 7233)
@@ -382,4 +382,5 @@
         title = data['title']
         email = data['email']
+        phone = data['phone']
         description = data['description']
         #password = data['password']
@@ -396,5 +397,6 @@
         try:
             self.context.addUser(name, password, title=title, email=email,
-                                 description=description, roles=roles)
+                                 phone=phone, description=description,
+                                 roles=roles)
         except KeyError:
             self.status = self.flash('The userid chosen already exists '
Index: main/waeup.sirp/trunk/src/waeup/sirp/interfaces.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/interfaces.py	(revision 7232)
+++ main/waeup.sirp/trunk/src/waeup/sirp/interfaces.py	(revision 7233)
@@ -23,4 +23,6 @@
 from zc.sourcefactory.basic import BasicSourceFactory
 from zope import schema
+from zope.pluggableauth.interfaces import IPrincipalInfo
+from zope.security.interfaces import IGroupClosureAwarePrincipal as IPrincipal
 from zope.component import getUtility
 from zope.component.interfaces import IObjectEvent
@@ -232,4 +234,27 @@
         required = True,)
 
+class ISIRPPrincipalInfo(IPrincipalInfo):
+    """Infos about principals that are users of WAeUP SIRP.
+    """
+    email = Attribute("The email address of a user")
+    phone = Attribute("The phone number of a user")
+
+
+class ISIRPPrincipal(IPrincipal):
+    """A principle for WAeUP SIRP.
+
+    This interface extends zope.security.interfaces.IPrincipal and
+    requires also an `id` and other attributes defined there.
+    """
+
+    email = schema.TextLine(
+        title = u'Email',
+        description = u'',
+        required=False,)
+
+    phone = schema.Int(
+        title = u'Phone',
+        description = u'',
+        required=False,)
 
 class IUserAccount(IWAeUPObject):
@@ -255,4 +280,10 @@
         required = True,
         constraint=validate_email,
+        )
+
+    phone = schema.Int(
+        title = u'Phone',
+        default = None,
+        required = True,
         )
 
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/authentication.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/authentication.py	(revision 7232)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/authentication.py	(revision 7233)
@@ -28,5 +28,5 @@
 from zope.publisher.interfaces.http import IHTTPRequest
 from zope.session.interfaces import ISession
-from waeup.sirp.authentication import PrincipalInfo, get_principal_role_manager
+from waeup.sirp.authentication import SIRPPrincipalInfo, get_principal_role_manager
 from waeup.sirp.interfaces import (
     IAuthPluginUtility, IUserAccount, IPasswordValidator)
@@ -54,4 +54,8 @@
     def email(self):
         return self.context.email
+
+    @property
+    def phone(self):
+        return self.context.phone
 
     @property
@@ -127,19 +131,17 @@
         if not account.checkPassword(credentials['password']):
             return None
-        return PrincipalInfo(id=account.name,
+        return SIRPPrincipalInfo(id=account.name,
                              title=account.title,
-                             description=account.description)
+                             description=account.description,
+                             email=account.email,
+                             phone=account.phone)
 
     def principalInfo(self, id):
         """Get a principal identified by `id`.
 
-        This one is required by IAuthenticatorPlugin.
-        """
-        account = self.getAccount(id)
-        if account is None:
-            return None
-        return PrincipalInfo(id=account.name,
-                             title=account.title,
-                             description=account.description)
+        This one is required by IAuthenticatorPlugin but not needed here
+        (see respective docstring in applicants package).
+        """
+        return None
 
     def getAccount(self, login):
Index: main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_authentication.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_authentication.py	(revision 7232)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_authentication.py	(revision 7233)
@@ -64,4 +64,5 @@
     password = None
     email = None
+    phone = None
 
 
Index: main/waeup.sirp/trunk/src/waeup/sirp/tests/test_authentication.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/tests/test_authentication.py	(revision 7232)
+++ main/waeup.sirp/trunk/src/waeup/sirp/tests/test_authentication.py	(revision 7233)
@@ -24,5 +24,5 @@
 from waeup.sirp.testing import FunctionalTestCase, FunctionalLayer
 from waeup.sirp.authentication import (
-    UserAuthenticatorPlugin, Account, PrincipalInfo, get_principal_role_manager)
+    UserAuthenticatorPlugin, Account, SIRPPrincipalInfo, get_principal_role_manager)
 
 class FakeSite(grok.Site, grok.Container):
@@ -63,5 +63,5 @@
         result2 = plugin.authenticateCredentials(
             dict(login='bob', password='nonsense'))
-        self.assertTrue(isinstance(result1, PrincipalInfo))
+        self.assertTrue(isinstance(result1, SIRPPrincipalInfo))
         self.assertTrue(result2 is None)
         return
@@ -72,5 +72,5 @@
         result1 = plugin.principalInfo('bob')
         result2 = plugin.principalInfo('manfred')
-        self.assertTrue(isinstance(result1, PrincipalInfo))
+        self.assertTrue(isinstance(result1, SIRPPrincipalInfo))
         self.assertTrue(result2 is None)
         return
Index: main/waeup.sirp/trunk/src/waeup/sirp/userscontainer.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/userscontainer.py	(revision 7232)
+++ main/waeup.sirp/trunk/src/waeup/sirp/userscontainer.py	(revision 7233)
@@ -32,5 +32,5 @@
 
     def addUser(self, name, password, title=None,
-                description=None, email=None, roles=[]):
+                description=None, email=None, phone=None, roles=[]):
         """Add a new Account instance, created from parameters.
         """
@@ -39,5 +39,6 @@
         #if description is None:
         #    description = title
-        self[name] = Account(name, password, title, description, email, roles)
+        self[name] = Account(name, password, title, description,
+                             email, phone, roles)
 
     def addAccount(self, account):
