Index: main/waeup.sirp/trunk/src/waeup/sirp/students/authentication.py
===================================================================
--- main/waeup.sirp/trunk/src/waeup/sirp/students/authentication.py	(revision 6669)
+++ main/waeup.sirp/trunk/src/waeup/sirp/students/authentication.py	(revision 6669)
@@ -0,0 +1,173 @@
+##
+## authentication.py
+## Login : <uli@pu.smp.net>
+## Started on  Fri Sep  2 15:22:47 2011 Uli Fouquet
+## $Id$
+## 
+## Copyright (C) 2011 Uli Fouquet
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+## 
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+## 
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""
+Authenticate students.
+"""
+import grok
+from zope.component import getUtility
+from zope.password.interfaces import IPasswordManager
+from zope.pluggableauth.interfaces import IAuthenticatorPlugin
+from waeup.sirp.authentication import PrincipalInfo
+from waeup.sirp.interfaces import IAuthPluginUtility, IUserAccount
+from waeup.sirp.students.interfaces import IStudent
+
+class StudentAccount(grok.Adapter):
+    """An adapter to turn student objects into accounts on-the-fly.
+    """
+    grok.context(IStudent)
+    grok.implements(IUserAccount)
+
+    @property
+    def name(self):
+        return self.context.student_id
+
+    @property
+    def password(self):
+        return getattr(self.context, 'password', None)
+
+    @property
+    def title(self):
+        return self.context.name
+
+    @property
+    def description(self):
+        return self.title
+
+    @property
+    def roles(self):
+        return getattr(self.context, 'roles', None)
+
+    def setPassword(self, password):
+        """Set a password (LDAP-compatible) SSHA encoded.
+
+        We do not store passwords in plaintext.
+        """
+        passwordmanager = getUtility(IPasswordManager, 'SSHA')
+        self.context.password = passwordmanager.encodePassword(password)
+
+    def checkPassword(self, password):
+        """Check whether the given `password` matches the one stored.
+        """
+        if not isinstance(password, basestring):
+            return False
+        passwordmanager = getUtility(IPasswordManager, 'SSHA')
+        return passwordmanager.checkPassword(self.context.password, password)
+
+class StudentsAuthenticatorPlugin(grok.GlobalUtility):
+    grok.implements(IAuthenticatorPlugin)
+    grok.provides(IAuthenticatorPlugin)
+    grok.name('students')
+
+    def authenticateCredentials(self, credentials):
+        """Authenticate `credentials`.
+
+        `credentials` is a tuple (login, password).
+
+        We look up students to find out whether a respective student
+        exists, then check the password and return the resulting
+        `PrincipalInfo` or ``None`` if no such student can be found.
+        """
+        if not isinstance(credentials, dict):
+            return None
+        if not ('login' in credentials and 'password' in credentials):
+            return None
+        account = self.getAccount(credentials['login'])
+
+        if account is None:
+            return None
+        if not account.checkPassword(credentials['password']):
+            return None
+        return PrincipalInfo(id=account.name,
+                             title=account.title,
+                             description=account.description)
+
+    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)
+
+    def getAccount(self, login):
+        """Look up a student identified by `login`. Returns an account.
+
+        Currently, we simply look up the key under which the student
+        is stored in the portal. That means we hit if login name and
+        name under which the student is stored match.
+
+        Returns not a student but an account object adapted from any
+        student found.
+
+        If no such student exists, ``None`` is returned.
+        """
+        site = grok.getSite()
+        if site is None:
+            return None
+        studentscontainer = site.get('students', None)
+        if studentscontainer is None:
+            return None
+        student = studentscontainer.get(login, None)
+        if student is None:
+            return None
+        return IUserAccount(student)
+
+    #def addAccount(self, account):
+    #    usercontainer = self.getUserContainer()
+    #    if usercontainer is None:
+    #        return
+    #    # XXX: complain if name already exists...
+    #    usercontainer.addAccount(account)
+
+    #def addUser(self, name, password, title=None, description=None):
+    #    usercontainer = self.getUserContainer()
+    #    if usercontainer is None:
+    #        return
+    #    usercontainer.addUser(name, password, title, description)
+
+    #def getUserContainer(self):
+    #    site = grok.getSite()
+    #    return site['users']
+
+
+class StudentsAuthenticatorSetup(grok.GlobalUtility):
+    """Register or unregister student authentication for a PAU.
+
+    This piece is called when a new site is created.
+    """
+    grok.implements(IAuthPluginUtility)
+
+    def register(self, pau):
+        plugins = list(pau.authenticatorPlugins)
+        plugins.append('students')
+        pau.authenticatorPlugins = tuple(plugins)
+        return pau
+
+    def unregister(self, pau):
+        plugins = [x for x in pau.authenticatorPlugins
+                   if x != 'students']
+        pau.authenticatorPlugins = tuple(plugins)
+        return pau
