[Zope3-checkins] CVS: Zope3/src/zope/app/services - auth.py:1.4

R. David Murray bitz@bitdance.com
Thu, 26 Dec 2002 18:22:17 -0500


Update of /cvs-repository/Zope3/src/zope/app/services
In directory cvs.zope.org:/tmp/cvs-serv21705/src/zope/app/services

Modified Files:
	auth.py 
Log Message:
Improve the efficiency of the basic persistent auth source.  Instead of
a BTreeContainer, use two BTrees, one mapping from ids to Users,
and one from login to Users.  This eliminates the need to look at
every User when looking up the user at login time.  Also standarize
the implementation of the helper method getPrincipalByLogin to raise
an error (NotFoundError) when the login isn't found, and provide
the corresponding query method.  Fix the tests to check for NotFoundError
as per the IAuthenticationService spec for getPrincipal.  Finally,
eliminate the ILocalAuthenticationService interface, since it doesn't
seem to add anything we need.  XXX the IContainer implementation is
not fully unit tested, since the BaseTestIContainer tests need to be
refactored first to facilitate it.


=== Zope3/src/zope/app/services/auth.py 1.3 => 1.4 ===
--- Zope3/src/zope/app/services/auth.py:1.3	Thu Dec 26 13:57:11 2002
+++ Zope3/src/zope/app/services/auth.py	Thu Dec 26 18:21:47 2002
@@ -16,12 +16,12 @@
 """
 from types import TupleType
 from persistence import Persistent
+from zodb.btrees.OOBTree import OOBTree
 
 from zope.exceptions import NotFoundError
 from zope.component import getAdapter, queryAdapter
 
 from zope.app.interfaces.container import IContainer
-from zope.app.container.btree import BTreeContainer
 
 from zope.app.interfaces.security import ILoginPassword
 from zope.app.interfaces.security import IAuthenticationService
@@ -38,28 +38,22 @@
 class DuplicateLogin(Exception): pass
 class DuplicateId(Exception): pass
 
-class ILocalAuthenticationService(IAuthenticationService, IContainer):
-    """TTW manageable authentication service"""
 
-    def getAllUsers():
-        """Get all users of the Service."""
+class AuthenticationService(Persistent):
 
-
-class AuthenticationService(BTreeContainer):
-
-    __implements__ = ILocalAuthenticationService
+    __implements__ = IAuthenticationService, IContainer
 
     def __init__(self):
-        super(AuthenticationService, self).__init__()
+        self._usersbylogin = OOBTree()
+        self._usersbyid = OOBTree()
+        self._next = 1
 
     def getPrincipalByLogin(self, login):
-        for p in self.values():
-            if p.getLogin() == login:
-                return p
-        return None
+        try: return self._usersbylogin[login]
+        except KeyError: raise NotFoundError(login)
 
-    def getAllUsers(self):
-        return self.values()
+    def queryPrincipalByLogin(self, login):
+        return self._usersbylogin.get(login)
 
     def authenticate(self, request):
         'See IAuthenticationService'
@@ -67,7 +61,7 @@
         if a is not None:
             login = a.getLogin()
             if login is not None:
-                p = self.getPrincipalByLogin(login)
+                p = self.queryPrincipalByLogin(login)
                 if p is not None:
                     password = a.getPassword()
                     if p.validate(password):
@@ -87,15 +81,58 @@
 
     def getPrincipal(self, id):
         'See IAuthenticationService'
-        r = self.get(id)
-        return r
+        try: return self._usersbyid[id]
+        except KeyError: raise NotFoundError(id)
 
     def getPrincipals(self, name):
         'See IAuthenticationService'
         name = name.lower()
-        return [p for p in self.values()
-                  if p.getTitle().lower().startswith(name) or
-                     p.getLogin().lower().startswith(name)]
+        return [p for p in self._usersbylogin.values()
+                  if p.getTitle().lower().find(name) >= 0 or
+                     p.getLogin().lower().find(name) >= 0 ]
+
+    def __getitem__(self, id):
+        'see IItemContainer'
+        return self._usersbyid[id]
+
+    def setObject(self, key, object):
+        'See IWriteContainer'
+        if key.strip()=='':
+            self._next += 1
+            key = self._next
+        self._usersbyid[key] = object
+        self._usersbylogin[object.getLogin()] = object
+
+    def __delitem__(self, key):
+        'See IWriteContainer'
+        user = self._usersbyid[key]
+        del self._usersbylogin[user.getLogin()]
+        del self._usersbyid[key]
+
+    def keys(self):
+        'See IEnumerableMapping'
+        return self._usersbyid.keys()
+
+    def values(self):
+        'See IEnumerableMapping'
+        return self._usersbyid.values()
+
+    def items(self):
+        'See IEnumerableMapping'
+        return self._usersbyid.items()
+
+    def __len__(self):
+        'See IEnumerableMapping'
+        return len(self._usersbyid)
+
+    def get(self, key, default=None):
+        'See IReadMapping'
+        return self._usersbyid.get(key, default)
+
+    def __contains__(self,key):
+        'See IReadMapping'
+        return key in self._usersbyid
+
 
 
 class User(Persistent):