diff roundup/password.py @ 4483:22bc0426e348

Second patch from issue2550688 -- with some changes: - password.py now has a second class JournalPassword used for journal storage. We have some backends that directly store serialized python objects. Also when reading from the journal some backends expected the string read to be usable as a parameter to a Password constructor. This now calls a JournalPassword constructor in all these cases. The new JournalPassword just keeps the scheme and has an empty password. - some factoring, move redundant implementation of "history" from rdbms_common and back_anydbm to hyperdb.
author Ralf Schlatterbeck <schlatterbeck@users.sourceforge.net>
date Thu, 14 Apr 2011 15:42:41 +0000
parents 1613754d2646
children 52e13bf0bb40
line wrap: on
line diff
--- a/roundup/password.py	Thu Apr 14 12:54:52 2011 +0000
+++ b/roundup/password.py	Thu Apr 14 15:42:41 2011 +0000
@@ -168,7 +168,49 @@
     chars = string.letters+string.digits
     return ''.join([random.choice(chars) for x in range(length)])
 
-class Password:
+class JournalPassword:
+    """ Password dummy instance intended for journal operation.
+        We do not store passwords in the journal any longer.  The dummy
+        version only reads the encryption scheme from the given
+        encrypted password.
+    """
+    default_scheme = 'PBKDF2'        # new encryptions use this scheme
+    pwre = re.compile(r'{(\w+)}(.+)')
+
+    def __init__ (self, encrypted=''):
+        if isinstance(encrypted, self.__class__):
+            self.scheme = encrypted.scheme or self.default_scheme
+        else:
+            m = self.pwre.match(encrypted)
+            if m:
+                self.scheme = m.group(1)
+            else:
+                self.scheme = self.default_scheme
+        self.password = ''
+
+    def dummystr(self):
+        """ return dummy string to store in journal
+            - reports scheme, but nothing else
+        """
+        return "{%s}*encrypted*" % (self.scheme,)
+
+    __str__ = dummystr
+
+    def __cmp__(self, other):
+        """Compare this password against another password."""
+        # check to see if we're comparing instances
+        if isinstance(other, self.__class__):
+            if self.scheme != other.scheme:
+                return cmp(self.scheme, other.scheme)
+            return cmp(self.password, other.password)
+
+        # assume password is plaintext
+        if self.password is None:
+            raise ValueError, 'Password not set'
+        return cmp(self.password, encodePassword(other, self.scheme,
+            self.password or None))
+
+class Password(JournalPassword):
     """The class encapsulates a Password property type value in the database.
 
     The encoding of the password is one if None, 'SHA', 'MD5' or 'plaintext'.
@@ -192,9 +234,7 @@
     """
     #TODO: code to migrate from old password schemes.
 
-    default_scheme = 'PBKDF2'        # new encryptions use this scheme
     known_schemes = [ "PBKDF2", "SHA", "MD5", "crypt", "plaintext" ]
-    pwre = re.compile(r'{(\w+)}(.+)')
 
     def __init__(self, plaintext=None, scheme=None, encrypted=None, strict=False):
         """Call setPassword if plaintext is not None."""
@@ -232,20 +272,6 @@
         self.password = encodePassword(plaintext, scheme)
         self.plaintext = plaintext
 
-    def __cmp__(self, other):
-        """Compare this password against another password."""
-        # check to see if we're comparing instances
-        if isinstance(other, Password):
-            if self.scheme != other.scheme:
-                return cmp(self.scheme, other.scheme)
-            return cmp(self.password, other.password)
-
-        # assume password is plaintext
-        if self.password is None:
-            raise ValueError, 'Password not set'
-        return cmp(self.password, encodePassword(other, self.scheme,
-            self.password))
-
     def __str__(self):
         """Stringify the encrypted password for database storage."""
         if self.password is None:

Roundup Issue Tracker: http://roundup-tracker.org/