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 porcupine.serverExceptions.DBItemNotFound: If the original location no longer exists. """ trans.actions.append( (self.restore, (trans, )) ) try: ## TODO: check if oDeleted exists oDeleted = db.getDeletedItem(self._deletedId, trans) oOriginalParent = db.getItem(oDeleted._parentid, trans) # try to restore original item self._restore(oDeleted, oOriginalParent, trans) self.delete(trans, False) # update container oOriginalParent._addItemReference(oDeleted) db.putItem(oOriginalParent, trans) except serverExceptions.DBTransactionIncomplete: trans.retry()
def delete(self, trans): """ Deletes the item permanently. @param trans: A valid transaction handle @return: None """ trans.actions.append( (self.delete, (trans, ))) try: oUser = currentThread().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 serverExceptions.PermissionDenied except serverExceptions.DBTransactionIncomplete: trans.retry()
def on_update(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 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 """ trans.actions.append( (self.restoreTo, (sParentId, trans)) ) try: ## TODO: check if oDeleted exists oDeleted = db.getDeletedItem(self._deletedId, trans) oParent = db.getItem(sParentId, trans) if not(oDeleted.getContentclass() in oParent.containment): raise serverExceptions.ContainmentError # try to restore original item self._restore(oDeleted, oParent, trans) self.delete(trans, False) # update container oParent._addItemReference(oDeleted) db.putItem(oParent, trans) except serverExceptions.DBTransactionIncomplete: trans.retry()
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 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 """ trans.actions.append( (self.appendTo, (parent, trans)) ) try: if type(parent)==str: oParent = db.getItem(parent, trans) else: oParent = parent oUser = currentThread().session.user iUserRole = objectAccess.getAccess(oParent, oUser) if iUserRole == objectAccess.READER: raise serverExceptions.PermissionDenied if not(self.getContentclass() in oParent.containment): raise serverExceptions.ContainmentError # 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 serverExceptions.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) except serverExceptions.DBTransactionIncomplete: trans.retry()
def on_delete(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: CompositionEventHandler.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_delete(item, attr, trans, bPermanent): if not item._isDeleted: from porcupine import datatypes if attr.value: if attr.respectsReferences: raise serverExceptions.ReferentialIntegrityError # 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 on_update(item, new_attr, old_attr, trans): from porcupine import datatypes # remove duplicates new_attr.value = list(sets.Set(new_attr.value)) # get previous value if old_attr: prvValue = sets.Set(old_attr.value) noAccessList = RelatorNEventHandler.getNoAccessIds(old_attr, trans) else: prvValue = sets.Set() noAccessList = [] # get current value currentValue = sets.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 update(self, trans): """ Updates the item. @param trans: A valid transaction handle @return: None """ trans.actions.append( (self.update, (trans, )) ) try: oOldItem = db.getItem(self._id, trans) oUser = currentThread().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 serverExceptions.PermissionDenied except serverExceptions.DBTransactionIncomplete: trans.retry()
def on_update(item, new_attr, old_attr, trans): # check containment if [obj for obj in new_attr.value if obj.getContentclass() != new_attr.compositeClass]: raise serverExceptions.ContainmentError dctObjects = {} for obj in new_attr.value: obj._containerid = item._id dctObjects[obj._id] = obj new_ids = sets.Set([obj._id for obj in new_attr.value]) # get previous value if old_attr: old_ids = sets.Set(old_attr.value) else: old_ids = sets.Set() # calculate added composites lstAdded = list(new_ids - old_ids) for sID in lstAdded: db.handle_update(dctObjects[sID], None, trans) dctObjects[sID]._isDeleted = False db.putItem(dctObjects[sID], trans) # calculate constant composites lstConstant = list(new_ids & old_ids) for sID in lstConstant: db.handle_update(dctObjects[sID], db.getItem(sID, trans) , trans) db.putItem(dctObjects[sID], trans) # calculate removed composites lstRemoved = list(old_ids - new_ids) for sID in lstRemoved: composite4removal = db.getItem(sID, trans) CompositionEventHandler.removeComposite(composite4removal, trans) new_attr.value = list(new_ids)
def on_delete(item, attr, trans, bPermanent): if not item._isDeleted: from porcupine import datatypes lstValue = attr.value if lstValue and attr.respectsReferences: raise serverExceptions.ReferentialIntegrityError # 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 _copy(self, target, trans, clearRolesInherited=False): oCopy = self.clone() if clearRolesInherited: oCopy.inheritRoles = False oUser = currentThread().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 """ trans.actions.append( (self.recycle, (rbID, trans)) ) try: oUser = currentThread().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 serverExceptions.ContainmentError oRecycleBin._addItemReference(oDeleted) db.putItem(oRecycleBin, trans) else: raise serverExceptions.PermissionDenied except serverExceptions.DBTransactionIncomplete: trans.retry()
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 """ trans.actions.append( (self.moveTo, (targetId, trans)) ) try: oUser = currentThread().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): raise serverExceptions.TargetContainedInSource if (not(self._isSystem) and bCanMove and iUserRole2 > objectAccess.READER): if not(self.getContentclass() in oTarget.containment): raise serverExceptions.ContainmentError 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 serverExceptions.PermissionDenied except serverExceptions.DBTransactionIncomplete: trans.retry()
sys.stdout.write('Creating root folder...') rootFolder = schemas.org.innoscript.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' } rootFolder.security = {'everyone':1, 'administrators':8} db.putItem(rootFolder, None) sys.stdout.write('[OK]\n') sys.stdout.write('Creating recycle bin...') rb = schemas.org.innoscript.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}