Code

Second patch from issue2550688 -- with some changes:
[roundup.git] / roundup / hyperdb.py
index 0c86ede0636fb88e9e8a91ba88f8eea784bb9af4..0ed036060d468d1a4fbd1336fb6db4c942cae431 100644 (file)
@@ -35,11 +35,15 @@ from roundup.i18n import _
 #
 class _Type(object):
     """A roundup property type."""
-    def __init__(self, required=False):
+    def __init__(self, required=False, default_value = None):
         self.required = required
+        self.__default_value = default_value
     def __repr__(self):
         ' more useful for dumps '
         return '<%s.%s>'%(self.__class__.__module__, self.__class__.__name__)
+    def get_default_value(self):
+        """The default value when creating a new instance of this property.""" 
+        return self.__default_value
     def sort_repr (self, cls, val, name):
         """Representation used for sorting. This should be a python
         built-in type, otherwise sorting will take ages. Note that
@@ -50,8 +54,8 @@ class _Type(object):
 
 class String(_Type):
     """An object designating a String property."""
-    def __init__(self, indexme='no', required=False):
-        super(String, self).__init__(required)
+    def __init__(self, indexme='no', required=False, default_value = ""):
+        super(String, self).__init__(required, default_value)
         self.indexme = indexme == 'yes'
     def from_raw(self, value, propname='', **kw):
         """fix the CRLF/CR -> LF stuff"""
@@ -72,24 +76,12 @@ class Password(_Type):
     def from_raw(self, value, **kw):
         if not value:
             return None
-        m = password.Password.pwre.match(value)
-        if m:
-            # password is being given to us encrypted
-            p = password.Password()
-            p.scheme = m.group(1)
-            if p.scheme not in 'SHA crypt plaintext'.split():
-                raise HyperdbValueError, \
-                        ('property %s: unknown encryption scheme %r') %\
-                        (kw['propname'], p.scheme)
-            p.password = m.group(2)
-            value = p
-        else:
-            try:
-                value = password.Password(value)
-            except password.PasswordValueError, message:
-                raise HyperdbValueError, \
-                        _('property %s: %s')%(kw['propname'], message)
-        return value
+        try:
+            return password.Password(encrypted=value, strict=True)
+        except password.PasswordValueError, message:
+            raise HyperdbValueError, \
+                    _('property %s: %s')%(kw['propname'], message)
+
     def sort_repr (self, cls, val, name):
         if not val:
             return val
@@ -97,8 +89,9 @@ class Password(_Type):
 
 class Date(_Type):
     """An object designating a Date property."""
-    def __init__(self, offset=None, required=False):
-        super(Date, self).__init__(required)
+    def __init__(self, offset=None, required=False, default_value = None):
+        super(Date, self).__init__(required = required,
+                                   default_value = default_value)
         self._offset = offset
     def offset(self, db):
         if self._offset is not None:
@@ -136,10 +129,11 @@ class Interval(_Type):
 class _Pointer(_Type):
     """An object designating a Pointer property that links or multilinks
     to a node in a specified class."""
-    def __init__(self, classname, do_journal='yes', required=False):
+    def __init__(self, classname, do_journal='yes', required=False,
+                 default_value = None):
         """ Default is to journal link and unlink events
         """
-        super(_Pointer, self).__init__(required)
+        super(_Pointer, self).__init__(required, default_value)
         self.classname = classname
         self.do_journal = do_journal == 'yes'
     def __repr__(self):
@@ -175,6 +169,14 @@ class Multilink(_Pointer):
        "do_journal" indicates whether the linked-to nodes should have
                     'link' and 'unlink' events placed in their journal
     """
+
+    def __init__(self, classname, do_journal = 'yes', required = False):
+
+        super(Multilink, self).__init__(classname,
+                                        do_journal,
+                                        required = required,
+                                        default_value = [])        
+
     def from_raw(self, value, db, klass, propname, itemid, **kw):
         if not value:
             return []
@@ -949,7 +951,9 @@ class Class:
         'date' is a Timestamp object specifying the time of the change and
         'tag' is the journaltag specified when the database was opened.
         """
-        raise NotImplementedError
+        if not self.do_journal:
+            raise ValueError('Journalling is disabled for this class')
+        return self.db.getjournal(self.classname, nodeid)
 
     # Locating nodes:
     def hasnode(self, nodeid):
@@ -1307,9 +1311,7 @@ class Class:
                     elif isinstance(prop, Interval):
                         value = date.Interval(value)
                     elif isinstance(prop, Password):
-                        pwd = password.Password()
-                        pwd.unpack(value)
-                        value = pwd
+                        value = password.JournalPassword(encrypted=value)
                     params[propname] = value
             elif action == 'create' and params:
                 # old tracker with data stored in the create!
@@ -1337,7 +1339,7 @@ class Class:
 
     def has_role(self, nodeid, *roles):
         '''See if this node has any roles that appear in roles.
-           
+
            For convenience reasons we take a list.
            In standard schemas only a user has a roles property but
            this may be different in customized schemas.