Back to index

plone3  3.1.7
test_ZODBUserManager.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights
00004 # Reserved.
00005 #
00006 # This software is subject to the provisions of the Zope Public License,
00007 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this
00008 # distribution.
00009 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00010 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00011 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00012 # FOR A PARTICULAR PURPOSE.
00013 #
00014 ##############################################################################
00015 import unittest
00016 
00017 from Products.PluggableAuthService.tests.conformance \
00018     import IAuthenticationPlugin_conformance
00019 from Products.PluggableAuthService.tests.conformance \
00020     import IUserEnumerationPlugin_conformance
00021 from Products.PluggableAuthService.tests.conformance \
00022     import IUserAdderPlugin_conformance
00023 
00024 from Products.PluggableAuthService.plugins.tests.helpers \
00025      import makeRequestAndResponse
00026 
00027 class DummyUser:
00028 
00029     def __init__( self, id ):
00030         self._id = id
00031 
00032     def getId( self ):
00033         return self._id
00034 
00035 class ZODBUserManagerTests( unittest.TestCase
00036                           , IAuthenticationPlugin_conformance
00037                           , IUserEnumerationPlugin_conformance
00038                           , IUserAdderPlugin_conformance
00039                           ):
00040 
00041     def _getTargetClass( self ):
00042 
00043         from Products.PluggableAuthService.plugins.ZODBUserManager \
00044             import ZODBUserManager
00045 
00046         return ZODBUserManager
00047 
00048     def _makeOne( self, id='test', *args, **kw ):
00049 
00050         return self._getTargetClass()( id=id, *args, **kw )
00051 
00052     def test_empty( self ):
00053 
00054         zum = self._makeOne()
00055 
00056         self.assertEqual( len( zum.listUserIds() ), 0 )
00057         self.assertEqual( len( zum.enumerateUsers() ), 0 )
00058         self.assertRaises( KeyError
00059                          , zum.getUserIdForLogin, 'userid@example.com' )
00060         self.assertRaises( KeyError
00061                          , zum.getLoginForUserId, 'userid' )
00062 
00063     def test_addUser( self ):
00064 
00065         zum = self._makeOne()
00066 
00067         zum.addUser( 'userid', 'userid@example.com', 'password' )
00068 
00069         user_ids = zum.listUserIds()
00070         self.assertEqual( len( user_ids ), 1 )
00071         self.assertEqual( user_ids[0], 'userid' )
00072         self.assertEqual( zum.getUserIdForLogin( 'userid@example.com' )
00073                         , 'userid' )
00074         self.assertEqual( zum.getLoginForUserId( 'userid' )
00075                         , 'userid@example.com' )
00076 
00077         info_list = zum.enumerateUsers()
00078         self.assertEqual( len( info_list ), 1 )
00079         info = info_list[ 0 ]
00080         self.assertEqual( info[ 'id' ], 'userid' )
00081         self.assertEqual( info[ 'login' ], 'userid@example.com' )
00082 
00083     def test_addUser_duplicate_check( self ):
00084 
00085         zum = self._makeOne()
00086 
00087         zum.addUser( 'userid', 'userid@example.com', 'password' )
00088 
00089         self.assertRaises( KeyError, zum.addUser
00090                          , 'userid', 'luser@other.com', 'wordpass' )
00091 
00092         self.assertRaises( KeyError, zum.addUser
00093                          , 'new_user', 'userid@example.com', '3733t' )
00094 
00095     def test_removeUser_nonesuch( self ):
00096 
00097         zum = self._makeOne()
00098 
00099         self.assertRaises( KeyError, zum.removeUser, 'nonesuch' )
00100 
00101     def test_removeUser_valid_id( self ):
00102 
00103         zum = self._makeOne()
00104 
00105         zum.addUser( 'userid', 'userid@example.com', 'password' )
00106         zum.addUser( 'doomed', 'doomed@example.com', 'password' )
00107 
00108         zum.removeUser( 'doomed' )
00109 
00110         user_ids = zum.listUserIds()
00111         self.assertEqual( len( user_ids ), 1 )
00112         self.assertEqual( len( zum.enumerateUsers() ), 1 )
00113         self.assertEqual( user_ids[0], 'userid' )
00114 
00115         self.assertEqual( zum.getUserIdForLogin( 'userid@example.com' )
00116                         , 'userid' )
00117         self.assertEqual( zum.getLoginForUserId( 'userid' )
00118                         , 'userid@example.com' )
00119 
00120         self.assertRaises( KeyError
00121                          , zum.getUserIdForLogin, 'doomed@example.com' )
00122         self.assertRaises( KeyError
00123                          , zum.getLoginForUserId, 'doomed' )
00124 
00125     def test_authenticateCredentials_bad_creds( self ):
00126 
00127         zum = self._makeOne()
00128 
00129         zum.addUser( 'userid', 'userid@example.com', 'password' )
00130 
00131         self.assertEqual( zum.authenticateCredentials( {} ), None )
00132 
00133     def test_authenticateCredentials_valid_creds( self ):
00134 
00135         zum = self._makeOne()
00136 
00137         zum.addUser( 'userid', 'userid@example.com', 'password' )
00138 
00139         user_id, login = zum.authenticateCredentials(
00140                                 { 'login' : 'userid@example.com'
00141                                 , 'password' : 'password'
00142                                 } )
00143 
00144         self.assertEqual( user_id, 'userid' )
00145         self.assertEqual( login, 'userid@example.com' )
00146 
00147     def test_enumerateUsers_no_criteria( self ):
00148 
00149         from Products.PluggableAuthService.tests.test_PluggableAuthService \
00150             import FauxRoot
00151 
00152         root = FauxRoot()
00153         zum = self._makeOne( id='no_crit' ).__of__( root )
00154 
00155         ID_LIST = ( 'foo', 'bar', 'baz', 'bam' )
00156 
00157         for id in ID_LIST:
00158 
00159             zum.addUser( id, '%s@example.com' % id, 'password' )
00160 
00161         info_list = zum.enumerateUsers()
00162 
00163         self.assertEqual( len( info_list ), len( ID_LIST ) )
00164 
00165         sorted = list( ID_LIST )
00166         sorted.sort()
00167 
00168         for i in range( len( sorted ) ):
00169 
00170             self.assertEqual( info_list[ i ][ 'id' ], sorted[ i ] )
00171             self.assertEqual( info_list[ i ][ 'login' ]
00172                             , '%s@example.com' % sorted[ i ] )
00173             self.assertEqual( info_list[ i ][ 'pluginid' ], 'no_crit' )
00174             self.assertEqual( info_list[ i ][ 'editurl' ]
00175                             , 'no_crit/manage_users?user_id=%s' % sorted[ i ])
00176 
00177     def test_enumerateUsers_exact( self ):
00178 
00179         from Products.PluggableAuthService.tests.test_PluggableAuthService \
00180             import FauxRoot
00181 
00182         root = FauxRoot()
00183         zum = self._makeOne( id='exact' ).__of__( root )
00184 
00185         ID_LIST = ( 'foo', 'bar', 'baz', 'bam' )
00186 
00187         for id in ID_LIST:
00188 
00189             zum.addUser( id, '%s@example.com' % id, 'password' )
00190 
00191         info_list = zum.enumerateUsers( id='bar', exact_match=True )
00192 
00193         self.assertEqual( len( info_list ), 1 )
00194         info = info_list[ 0 ]
00195 
00196         self.assertEqual( info[ 'id' ], 'bar' )
00197         self.assertEqual( info[ 'login' ], 'bar@example.com' )
00198         self.assertEqual( info[ 'pluginid' ], 'exact' )
00199         self.assertEqual( info[ 'editurl' ]
00200                         , 'exact/manage_users?user_id=bar' )
00201 
00202 
00203     def test_enumerateUsers_partial( self ):
00204 
00205         from Products.PluggableAuthService.tests.test_PluggableAuthService \
00206             import FauxRoot
00207 
00208         root = FauxRoot()
00209         zum = self._makeOne( id='partial' ).__of__( root )
00210 
00211         ID_LIST = ( 'foo', 'bar', 'baz', 'bam' )
00212 
00213         for id in ID_LIST:
00214 
00215             zum.addUser( id, '%s@example.com' % id, 'password' )
00216 
00217         info_list = zum.enumerateUsers( login='example.com', exact_match=False )
00218 
00219         self.assertEqual( len( info_list ), len( ID_LIST ) ) # all match
00220 
00221         sorted = list( ID_LIST )
00222         sorted.sort()
00223 
00224         for i in range( len( sorted ) ):
00225 
00226             self.assertEqual( info_list[ i ][ 'id' ], sorted[ i ] )
00227             self.assertEqual( info_list[ i ][ 'login' ]
00228                             , '%s@example.com' % sorted[ i ] )
00229             self.assertEqual( info_list[ i ][ 'pluginid' ], 'partial' )
00230             self.assertEqual( info_list[ i ][ 'editurl' ]
00231                             , 'partial/manage_users?user_id=%s' % sorted[ i ])
00232 
00233         info_list = zum.enumerateUsers( id='ba', exact_match=False )
00234 
00235         self.assertEqual( len( info_list ), len( ID_LIST ) - 1 ) # no 'foo'
00236 
00237         sorted = list( ID_LIST )
00238         sorted.sort()
00239 
00240         for i in range( len( sorted ) - 1 ):
00241 
00242             self.assertEqual( info_list[ i ][ 'id' ], sorted[ i ] )
00243             self.assertEqual( info_list[ i ][ 'login' ]
00244                             , '%s@example.com' % sorted[ i ] )
00245             self.assertEqual( info_list[ i ][ 'pluginid' ], 'partial' )
00246             self.assertEqual( info_list[ i ][ 'editurl' ]
00247                             , 'partial/manage_users?user_id=%s' % sorted[ i ])
00248 
00249     def test_enumerateUsers_other_criteria( self ):
00250 
00251         from Products.PluggableAuthService.tests.test_PluggableAuthService \
00252             import FauxRoot
00253 
00254         root = FauxRoot()
00255         zum = self._makeOne( id='partial' ).__of__( root )
00256 
00257         ID_LIST = ( 'foo', 'bar', 'baz', 'bam' )
00258 
00259         for id in ID_LIST:
00260 
00261             zum.addUser( id, '%s@example.com' % id, 'password' )
00262 
00263         info_list = zum.enumerateUsers( email='bar@example.com',
00264                                         exact_match=False )
00265         self.assertEqual( len( info_list ), 0 )
00266 
00267     def test_enumerateUsers_unicode( self ):
00268 
00269         from Products.PluggableAuthService.tests.test_PluggableAuthService \
00270             import FauxRoot
00271 
00272         root = FauxRoot()
00273         zum = self._makeOne( id='partial' ).__of__( root )
00274 
00275         ID_LIST = ( 'foo', 'bar', 'baz', 'bam' )
00276 
00277         for id in ID_LIST:
00278 
00279             zum.addUser( id, '%s@example.com' % id, 'password' )
00280 
00281         info_list = zum.enumerateUsers( id = u'abc',
00282                                         exact_match=False )
00283         self.assertEqual( len( info_list ), 0 )
00284 
00285     def test_enumerateUsers_exact_nonesuch( self ):
00286 
00287         from Products.PluggableAuthService.tests.test_PluggableAuthService \
00288             import FauxRoot
00289 
00290         root = FauxRoot()
00291         zum = self._makeOne( id='exact_nonesuch' ).__of__( root )
00292 
00293         ID_LIST = ( 'foo', 'bar', 'baz', 'bam' )
00294 
00295         for id in ID_LIST:
00296 
00297             zum.addUser( id, '%s@example.com' % id, 'password' )
00298 
00299         self.assertEquals( zum.enumerateUsers( id='qux', exact_match=True )
00300                          , () )
00301 
00302     def test_enumerateUsers_multiple_ids( self ):
00303 
00304         from Products.PluggableAuthService.tests.test_PluggableAuthService \
00305             import FauxRoot
00306 
00307         root = FauxRoot()
00308         zum = self._makeOne( id='partial' ).__of__( root )
00309 
00310         ID_LIST = ( 'foo', 'bar', 'baz', 'bam' )
00311 
00312         for id in ID_LIST:
00313 
00314             zum.addUser( id, '%s@example.com' % id, 'password' )
00315 
00316         info_list = zum.enumerateUsers( id=ID_LIST )
00317 
00318         self.assertEqual( len( info_list ), len( ID_LIST ) )
00319 
00320         for info in info_list:
00321             self.failUnless( info[ 'id' ] in ID_LIST )
00322 
00323         SUBSET = ID_LIST[:3]
00324 
00325         info_list = zum.enumerateUsers( id=SUBSET )
00326 
00327         self.assertEqual( len( info_list ), len( SUBSET ) )
00328 
00329         for info in info_list:
00330             self.failUnless( info[ 'id' ] in SUBSET )
00331 
00332     def test_enumerateUsers_multiple_logins( self ):
00333 
00334         from Products.PluggableAuthService.tests.test_PluggableAuthService \
00335             import FauxRoot
00336 
00337         root = FauxRoot()
00338         zum = self._makeOne( id='partial' ).__of__( root )
00339 
00340         ID_LIST = ( 'foo', 'bar', 'baz', 'bam' )
00341         LOGIN_LIST = [ '%s@example.com' % x for x in ID_LIST ]
00342 
00343         for i in range( len( ID_LIST ) ):
00344 
00345             zum.addUser( ID_LIST[i], LOGIN_LIST[i], 'password' )
00346 
00347         info_list = zum.enumerateUsers( login=LOGIN_LIST )
00348 
00349         self.assertEqual( len( info_list ), len( LOGIN_LIST ) )
00350 
00351         for info in info_list:
00352             self.failUnless( info[ 'id' ] in ID_LIST )
00353             self.failUnless( info[ 'login' ] in LOGIN_LIST )
00354 
00355         SUBSET_LOGINS = LOGIN_LIST[:3]
00356         SUBSET_IDS = ID_LIST[:3]
00357 
00358         info_list = zum.enumerateUsers( login=SUBSET_LOGINS )
00359 
00360         self.assertEqual( len( info_list ), len( SUBSET_LOGINS ) )
00361 
00362         for info in info_list:
00363             self.failUnless( info[ 'id' ] in SUBSET_IDS )
00364             self.failUnless( info[ 'login' ] in SUBSET_LOGINS )
00365 
00366     def test_authenticateWithOldPasswords( self ):
00367 
00368         import sha
00369 
00370         zum = self._makeOne()
00371 
00372         # synthesize an older account
00373 
00374         old_password = sha.sha( 'old_password' ).hexdigest()
00375         zum._user_passwords[ 'old_user' ] = old_password
00376         zum._login_to_userid[ 'old_user@example.com' ] = 'old_user'
00377         zum._userid_to_login[ 'old_user' ] = 'old_user@example.com'
00378 
00379         # create a new user
00380 
00381         zum.addUser( 'new_user', 'new_user@example.com', 'new_password' )
00382 
00383         user_id, login = zum.authenticateCredentials(
00384                                 { 'login' : 'old_user@example.com'
00385                                 , 'password' : 'old_password'
00386                                 } )
00387 
00388         self.assertEqual( user_id, 'old_user' )
00389         self.assertEqual( login, 'old_user@example.com' )
00390 
00391         user_id, login = zum.authenticateCredentials(
00392                                 { 'login' : 'new_user@example.com'
00393                                 , 'password' : 'new_password'
00394                                 } )
00395 
00396         self.assertEqual( user_id, 'new_user' )
00397         self.assertEqual( login, 'new_user@example.com' )
00398 
00399     def test_updateUserPassword(self):
00400 
00401         zum = self._makeOne()
00402 
00403         # Create a user and make sure we can authenticate with it
00404         zum.addUser( 'user1', 'user1@example.com', 'password' )
00405         info1 = { 'login' : 'user1@example.com', 'password' : 'password' }
00406         user_id, login = zum.authenticateCredentials(info1)
00407         self.assertEqual(user_id, 'user1')
00408         self.assertEqual(login, 'user1@example.com')
00409 
00410         # Give the user a new password; attempting to authenticate with the
00411         # old password must fail
00412         zum.updateUserPassword('user1', 'new_password')
00413         self.failIf(zum.authenticateCredentials(info1))
00414 
00415         # Try to authenticate with the new password, this must succeed.
00416         info2 = { 'login' : 'user1@example.com', 'password' : 'new_password' }
00417         user_id, login = zum.authenticateCredentials(info2)
00418         self.assertEqual(user_id, 'user1')
00419         self.assertEqual(login, 'user1@example.com')
00420 
00421     def test_updateUser(self):
00422 
00423         zum = self._makeOne()
00424 
00425         # Create a user and make sure we can authenticate with it
00426         zum.addUser( 'user1', 'user1@example.com', 'password' )
00427         info1 = { 'login' : 'user1@example.com', 'password' : 'password' }
00428         user_id, login = zum.authenticateCredentials(info1)
00429         self.assertEqual(user_id, 'user1')
00430         self.assertEqual(login, 'user1@example.com')
00431 
00432         # Give the user a new login; attempts to authenticate with the
00433         # old login must fail.
00434         zum.updateUser('user1', 'user1@foobar.com')
00435         self.failIf(zum.authenticateCredentials(info1))
00436 
00437         # Try to authenticate with the new login, this must succeed.
00438         info2 = { 'login' : 'user1@foobar.com', 'password' : 'password' }
00439         user_id, login = zum.authenticateCredentials(info2)
00440         self.assertEqual(user_id, 'user1')
00441         self.assertEqual(login, 'user1@foobar.com')
00442 
00443     def test_enumerateUsersWithOptionalMangling(self):
00444 
00445         zum = self._makeOne()
00446         zum.prefix = 'special__'
00447 
00448         zum.addUser('user', 'login', 'password')
00449         info = zum.enumerateUsers(login='login')
00450         self.assertEqual(info[0]['id'], 'special__user')
00451 
00452     def test_getUserByIdWithOptionalMangling(self):
00453 
00454         zum = self._makeOne()
00455         zum.prefix = 'special__'
00456 
00457         zum.addUser('user', 'login', 'password')
00458 
00459         info = zum.enumerateUsers(id='user', exact_match=True)
00460         self.assertEqual(len(info), 0)
00461 
00462         info = zum.enumerateUsers(id='special__user', exact_match=True)
00463         self.assertEqual(info[0]['id'], 'special__user')
00464 
00465         info = zum.enumerateUsers(id='special__luser', exact_match=True)
00466         self.assertEqual(len(info), 0)
00467 
00468     def test_addUser_with_not_yet_encrypted_password(self):
00469         # See collector #1869 && #1926
00470         from AccessControl.AuthEncoding import is_encrypted
00471 
00472         USER_ID = 'not_yet_encrypted'
00473         PASSWORD = 'password'
00474 
00475         self.failIf(is_encrypted(PASSWORD))
00476 
00477         zum = self._makeOne()
00478         zum.addUser(USER_ID, USER_ID, PASSWORD)
00479 
00480         uid_and_info = zum.authenticateCredentials(
00481                                 { 'login': USER_ID
00482                                 , 'password': PASSWORD
00483                                 })
00484 
00485         self.assertEqual(uid_and_info, (USER_ID, USER_ID))
00486 
00487     def test_addUser_with_preencrypted_password(self):
00488         # See collector #1869 && #1926
00489         from AccessControl.AuthEncoding import pw_encrypt
00490 
00491         USER_ID = 'already_encrypted'
00492         PASSWORD = 'password'
00493 
00494         ENCRYPTED = pw_encrypt(PASSWORD)
00495 
00496         zum = self._makeOne()
00497         zum.addUser(USER_ID, USER_ID, ENCRYPTED)
00498 
00499         uid_and_info = zum.authenticateCredentials(
00500                                 { 'login': USER_ID
00501                                 , 'password': PASSWORD
00502                                 })
00503 
00504         self.assertEqual(uid_and_info, (USER_ID, USER_ID))
00505 
00506     def test_updateUserPassword_with_not_yet_encrypted_password(self):
00507         from AccessControl.AuthEncoding import is_encrypted
00508 
00509         USER_ID = 'not_yet_encrypted'
00510         PASSWORD = 'password'
00511 
00512         self.failIf(is_encrypted(PASSWORD))
00513 
00514         zum = self._makeOne()
00515         zum.addUser(USER_ID, USER_ID, '')
00516         zum.updateUserPassword(USER_ID, PASSWORD)
00517 
00518         uid_and_info = zum.authenticateCredentials(
00519                                 { 'login': USER_ID
00520                                 , 'password': PASSWORD
00521                                 })
00522 
00523         self.assertEqual(uid_and_info, (USER_ID, USER_ID))
00524 
00525     def test_updateUserPassword_with_preencrypted_password(self):
00526         from AccessControl.AuthEncoding import pw_encrypt
00527 
00528         USER_ID = 'already_encrypted'
00529         PASSWORD = 'password'
00530 
00531         ENCRYPTED = pw_encrypt(PASSWORD)
00532 
00533         zum = self._makeOne()
00534         zum.addUser(USER_ID, USER_ID, '')
00535         zum.updateUserPassword(USER_ID, ENCRYPTED)
00536 
00537         uid_and_info = zum.authenticateCredentials(
00538                                 { 'login': USER_ID
00539                                 , 'password': PASSWORD
00540                                 })
00541 
00542         self.assertEqual(uid_and_info, (USER_ID, USER_ID))
00543 
00544     def test_manage_updatePassword(self):
00545         from AccessControl.SecurityManagement import newSecurityManager
00546         from AccessControl.SecurityManagement import noSecurityManager
00547         from Acquisition import Implicit
00548         # Test that a user can update her own password using the
00549         # ZMI-provided form handler: http://www.zope.org/Collectors/PAS/56
00550         zum = self._makeOne()
00551 
00552         # Create a user and make sure we can authenticate with it
00553         zum.addUser( 'user1', 'user1@example.com', 'password' )
00554         info1 = { 'login' : 'user1@example.com', 'password' : 'password' }
00555         self.failUnless(zum.authenticateCredentials(info1))
00556 
00557         # Give the user a new password; attempting to authenticate with the
00558         # old password must fail
00559         class FauxUser(Implicit):
00560 
00561             def __init__(self, id):
00562                 self._id = id
00563 
00564             def getId( self ):
00565                 return self._id
00566 
00567         newSecurityManager(None, FauxUser('user1'))
00568         try:
00569             zum.manage_updatePassword('user2@example.com',
00570                                       'new_password',
00571                                       'new_password',
00572                                      )
00573         finally:
00574             noSecurityManager()
00575 
00576         self.failIf(zum.authenticateCredentials(info1))
00577 
00578         # Try to authenticate with the new password, this must succeed.
00579         info2 = { 'login' : 'user2@example.com', 'password' : 'new_password' }
00580         user_id, login = zum.authenticateCredentials(info2)
00581         self.assertEqual(user_id, 'user1')
00582         self.assertEqual(login, 'user2@example.com')
00583 
00584     def testPOSTProtections(self):
00585         from AccessControl.AuthEncoding import pw_encrypt
00586         from zExceptions import Forbidden
00587         USER_ID = 'testuser'
00588         PASSWORD = 'password'
00589 
00590         ENCRYPTED = pw_encrypt(PASSWORD)
00591 
00592         zum = self._makeOne()
00593         zum.addUser(USER_ID, USER_ID, '')
00594 
00595         req, res = makeRequestAndResponse()
00596         # test manage_updateUserPassword
00597         # Fails with a GET
00598         req.set('REQUEST_METHOD', 'GET')
00599         self.assertRaises(Forbidden, zum.manage_updateUserPassword,
00600                           USER_ID, PASSWORD, PASSWORD, REQUEST=req)
00601         # Works with a POST
00602         req.set('REQUEST_METHOD', 'POST')
00603         zum.manage_updateUserPassword(USER_ID, PASSWORD, PASSWORD, REQUEST=req)
00604 
00605         # test manage_updatePassword
00606         req.set('REQUEST_METHOD', 'GET')
00607         self.assertRaises(Forbidden, zum.manage_updatePassword,
00608                           USER_ID, PASSWORD, PASSWORD, REQUEST=req)
00609         # XXX: This method is broken
00610 
00611         # test manage_removeUsers
00612         req.set('REQUEST_METHOD', 'GET')
00613         self.assertRaises(Forbidden, zum.manage_removeUsers,
00614                           [USER_ID], REQUEST=req)
00615         req.set('REQUEST_METHOD', 'POST')
00616         zum.manage_removeUsers([USER_ID], REQUEST=req)
00617 
00618 
00619 if __name__ == "__main__":
00620     unittest.main()
00621 
00622 def test_suite():
00623     return unittest.TestSuite((
00624         unittest.makeSuite( ZODBUserManagerTests ),
00625         ))