[Checkins] SVN: PluggableAuthService/trunk/ - ZODBUserManager: Extend the "notional IZODBUserManager interface"

Jens Vagelpohl jens at dataflake.org
Sat Jun 24 07:01:17 EDT 2006


Log message for revision 68822:
  - ZODBUserManager: Extend the "notional IZODBUserManager interface"
    with the left-out updateUser facility and a corresponding
    manage_updateUser method for ZMI use. Removed any responsibility
    for updating a user's login from the updateUserPassword and
    manage_updateUserPassword methods. This fixes the breakage
    described in the collector issue below, and makes the ZMI view
    for updating users work in a sane way.
    (http://www.zope.org/Collectors/PAS/42)
  

Changed:
  U   PluggableAuthService/trunk/doc/CHANGES.txt
  U   PluggableAuthService/trunk/plugins/ZODBUserManager.py
  U   PluggableAuthService/trunk/plugins/tests/test_ZODBUserManager.py
  U   PluggableAuthService/trunk/plugins/www/zuUsers.zpt

-=-
Modified: PluggableAuthService/trunk/doc/CHANGES.txt
===================================================================
--- PluggableAuthService/trunk/doc/CHANGES.txt	2006-06-24 09:46:59 UTC (rev 68821)
+++ PluggableAuthService/trunk/doc/CHANGES.txt	2006-06-24 11:01:17 UTC (rev 68822)
@@ -4,6 +4,15 @@
 
     Bugs Fixed
 
+      - ZODBUserManager: Extend the "notional IZODBUserManager interface"
+        with the left-out updateUser facility and a corresponding
+        manage_updateUser method for ZMI use. Removed any responsibility
+        for updating a user's login from the updateUserPassword and
+        manage_updateUserPassword methods. This fixes the breakage
+        described in the collector issue below, and makes the ZMI view
+        for updating users work in a sane way.
+        (http://www.zope.org/Collectors/PAS/42)
+
       - CookieAuthHelper: If expireCookie was called and extractCredentials
         was hit in the same request, the CookieAuthHelper would throw an
         exception (http://www.zope.org/Collectors/PAS/43)

Modified: PluggableAuthService/trunk/plugins/ZODBUserManager.py
===================================================================
--- PluggableAuthService/trunk/plugins/ZODBUserManager.py	2006-06-24 09:46:59 UTC (rev 68821)
+++ PluggableAuthService/trunk/plugins/ZODBUserManager.py	2006-06-24 11:01:17 UTC (rev 68822)
@@ -287,6 +287,16 @@
         view_name = createViewName('enumerateUsers')
         self.ZCacheable_invalidate(view_name=view_name)
 
+    security.declarePrivate('updateUser')
+    def updateUser(self, user_id, login_name):
+        
+        # The following raises a KeyError if the user_id is invalid
+        old_login = self.getLoginForUserId(user_id)
+
+        del self._login_to_userid[old_login]
+        self._login_to_userid[login_name] = user_id
+        self._userid_to_login[user_id] = login_name
+
     security.declarePrivate( 'removeUser' )
     def removeUser( self, user_id ):
 
@@ -306,18 +316,11 @@
         self.ZCacheable_invalidate(view_name=view_name)
 
     security.declarePrivate( 'updateUserPassword' )
-    def updateUserPassword( self, user_id, login_name, password ):
+    def updateUserPassword( self, user_id, password ):
 
         if self._user_passwords.get( user_id ) is None:
             raise KeyError, 'Invalid user ID: %s' % user_id
 
-        old_login_name = self._userid_to_login[ user_id ]
-
-        if old_login_name != login_name:
-            del self._login_to_userid[ old_login_name ]
-            self._login_to_userid[ login_name ] = user_id
-            self._userid_to_login[ user_id ] = login_name
-
         if password:
             digested = AuthEncoding.pw_encrypt( password )
             self._user_passwords[ user_id ] = digested
@@ -377,7 +380,6 @@
     security.declareProtected( ManageUsers, 'manage_updateUserPassword' )
     def manage_updateUserPassword( self
                                  , user_id
-                                 , login_name
                                  , password
                                  , confirm
                                  , RESPONSE=None
@@ -389,15 +391,28 @@
 
         else:
         
-            if not login_name:
-                login_name = user_id
+            self.updateUserPassword( user_id, password )
 
-            # XXX:  validate 'user_id', 'login_name' against policies?
+            message = 'password+updated'
 
-            self.updateUserPassword( user_id, login_name, password )
+        if RESPONSE is not None:
+            RESPONSE.redirect( '%s/manage_users?manage_tabs_message=%s'
+                             % ( self.absolute_url(), message )
+                             )
 
-            message = 'password+updated'
+    security.declareProtected( ManageUsers, 'manage_updateUser' )
+    def manage_updateUser(self, user_id, login_name, RESPONSE=None):
+        """ Update a user's login name via the ZMI.
+        """
+        if not login_name:
+            login_name = user_id
 
+        # XXX:  validate 'user_id', 'login_name' against policies?
+
+        self.updateUser(user_id, login_name)
+
+        message = 'Login+name+updated'
+
         if RESPONSE is not None:
             RESPONSE.redirect( '%s/manage_users?manage_tabs_message=%s'
                              % ( self.absolute_url(), message )

Modified: PluggableAuthService/trunk/plugins/tests/test_ZODBUserManager.py
===================================================================
--- PluggableAuthService/trunk/plugins/tests/test_ZODBUserManager.py	2006-06-24 09:46:59 UTC (rev 68821)
+++ PluggableAuthService/trunk/plugins/tests/test_ZODBUserManager.py	2006-06-24 11:01:17 UTC (rev 68822)
@@ -357,6 +357,50 @@
         self.assertEqual( user_id, 'new_user' )
         self.assertEqual( login, 'new_user at example.com' )
 
+    def test_updateUserPassword(self):
+
+        zum = self._makeOne()
+
+        # Create a user and make sure we can authenticate with it
+        zum.addUser( 'user1', 'user1 at example.com', 'password' )
+        info1 = { 'login' : 'user1 at example.com', 'password' : 'password' }
+        user_id, login = zum.authenticateCredentials(info1)
+        self.assertEqual(user_id, 'user1')
+        self.assertEqual(login, 'user1 at example.com')
+
+        # Give the user a new password; attempting to authenticate with the
+        # old password must fail
+        zum.updateUserPassword('user1', 'new_password')
+        self.failIf(zum.authenticateCredentials(info1))
+
+        # Try to authenticate with the new password, this must succeed.
+        info2 = { 'login' : 'user1 at example.com', 'password' : 'new_password' }
+        user_id, login = zum.authenticateCredentials(info2)
+        self.assertEqual(user_id, 'user1')
+        self.assertEqual(login, 'user1 at example.com')
+
+    def test_updateUser(self):
+
+        zum = self._makeOne()
+
+        # Create a user and make sure we can authenticate with it
+        zum.addUser( 'user1', 'user1 at example.com', 'password' )
+        info1 = { 'login' : 'user1 at example.com', 'password' : 'password' }
+        user_id, login = zum.authenticateCredentials(info1)
+        self.assertEqual(user_id, 'user1')
+        self.assertEqual(login, 'user1 at example.com')
+
+        # Give the user a new login; attempts to authenticate with the
+        # old login must fail.
+        zum.updateUser('user1', 'user1 at foobar.com')
+        self.failIf(zum.authenticateCredentials(info1))
+
+        # Try to authenticate with the new login, this must succeed.
+        info2 = { 'login' : 'user1 at foobar.com', 'password' : 'password' }
+        user_id, login = zum.authenticateCredentials(info2)
+        self.assertEqual(user_id, 'user1')
+        self.assertEqual(login, 'user1 at foobar.com')
+
     def test_enumerateUsersWithOptionalMangling(self):
 
         zum = self._makeOne()

Modified: PluggableAuthService/trunk/plugins/www/zuUsers.zpt
===================================================================
--- PluggableAuthService/trunk/plugins/www/zuUsers.zpt	2006-06-24 09:46:59 UTC (rev 68821)
+++ PluggableAuthService/trunk/plugins/www/zuUsers.zpt	2006-06-24 11:01:17 UTC (rev 68822)
@@ -126,11 +126,34 @@
   </td>
  </tr>
 
- <tbody metal:use-macro="here/manage_widgets/macros/authentication_widgets">
+ <tr valign="top">
+  <th align="right">
+   <div class="form-label">Login name:</div>
+  </th>
+  <td>
+    <div class="form-label" tal:content="login_name"> Login </div>
+  </td>
+ </tr>
 
- </tbody>
+ <tr valign="top">
+  <th align="right">
+   <div class="form-label">Password:</div>
+  </th>
+  <td>
+   <input type="password" name="password" size="20" value="password" />
+  </td>
+ </tr>
 
  <tr valign="top">
+  <th align="right">
+   <div class="form-label">Confirm password:</div>
+  </th>
+  <td>
+   <input type="password" name="confirm" size="20" value="confirm" />
+  </td>
+ </tr>
+
+ <tr valign="top">
   <td />
   <td>
    <input type="submit" value=" Update Password " />
@@ -160,10 +183,25 @@
   <th align="right">
    <div class="form-label">User ID:</div>
   </th>
-  <td tal:content="user_id">USER_ID</td>
+  <td>
+   <input type="hidden" name="user_id"
+          tal:attributes="value user_id" />
+   <div class="form-label" tal:content="user_id">USER_ID</div>
+  </td>
  </tr>
 
  <tr valign="top">
+  <th align="right">
+   <div class="form-label">Login name:</div>
+  </th>
+  <td>
+   <input type="text" name="login_name" size="40"
+          tal:attributes="value login_name"
+   />
+  </td>
+ </tr>
+
+ <tr valign="top">
   <td />
   <td>
    <input type="submit" value=" Update User " />



More information about the Checkins mailing list