changeset 1914:591c6df0f900

moint account_password: allow to invalidate a stored pw hash add test for pw hash invalidation set_password: giving an empty or None password means to invalidate the stored pw hash. added docstring.
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Sun, 20 Jan 2013 17:16:14 +0100
parents dbcadc76561a
children a2d2f4a93e0b
files MoinMoin/_tests/test_user.py MoinMoin/script/account/resetpw.py MoinMoin/user.py
diffstat 3 files changed, 46 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/_tests/test_user.py	Sun Jan 20 16:12:13 2013 +0100
+++ b/MoinMoin/_tests/test_user.py	Sun Jan 20 17:16:14 2013 +0100
@@ -79,6 +79,29 @@
         theUser = user.User(name=name, password=password)
         assert theUser.valid
 
+    def testInvalidatePassword(self):
+        """ user: test invalidation of password """
+        # Create test user
+        name = u'__Non Existent User Name__'
+        password = name
+        self.createUser(name, password)
+
+        # Try to "login"
+        theUser = user.User(name=name, password=password)
+        assert theUser.valid
+
+        # invalidate the stored password (hash)
+        theUser.set_password("") # emptry str or None means "invalidate"
+        theUser.save()
+
+        # Try to "login" with previous password
+        theUser = user.User(name=name, password=password)
+        assert not theUser.valid
+
+        # Try to "login" with empty password
+        theUser = user.User(name=name, password="")
+        assert not theUser.valid
+
     def testPasswordHash(self):
         """
         Create user, set a specific pw hash and check that user can login
--- a/MoinMoin/script/account/resetpw.py	Sun Jan 20 16:12:13 2013 +0100
+++ b/MoinMoin/script/account/resetpw.py	Sun Jan 20 17:16:14 2013 +0100
@@ -23,7 +23,7 @@
                help='Set password for the user with user name NAME.'),
         Option('--uid', '-u', required=False, dest='uid', type=unicode,
                help='Set password for the user with user id UID.'),
-        Option('--password', '-p', required=True, dest='password', type=unicode,
+        Option('--password', '-p', required=False, dest='password', type=unicode,
                help='New password for this account.'),
     )
 
@@ -45,9 +45,12 @@
             return
 
         try:
-            u.enc_password = app.cfg.cache.pwd_context.encrypt(password)
+            u.set_password(password)
         except (TypeError, ValueError) as err:
             print "Error: Password could not get processed, aborting."
         else:
             u.save()
-            print 'Password set.'
+            if password:
+                print 'Password set.'
+            else:
+                print 'Password invalidated.'
--- a/MoinMoin/user.py	Sun Jan 20 16:12:13 2013 +0100
+++ b/MoinMoin/user.py	Sun Jan 20 17:16:14 2013 +0100
@@ -433,7 +433,23 @@
         return password_correct, bool(recomputed_hash)
 
     def set_password(self, password, is_encrypted=False, salt=None):
-        if not is_encrypted:
+        """
+        Set or update the password (hash) stored for this user.
+
+        :param password: the new password (or pw hash)
+                         giving an empty string or None as password will invalidate the stored
+                         password hash (meaning that it will not match against any given password)
+        :param is_encrypted: if False (default), the password is given as plaintext and will be
+                             "encrypted" (hashed) before getting stored.
+                             if True, the already "encrypted" password hash is given in param
+                             password and will be stored "as is" - this is mainly useful for tests.
+        :param salt: if None (default), passlib will generate and use a random salt.
+                     Otherwise, the given salt will be used - this is mainly useful for tests.
+        """
+        if not password:
+            # invalidate the pw hash
+            password = ''
+        elif not is_encrypted:
             password = self._cfg.cache.pwd_context.encrypt(password, salt=salt)
         self.profile[ENC_PASSWORD] = password
         # Invalidate all other browser sessions except this one.