[Checkins] SVN: Products.PluggableAuthService/trunk/Products/PluggableAuthService/ Ensure the _findUser cache is invalidated if the roles or groups for a principal change.

Wichert Akkerman wichert at wiggy.net
Mon Aug 4 06:34:41 EDT 2008


Log message for revision 89339:
  Ensure the _findUser cache is invalidated if the roles or groups for a principal change.

Changed:
  U   Products.PluggableAuthService/trunk/Products/PluggableAuthService/doc/CHANGES.txt
  U   Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/BasePlugin.py
  U   Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/ZODBGroupManager.py
  U   Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/ZODBRoleManager.py
  U   Products.PluggableAuthService/trunk/Products/PluggableAuthService/tests/test_MoreCaching.py

-=-
Modified: Products.PluggableAuthService/trunk/Products/PluggableAuthService/doc/CHANGES.txt
===================================================================
--- Products.PluggableAuthService/trunk/Products/PluggableAuthService/doc/CHANGES.txt	2008-08-04 10:33:01 UTC (rev 89338)
+++ Products.PluggableAuthService/trunk/Products/PluggableAuthService/doc/CHANGES.txt	2008-08-04 10:34:40 UTC (rev 89339)
@@ -4,6 +4,9 @@
 PluggableAuthService 1.6 (unreleased)
 -------------------------------------
 
+- Ensure the _findUser cache is invalidated if the roles or groups for
+  a principal change.
+
 - Launchpad #15569586:  docstring fix.
 
 - Factored out 'filter' logic into separate classes;  added filters

Modified: Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/BasePlugin.py
===================================================================
--- Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/BasePlugin.py	2008-08-04 10:33:01 UTC (rev 89338)
+++ Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/BasePlugin.py	2008-08-04 10:34:40 UTC (rev 89339)
@@ -18,7 +18,7 @@
 """
 from OFS.SimpleItem import SimpleItem
 from OFS.PropertyManager import PropertyManager
-from Acquisition import aq_parent, aq_inner
+from Acquisition import aq_base, aq_parent, aq_inner
 from AccessControl import ClassSecurityInfo
 from App.class_init import default__class_init__ as InitializeClass
 try:
@@ -36,6 +36,7 @@
 
 from Products.PluggableAuthService.utils import classImplements
 from Products.PluggableAuthService.permissions import ManageUsers
+from Products.PluggableAuthService.utils import createViewName
 
 class BasePlugin(SimpleItem, PropertyManager):
 
@@ -113,6 +114,13 @@
         """ Canonical way to get at the PAS instance from a plugin """
         return aq_parent( aq_inner( self ) )
 
+    security.declarePrivate( '_invalidatePrincipalCache' )
+    def _invalidatePrincipalCache( self, id ):
+        pas = self._getPAS()
+        if pas is not None and hasattr( aq_base(pas), 'ZCacheable_invalidate'):
+            view_name = createViewName('_findUser', id)
+            pas.ZCacheable_invalidate(view_name)
+
 classImplements(BasePlugin, *implementedBy(SimpleItem))
 
 InitializeClass(BasePlugin)

Modified: Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/ZODBGroupManager.py
===================================================================
--- Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/ZODBGroupManager.py	2008-08-04 10:33:01 UTC (rev 89338)
+++ Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/ZODBGroupManager.py	2008-08-04 10:34:40 UTC (rev 89339)
@@ -70,6 +70,7 @@
         self._groups = OOBTree()
         self._principal_groups = OOBTree()
 
+
     #
     #   IGroupEnumerationPlugin implementation
     #
@@ -279,6 +280,7 @@
         if not already:
             new = current + ( group_id, )
             self._principal_groups[ principal_id ] = new
+            self._invalidatePrincipalCache( principal_id )
 
         return not already
     addPrincipalToGroup = postonly(addPrincipalToGroup)
@@ -304,6 +306,7 @@
 
         if already:
             self._principal_groups[ principal_id ] = new
+            self._invalidatePrincipalCache( principal_id )
 
         return already
     removePrincipalFromGroup = postonly(removePrincipalFromGroup)

Modified: Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/ZODBRoleManager.py
===================================================================
--- Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/ZODBRoleManager.py	2008-08-04 10:33:01 UTC (rev 89338)
+++ Products.PluggableAuthService/trunk/Products/PluggableAuthService/plugins/ZODBRoleManager.py	2008-08-04 10:34:40 UTC (rev 89339)
@@ -305,6 +305,7 @@
         if not already:
             new = current + ( role_id, )
             self._principal_roles[ principal_id ] = new
+            self._invalidatePrincipalCache( principal_id )
 
         return not already
     assignRoleToPrincipal = postonly(assignRoleToPrincipal)
@@ -329,6 +330,7 @@
 
         if already:
             self._principal_roles[ principal_id ] = new
+            self._invalidatePrincipalCache( principal_id )
 
         return already
     removeRoleFromPrincipal = postonly(removeRoleFromPrincipal)

Modified: Products.PluggableAuthService/trunk/Products/PluggableAuthService/tests/test_MoreCaching.py
===================================================================
--- Products.PluggableAuthService/trunk/Products/PluggableAuthService/tests/test_MoreCaching.py	2008-08-04 10:33:01 UTC (rev 89338)
+++ Products.PluggableAuthService/trunk/Products/PluggableAuthService/tests/test_MoreCaching.py	2008-08-04 10:34:40 UTC (rev 89339)
@@ -247,26 +247,68 @@
 
         self.assertCacheStats(0, 0, 0)
 
-        self.pas._doAddUser(user_id, password, [pastc.user_role], [])
+        self.pas._doAddUser(user_id, password, [], [])
 
-        # XXX: _doAddUser calls getUser
         self.assertCacheStats(2, 2, 0)
 
-        # XXX: As a result the user is now cached, but without roles
         user = self.pas.getUserById(user_id)
         self.failIf(user is None)
         self.assertEqual(user.getId(), user_id)
         self.assertEqual(user.getRoles(), ['Authenticated'])
 
-        # XXX: Must clear cache to get roles
-        self.pas.ZCacheable_invalidate()
+        self.assertCacheStats(3, 3, 1)
 
-        user = self.pas.getUserById(user_id)
-        self.failIf(user is None)
-        self.assertEqual(user.getId(), user_id)
-        self.assertEqual(user.getRoles(), ['Authenticated', pastc.user_role])
+    def test_addingRoleResetsCache(self):
+        user_id = 'test_user_2_'
+        password = 'secret'
 
+        self.pas._doAddUser(user_id, password, [], [])
+        self.assertCacheStats(2, 2, 0)
+        self.pas.roles.assignRoleToPrincipal( pastc.user_role, user_id )
+        self.assertCacheStats(0, 0, 0)
 
+    def test_removingRoleResetsCache(self):
+        user_id = 'test_user_2_'
+        password = 'secret'
+
+        self.pas._doAddUser(user_id, password, [], [])
+        self.assertCacheStats(2, 2, 0)
+        self.pas.roles._principal_roles[ user_id ] = (pastc.user_role, )
+        self.pas.roles.removeRoleFromPrincipal( pastc.user_role, user_id )
+        self.assertCacheStats(0, 0, 0)
+
+    def test_addPrincipalToGroupResetsCache(self):
+        group_id = 'test_group_1_'
+        user_id = 'test_user_2_'
+        password = 'secret'
+
+        factory = self.pas.manage_addProduct['PluggableAuthService']
+        factory.addZODBGroupManager( 'groups' )
+        self.pas._doAddUser(user_id, password, [], [])
+        groups = self.pas.groups
+        groups.addGroup( group_id )
+        self.assertCacheStats(2, 2, 0)
+
+        groups.addPrincipalToGroup( user_id, group_id)
+        self.assertCacheStats(0, 0, 0)
+
+    def test_removePrincipalFromGroupResetsCache(self):
+        group_id = 'test_group_1_'
+        user_id = 'test_user_2_'
+        password = 'secret'
+
+        factory = self.pas.manage_addProduct['PluggableAuthService']
+        factory.addZODBGroupManager( 'groups' )
+        self.pas._doAddUser(user_id, password, [], [])
+        groups = self.pas.groups
+        groups.addGroup( group_id )
+        groups._principal_groups[user_id] = (group_id,)
+        self.assertCacheStats(2, 2, 0)
+
+        groups.removePrincipalFromGroup( user_id, group_id)
+        self.assertCacheStats(0, 0, 0)
+
+
 def test_suite():
     from unittest import TestSuite, makeSuite
     return TestSuite((



More information about the Checkins mailing list