def on_delete(cls, item, attr, trans, bPermanent):
        if not item._isDeleted:
            from porcupine import datatypes

            lstValue = attr.value
            if lstValue and attr.respectsReferences:
                raise exceptions.ReferentialIntegrityError, (
                    'Cannot delete object "%s" ' % item.displayName.value +
                    'because it is being referenced by other objects.')
            
            # remove references
            for sID in lstValue:
                oItemRef = _db.getItem(sID, trans)
                if oItemRef.getContentclass() in attr.relCc:
                    oAttrRef = getattr(oItemRef, attr.relAttr)
                    if isinstance(oAttrRef, datatypes.RelatorN):
                        try:
                            oAttrRef.value.remove(item._id)
                        except ValueError:
                            pass
                    elif isinstance(oAttrRef, datatypes.Relator1):
                        oAttrRef.value = ''
                    _db.putItem(oItemRef, trans)
                else:
                    attr.value.remove(sID)
 def on_update(cls, item, new_attr, old_attr, trans):
     from porcupine import datatypes
     
     # get previous value
     if old_attr:
         prvValue = old_attr.value
     else:
         prvValue = ''
     
     if new_attr.value != prvValue:
         if new_attr.value:
             oItemRef = _db.getItem(new_attr.value, trans)
             if oItemRef.getContentclass() in new_attr.relCc:
                 oAttrRef = getattr(oItemRef, new_attr.relAttr)
                 if isinstance(oAttrRef, datatypes.RelatorN):
                     oAttrRef.value.append(item._id)
                 elif isinstance(oAttrRef, datatypes.Relator1):
                     oAttrRef.value = item._id
                 _db.putItem(oItemRef, trans)
             else:
                 new_attr.value = ''
         if prvValue:
             oItemRef = _db.getItem(prvValue, trans)
             oAttrRef = getattr(oItemRef, new_attr.relAttr)
             if isinstance(oAttrRef, datatypes.RelatorN):
                 try:
                     oAttrRef.value.remove(item._id)
                 except ValueError:
                     pass
             elif isinstance(oAttrRef, datatypes.Relator1):
                 oAttrRef.value = ''
             _db.putItem(oItemRef, trans)
    def delete(self, trans):
        """
        Deletes the item permanently.
        
        @param trans: A valid transaction handle 
        
        @return: None
        """
        oUser = currentThread().context.session.user
        self = _db.getItem(self._id, trans)

        iUserRole = objectAccess.getAccess(self, oUser)
        bCanDelete = (iUserRole > objectAccess.AUTHOR) or \
            (iUserRole == objectAccess.AUTHOR and self._owner == oUser._id)
        
        if (not(self._isSystem) and bCanDelete):
            # delete item physically
            self._delete(trans)
            # update container
            oParent = _db.getItem(self._parentid, trans)
            oParent._removeItemReference(self)
            _db.putItem(oParent, trans)
        else:
            raise exceptions.PermissionDenied, \
                'The object was not deleted.\n' + \
                'The user has insufficient permissions.'
 def restoreTo(self, sParentId, trans):
     """
     Restores the deleted object to the specified container.
     
     @param sParentId: The ID of the container in which
         the item will be restored
     @type sParentId: str    
     
     @param trans: A valid transaction handle
         
     @return: None
     """
     ## TODO: check if oDeleted exists
     oDeleted = _db.getDeletedItem(self._deletedId, trans)
     oParent = _db.getItem(sParentId, trans)
     
     if not(oDeleted.getContentclass() in oParent.containment):
         raise exceptions.ContainmentError, \
             'The target container does not accept ' + \
             'objects of type "%s".' % oDeleted.getContentclass()
     
     # try to restore original item
     self._restore(oDeleted, oParent, trans)
     
     self.delete(trans, False)
     
     # update container
     oParent._addItemReference(oDeleted)
     _db.putItem(oParent, trans)
 def _applySecurity(self, oParent, trans):
     if self.inheritRoles:
         self.security = oParent.security
     if self.isCollection:
         for sID in self._subfolders.values() + self._items.values():
             oItem = _db.getItem(sID, trans)
             if oItem.inheritRoles:
                 oItem._applySecurity(self, trans)
                 _db.putItem(oItem, trans)
 def on_update(cls, item, new_attr, old_attr, trans):
     from porcupine.systemObjects import Composite
     # load objects
     dctObjects = {}
     for i, obj in enumerate(new_attr.value):
         if isinstance(obj, Composite):
             obj._containerid = item._id
         elif isinstance(obj, str):
             obj = _db.getItem(obj, trans)
             new_attr.value[i] = obj
         else:
             raise exceptions.ContainmentError, \
                 'Invalid object type "%s" in composition.' % \
                 obj.__class__.__name__
         dctObjects[obj._id] = obj
     
     # check containment
     compositeClass = misc.getCallableByName(new_attr.compositeClass)
     
     if [obj for obj in dctObjects.values()
             if not isinstance(obj, compositeClass)]:
         raise exceptions.ContainmentError, \
             'Invalid content class "%s" in composition.' % \
             obj.getContentclass()
     
     # get previous value
     if old_attr != None:
         old_ids = set(old_attr.value)
     else:
         old_ids = set()
     
     new_ids = set([obj._id for obj in new_attr.value])
     
     # calculate added composites
     lstAdded = list(new_ids - old_ids)
     for obj_id in lstAdded:
         _db.handle_update(dctObjects[obj_id], None, trans)
         dctObjects[obj_id]._isDeleted = False
         _db.putItem(dctObjects[obj_id], trans)
     
     # calculate constant composites
     lstConstant = list(new_ids & old_ids)
     for obj_id in lstConstant:
         _db.handle_update(dctObjects[obj_id],
                              _db.getItem(obj_id, trans),
                              trans)
         _db.putItem(dctObjects[obj_id], trans)
     
     # calculate removed composites
     lstRemoved = list(old_ids - new_ids)
     for obj_id in lstRemoved:
         composite4removal = _db.getItem(obj_id, trans)
         cls.removeComposite(composite4removal, trans)
     
     new_attr.value = list(new_ids)
 def on_create(item, attr, trans):
     if item._isDeleted and attr.cascadeDelete and attr.value:
         from porcupine.systemObjects import DeletedItem
         oItemRef = _db.getDeletedItem(attr.value, trans)
         parent = _db.getItem(oItemRef._parentid, trans)
         # update container
         parent._addItemReference(oItemRef)
         _db.putItem(parent, trans)
         deletedItem = DeletedItem(oItemRef, trans)
         deletedItem._undelete(oItemRef, trans)
     Relator1EventHandler.on_update(item, attr, None, trans)
    def appendTo(self, parent, trans):
        """
        Adds the item to the specified container.

        @param parent: The id of the destination container or the container
            itself
        @type parent: str OR L{Container}
        
        @param trans: A valid transaction handle
        
        @return: None
        """
        if type(parent) == str:
            oParent = _db.getItem(parent, trans)
        else:
            oParent = parent
        
        if isinstance(self, Shortcut):
            contentclass = self.target.getItem(trans).getContentclass()
        else:
            contentclass = self.contentclass
        
        oUser = currentThread().context.user
        iUserRole = objectAccess.getAccess(oParent, oUser)
        if iUserRole == objectAccess.READER:
            raise exceptions.PermissionDenied, \
                'The user does not have write permissions ' + \
                'on the parent folder.'
        if not(contentclass in oParent.containment):
            raise exceptions.ContainmentError, \
                'The target container does not accept ' + \
                'objects of type "%s".' % contentclass

        # set security to new item
        if iUserRole == objectAccess.COORDINATOR:
            # user is COORDINATOR
            self._applySecurity(oParent, trans)
        else:
            # user is not COORDINATOR
            self.inheritRoles = True
            self.security = oParent.security
            #if trans._retries == 0:
            #   raise exceptions.DBTransactionIncomplete    
        self._owner = oUser._id
        self._created = time.time()
        self.modifiedBy = oUser.displayName.value
        self.modified = time.time()
        self._parentid = oParent._id
        _db.handle_update(self, None, trans)
        _db.putItem(self, trans)
        # update container
        oParent._addItemReference(self)
        _db.putItem(oParent, trans)
    def on_update(item, new_attr, old_attr, trans):
        from porcupine import datatypes
        # remove duplicates
        new_attr.value = list(set(new_attr.value))
        
        # get previous value
        if old_attr:
            prvValue = set(old_attr.value)
            noAccessList = RelatorNEventHandler.getNoAccessIds(old_attr, trans)
        else:
            prvValue = set()
            noAccessList = []

        # get current value
        currentValue = set(new_attr.value + noAccessList)

        if currentValue != prvValue:
            # calculate added references
            lstAdded = list(currentValue - prvValue)
            for sID in lstAdded:
                try:
                    ref_item = _db.getItem(sID, trans)
                except exceptions.ObjectNotFound:
                    ref_item = None
                if ref_item != None and \
                        (not new_attr.relCc or
                        ref_item.getContentclass() in new_attr.relCc):
                    oAttrRef = getattr(ref_item, new_attr.relAttr)
                    if isinstance(oAttrRef, datatypes.RelatorN):
                        oAttrRef.value.append(item._id)
                    elif isinstance(oAttrRef, datatypes.Relator1):
                        oAttrRef.value = item._id
                    _db.putItem(ref_item, trans)
                else:
                    new_attr.value.remove(sID)
    
            # calculate removed references
            lstRemoved = list(prvValue - currentValue)
            for sID in lstRemoved:
                ref_item = _db.getItem(sID, trans)
                oAttrRef = getattr(ref_item, new_attr.relAttr)
                if isinstance(oAttrRef, datatypes.RelatorN):
                    try:
                        oAttrRef.value.remove(item._id)
                    except ValueError:
                        pass
                elif isinstance(oAttrRef, datatypes.Relator1):
                    oAttrRef.value = ''
                _db.putItem(ref_item, trans)
 def on_delete(cls, item, attr, trans, bPermanent):
     if bPermanent:
         if item._isDeleted:
             func_get = _db.getDeletedItem
         else:
             func_get = _db.getItem
         composites = [func_get(sID, trans) for sID in attr.value]
         for composite in composites:
             cls.removeComposite(composite, trans)
     else:
         for sID in attr.value:
             composite = _db.getItem(sID, trans)
             _db.handle_delete(composite, trans, False)
             composite._isDeleted = True
             _db.putItem(composite, trans)
    def _undelete(self, deletedItem, trans):
        """
        Undeletes a logically deleted item.
        
        Returns: None
        """
        _db.handle_update(deletedItem, None, trans)
        deletedItem._isDeleted = False
        
        if deletedItem.isCollection:
            lstChildren = deletedItem._items.values() + deletedItem._subfolders.values()
            for sID in lstChildren:
                oChild = _db.getDeletedItem(sID, trans)
                self._undelete(oChild, trans)

        _db.putItem(deletedItem, trans)
 def _recycle(self, trans):
     """
     Removes an item's references and marks it as deleted.
     
     Returns: None
     """
     _db.handle_delete(self, trans, False)
     self._isDeleted = True
     
     if self.isCollection:
         lstChildren = self._items.values() + self._subfolders.values()
         for sID in lstChildren:
             oChild = _db.getItem(sID, trans)
             oChild._recycle(trans)
     
     _db.putItem(self, trans)
    def on_update(cls, item, new_attr, old_attr, trans):
        from porcupine import datatypes
        # remove duplicates
        new_attr.value = list(set(new_attr.value))
        
        # get previous value
        if old_attr:
            prvValue = set(old_attr.value)
            noAccessList = cls.getNoAccessIds(old_attr, trans)
        else:
            prvValue = set()
            noAccessList = []

        # get current value
        currentValue = set(new_attr.value + noAccessList)

        if currentValue != prvValue:
            # calculate added references
            lstAdded = list(currentValue - prvValue)
            for sID in lstAdded:
                oItemRef = _db.getItem(sID, trans)
                if oItemRef.getContentclass() in new_attr.relCc:
                    oAttrRef = getattr(oItemRef, new_attr.relAttr)
                    if isinstance(oAttrRef, datatypes.RelatorN):
                        oAttrRef.value.append(item._id)
                    elif isinstance(oAttrRef, datatypes.Relator1):
                        oAttrRef.value = item._id
                    _db.putItem(oItemRef, trans)
                else:
                    new_attr.value.remove(sID)
    
            # calculate removed references
            lstRemoved = list(prvValue - currentValue)
            for sID in lstRemoved:
                oItemRef = _db.getItem(sID, trans)
                oAttrRef = getattr(oItemRef, new_attr.relAttr)
                if isinstance(oAttrRef, datatypes.RelatorN):
                    try:
                        oAttrRef.value.remove(item._id)
                    except ValueError:
                        pass
                elif isinstance(oAttrRef, datatypes.Relator1):
                    oAttrRef.value = ''
                _db.putItem(oItemRef, trans)
 def on_delete(item, attr, trans, bPermanent):
     lstValue = attr.value
     if not item._isDeleted:
         from porcupine import datatypes
         
         if lstValue and attr.respectsReferences:
             raise exceptions.ReferentialIntegrityError, (
                 'Cannot delete object "%s" ' % item.displayName.value +
                 'because it is being referenced by other objects.')
         
         # remove references
         for sID in lstValue:
             ref_item = _db.getItem(sID, trans)
             if ref_item.getContentclass() in attr.relCc:
                 oAttrRef = getattr(ref_item, attr.relAttr)
                 if isinstance(oAttrRef, datatypes.RelatorN):
                     try:
                         oAttrRef.value.remove(item._id)
                     except ValueError:
                         pass
                 elif isinstance(oAttrRef, datatypes.Relator1):
                     oAttrRef.value = ''
                 _db.putItem(ref_item, trans)
             else:
                 attr.value.remove(sID)
         
             if attr.cascadeDelete:
                 oParent = _db.getItem(oItemRef._parentid, trans)
                 try:
                     oParent._removeItemReference(oItemRef)
                     _db.putItem(oParent, trans)
                 except KeyError:
                     pass
     
     if attr.cascadeDelete:
         for sID in lstValue:
             if item._isDeleted:
                 oItemRef = _db.getDeletedItem(sID, trans)
             else:
                 oItemRef = _db.getItem(sID, trans)
             if bPermanent:
                 oItemRef._delete(trans)
             else:
                 oItemRef._recycle(trans)
 def on_delete(cls, item, attr, trans, bPermanent):
     if not item._isDeleted:
         from porcupine import datatypes
         if attr.value:
             if attr.respectsReferences:
                 raise exceptions.ReferentialIntegrityError, (
                     'Cannot delete object "%s" ' % item.displayName.value +
                     'because it is referenced by other objects.')
             # remove reference
             oItemRef = _db.getItem(attr.value, trans)
             oAttrRef = getattr(oItemRef, attr.relAttr)
             if isinstance(oAttrRef, datatypes.RelatorN):
                 try:
                     oAttrRef.value.remove(item._id)
                 except ValueError:
                     pass
             elif isinstance(oAttrRef, datatypes.Relator1):
                 oAttrRef.value = ''
             _db.putItem(oItemRef, trans)
    def update(self, trans):
        """
        Updates the item.
        
        @param trans: A valid transaction handle
            
        @return: None
        """
        oOldItem = _db.getItem(self._id, trans)
        
        oUser = currentThread().context.session.user
        iUserRole = objectAccess.getAccess(oOldItem, oUser)
        
        if iUserRole > objectAccess.READER:
            # set security
            if iUserRole == objectAccess.COORDINATOR:
                # user is COORDINATOR
                if (self.inheritRoles != oOldItem.inheritRoles) or \
                (not self.inheritRoles and self.security != oOldItem.security):
                    oParent = _db.getItem(self._parentid, trans)
                    self._applySecurity(oParent, trans)
            else:
                # restore previous ACL
                self.security = oOldItem.security
                self.inheritRoles = oOldItem.inheritRoles

            _db.handle_update(self, oOldItem, trans)
            self.modifiedBy = oUser.displayName.value
            self.modified = time.time()
            _db.putItem(self, trans)
            
            if self.displayName.value != oOldItem.displayName.value:
                oParent = _db.getItem(self._parentid, trans)
                oParent._removeItemReference(oOldItem)
                oParent._addItemReference(self)
                _db.putItem(oParent, trans)
        else:
            raise exceptions.PermissionDenied, \
                    'The user does not have update permissions.'
    def restore(self, trans):
        """
        Restores the deleted item to its original location, if
        it still exists.
        
        @param trans: A valid transaction handle
        
        @return: None
        
        @raise L{porcupine.exceptions.ObjectNotFound}:
            If the original location no longer exists.
        """
        ## TODO: check if oDeleted exists
        oDeleted = _db.getDeletedItem(self._deletedId, trans)
        oOriginalParent = _db.getItem(oDeleted._parentid, trans)
        # update container
        oOriginalParent._addItemReference(oDeleted)
        _db.putItem(oOriginalParent, trans)
        
        # try to restore original item
        self._restore(oDeleted, oOriginalParent, trans)

        self.delete(trans, False)
 def on_update(item, new_attr, old_attr, trans):
     from porcupine import datatypes, systemObjects
     
     # get previous value
     if old_attr:
         prvValue = old_attr.value
     else:
         prvValue = ''
     
     if new_attr.value != prvValue:
         if new_attr.value:
             try:
                 ref_item = _db.getItem(new_attr.value, trans)
             except exceptions.ObjectNotFound:
                 ref_item = None
             if ref_item != None and \
                     (not new_attr.relCc or
                     ref_item.getContentclass() in new_attr.relCc):
                 oAttrRef = getattr(ref_item, new_attr.relAttr)
                 if isinstance(oAttrRef, datatypes.RelatorN):
                     oAttrRef.value.append(item._id)
                 elif isinstance(oAttrRef, datatypes.Relator1):
                     oAttrRef.value = item._id
                 _db.putItem(ref_item, trans)
             else:
                 new_attr.value = ''
         if prvValue:
             ref_item = _db.getItem(prvValue, trans)
             oAttrRef = getattr(ref_item, new_attr.relAttr)
             if isinstance(oAttrRef, datatypes.RelatorN):
                 try:
                     oAttrRef.value.remove(item._id)
                 except ValueError:
                     pass
             elif isinstance(oAttrRef, datatypes.Relator1):
                 oAttrRef.value = ''
             _db.putItem(ref_item, trans)
    def _copy(self, target, trans, clearRolesInherited=False):
        oCopy = self.clone()
        if clearRolesInherited:
            oCopy.inheritRoles = False

        oUser = currentThread().context.session.user
        oCopy._owner = oUser._id
        oCopy._created = time.time()
        oCopy.modifiedBy = oUser.displayName.value
        oCopy.modified = time.time()
        oCopy._parentid = target._id
        
        _db.handle_update(oCopy, None, trans)
        _db.putItem(oCopy, trans)

        if self.isCollection:
            lstChildrentIds = self._items.values() + self._subfolders.values()
            for sId in lstChildrentIds:
                child = _db.getItem(sId, trans)
                if child and objectAccess.getAccess(child, oUser):
                    child._copy(oCopy, trans)

        target._addItemReference(oCopy)
        _db.putItem(target, trans)
 def recycle(self, rbID, trans):
     """
     Moves the item to the specified recycle bin.
     
     The item then becomes inaccesible.
     
     @param rbID: The id of the destination container, which must be
                  a L{RecycleBin} instance
     @type rbID: str
     
     @param trans: A valid transaction handle 
     
     @return: None
     """
     oUser = currentThread().context.session.user
     self = _db.getItem(self._id, trans)
     
     iUserRole = objectAccess.getAccess(self, oUser)
     bCanDelete = (iUserRole > objectAccess.AUTHOR) or \
         (iUserRole == objectAccess.AUTHOR and self._owner == oUser._id)
     
     if (not(self._isSystem) and bCanDelete):
         oDeleted = DeletedItem(self)
         
         oDeleted._owner = oUser._id
         oDeleted._created = time.time()
         oDeleted.modifiedBy = oUser.displayName.value
         oDeleted.modified = time.time()
         oDeleted._parentid = rbID
         _db.handle_update(oDeleted, None, trans)
         _db.putItem(oDeleted, trans)
         
         # delete item logically
         self._recycle(trans)
         
         # save container
         oParent = _db.getItem(self._parentid, trans)
         oParent._removeItemReference(self)
         _db.putItem(oParent, trans)
         
         #update recycle bin
         oRecycleBin = _db.getItem(rbID, trans)
         if not(oDeleted.getContentclass() in oRecycleBin.containment):
             raise exceptions.ContainmentError, \
                 'The target container does not accept ' + \
                 'objects of type "%s".' % oDeleted.getContentclass()
         oRecycleBin._addItemReference(oDeleted)
         _db.putItem(oRecycleBin, trans)
     else:
         raise exceptions.PermissionDenied, \
             'The object was not deleted.\n' + \
             'The user has insufficient permissions.'
    def moveTo(self, targetId, trans):
        """
        Moves the item to the designated target.
        
        @param targetId: The ID of the destination container
        @type targetId: str
        
        @param trans: A valid transaction handle 
            
        @return: None
        """
        oUser = currentThread().context.session.user
        iUserRole = objectAccess.getAccess(self, oUser)
        bCanMove = (iUserRole > objectAccess.AUTHOR)## or (iUserRole == objectAccess.AUTHOR and oItem.owner == oUser.id)

        parentId = self._parentid
        oTarget = _db.getItem(targetId, trans)
    
        iUserRole2 = objectAccess.getAccess(oTarget, oUser)
    
        if self.isCollection and oTarget.isContainedIn(self._id, trans):
            raise exceptions.ContainmentError, \
                'Cannot move item to destination.\n' + \
                'The destination is contained in the source.'
    
        if (not(self._isSystem) and bCanMove and iUserRole2 > objectAccess.READER):
            if not(self.getContentclass() in oTarget.containment):
                raise exceptions.ContainmentError, \
                    'The target container does not accept ' + \
                    'objects of type "%s".' % self.getContentclass()

            self._parentid = targetId
            self.inheritRoles = False
            _db.putItem(self, trans)

            #update target
            oTarget._addItemReference(self)
            _db.putItem(oTarget, trans)

            #update parent
            oParent = _db.getItem(parentId, trans)
            oParent._removeItemReference(self)
            _db.putItem(oParent, trans)
        else:
            raise exceptions.PermissionDenied, \
                'The object was not moved.\n' + \
                'The user has insufficient permissions.'
    rootFolder = org.innoscript.desktop.schema.common.RootFolder()
    rootFolder._id = ''
    rootFolder.description.value = 'Root Folder'
    rootFolder.displayName.value = 'Porcupine Server'
    rootFolder._isSystem = True
    rootFolder._owner = sOwner
    rootFolder.modifiedBy = sOwner
    rootFolder._created = ftime
    rootFolder.modified = ftime
    rootFolder._subfolders = {
        'Categories':'categories',
        'Administrative Tools':'admintools',
        'Personal folders':'personal'
    }
    rootFolder.security = {'everyone':1, 'administrators':8}
    _db.putItem(rootFolder, None)
    sys.stdout.write('[OK]\n')

    sys.stdout.write('Creating recycle bin...')
    rb = org.innoscript.desktop.schema.common.RecycleBin()
    rb._id = 'rb'
    rb.description.value = 'Deleted items container'
    rb.displayName.value = 'Recycle Bin'
    rb._isSystem = True
    rb._owner = sOwner
    rb.modifiedBy = sOwner
    rb._created = ftime
    rb.modified = ftime
    rb.inheritRoles = False
    rb.security = {'administrators':8}
    _db.putItem(rb, None)