def update(self, trans): """ Updates the item. @param trans: A valid transaction handle @return: None """ old_item = _db.get_item(self._id, trans) parent = _db.get_item(self._parentid, trans) user = currentThread().context.user user_role = permsresolver.get_access(old_item, user) if user_role > permsresolver.READER: # set security if user_role == permsresolver.COORDINATOR: # user is COORDINATOR if (self.inheritRoles != old_item.inheritRoles) or \ (not self.inheritRoles and \ self.security != old_item.security): self._applySecurity(parent, trans) else: # restore previous ACL self.security = old_item.security self.inheritRoles = old_item.inheritRoles _db.handle_update(self, old_item, trans) self.modifiedBy = user.displayName.value self.modified = time.time() parent.modified = self.modified _db.put_item(self, trans) _db.put_item(parent, trans) else: raise exceptions.PermissionDenied, \ 'The user does not have update permissions.'
def delete(self, trans): """ Deletes the item permanently. @param trans: A valid transaction handle @return: None """ user = currentThread().context.user self = _db.get_item(self._id, trans) user_role = permsresolver.get_access(self, user) can_delete = (user_role > permsresolver.AUTHOR) or \ (user_role == permsresolver.AUTHOR and self._owner == user._id) if (not(self._isSystem) and can_delete): # delete item physically self._delete(trans) # update container parent = _db.get_item(self._parentid, trans) parent.modified = time.time() _db.put_item(parent, trans) else: raise exceptions.PermissionDenied, \ 'The object was not deleted.\n' + \ 'The user has insufficient permissions.'
def on_update(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.get_item(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 composite_type = misc.get_rto_by_name(new_attr.compositeClass) if [obj for obj in dctObjects.values() if not isinstance(obj, composite_type)]: raise exceptions.ContainmentError, \ 'Invalid content class "%s" in composition.' % \ obj.get_contentclass() # 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) _db.put_item(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.get_item(obj_id, trans), trans) _db.put_item(dctObjects[obj_id], trans) # calculate removed composites lstRemoved = list(old_ids - new_ids) [CompositionEventHandler._removeComposite(_db.get_item(id, trans), trans) for id in lstRemoved] new_attr.value = list(new_ids)
def on_delete(item, attr, trans, bPermanent): if bPermanent: [CompositionEventHandler._removeComposite(_db.get_item(id, trans), trans) for id in attr.value] else: for sID in attr.value: composite = _db.get_item(sID, trans) _db.handle_delete(composite, trans, False) composite._isDeleted = 1 _db.put_item(composite, trans)
def _remove_reference(attr, oid, trans): from porcupine.datatypes import Relator1, RelatorN ref_item = _db.get_item(attr.value, trans) ref_attr = getattr(ref_item, attr.relAttr) if isinstance(ref_attr, RelatorN): try: ref_attr.value.remove(oid) except ValueError: pass elif isinstance(ref_attr, Relator1): ref_attr.value = None ref_attr.validate() _db.put_item(ref_item, trans)
def _applySecurity(self, oParent, trans): if self.inheritRoles: self.security = oParent.security if self.isCollection: cursor = None try: cursor = _db.query_index('_parentid', self._id, trans) cursor.fetch_all = True for child in cursor: child._applySecurity(self, trans) _db.put_item(child, trans) finally: if cursor != None: cursor.close()
def _add_reference(attr, oid, trans): from porcupine.datatypes import Relator1, RelatorN ref_item = _db.get_item(attr.value, trans) if ref_item != None and isinstance(ref_item, tuple([misc.get_rto_by_name(cc) for cc in attr.relCc])): ref_attr = getattr(ref_item, attr.relAttr) if isinstance(ref_attr, RelatorN): ref_attr.value.append(oid) elif isinstance(ref_attr, Relator1): ref_attr.value = oid ref_attr.validate() _db.put_item(ref_item, trans) else: attr.value = None
def _remove_references(attr, ids, oid, trans): # remove references from porcupine.datatypes import Relator1, RelatorN for id in ids: ref_item = _db.get_item(id, trans) ref_attr = getattr(ref_item, attr.relAttr) if isinstance(ref_attr, RelatorN): try: ref_attr.value.remove(oid) except ValueError: pass elif isinstance(ref_attr, Relator1): ref_attr.value = '' ref_attr.validate() _db.put_item(ref_item, trans)
def recycle(self, rb_id, trans): """ Moves the item to the specified recycle bin. The item then becomes inaccessible. @param rb_id: The id of the destination container, which must be a L{RecycleBin} instance @type rb_id: str @param trans: A valid transaction handle @return: None """ user = currentThread().context.user self = _db.get_item(self._id, trans) user_role = permsresolver.get_access(self, user) can_delete = (user_role > permsresolver.AUTHOR) or \ (user_role == permsresolver.AUTHOR and self._owner == user._id) if (not(self._isSystem) and can_delete): deleted = DeletedItem(self, trans) deleted._owner = user._id deleted._created = time.time() deleted.modifiedBy = user.displayName.value deleted.modified = time.time() deleted._parentid = rb_id # check recycle bin's containment recycle_bin = _db.get_item(rb_id, trans) if not(deleted.get_contentclass() in recycle_bin.containment): raise exceptions.ContainmentError, \ 'The target container does not accept ' + \ 'objects of type\n"%s".' % deleted.get_contentclass() _db.handle_update(deleted, None, trans) _db.put_item(deleted, trans) # delete item logically self._recycle(trans) # update container parent = _db.get_item(self._parentid, trans) parent.modified = time.time() _db.put_item(parent, trans) else: raise exceptions.PermissionDenied, \ 'The object was not deleted.\n' + \ 'The user has insufficient permissions.'
def append_to(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: parent = _db.get_item(parent, trans) if isinstance(self, Shortcut): contentclass = self.get_target_contentclass(trans) else: contentclass = self.get_contentclass() user = currentThread().context.user user_role = permsresolver.get_access(parent, user) if user_role == permsresolver.READER: raise exceptions.PermissionDenied, \ 'The user does not have write permissions ' + \ 'on the parent folder.' if not(contentclass in parent.containment): raise exceptions.ContainmentError, \ 'The target container does not accept ' + \ 'objects of type\n"%s".' % contentclass # set security to new item if user_role == permsresolver.COORDINATOR: # user is COORDINATOR self._applySecurity(parent, trans) else: # user is not COORDINATOR self.inheritRoles = True self.security = parent.security self._owner = user._id self._created = time.time() self.modifiedBy = user.displayName.value self.modified = time.time() self._parentid = parent._id _db.handle_update(self, None, trans) parent.modified = self.modified _db.put_item(self, trans) _db.put_item(parent, trans)
def _copy(self, target, trans, clear_inherited=False): clone = self.clone() if clear_inherited: clone.inheritRoles = False user = currentThread().context.user clone._owner = user._id clone._created = time.time() clone.modifiedBy = user.displayName.value clone.modified = time.time() clone._parentid = target._id _db.handle_update(clone, None, trans) _db.put_item(clone, trans) if self.isCollection: [child._copy(clone, trans) for child in self.get_children(trans)]
def copy_to(self, target_id, trans): """ Copies the item to the designated target. @param target_id: The ID of the destination container @type target_id: str @param trans: A valid transaction handle @return: None @raise L{porcupine.exceptions.ObjectNotFound}: If the target container does not exist. """ target = _db.get_item(target_id, trans) if target == None or target._isDeleted: raise exceptions.ObjectNotFound, ( 'The target container "%s" does not exist.' % target_id , False) if isinstance(self, Shortcut): contentclass = self.get_target_contentclass(trans) else: contentclass = self.get_contentclass() if self.isCollection and target.is_contained_in(self._id, trans): raise exceptions.ContainmentError, \ 'Cannot copy item to destination.\n' + \ 'The destination is contained in the source.' # check permissions on target folder user = currentThread().context.user user_role = permsresolver.get_access(target, user) if not(self._isSystem) and user_role > permsresolver.READER: if not(contentclass in target.containment): raise exceptions.ContainmentError, \ 'The target container does not accept ' + \ 'objects of type\n"%s".' % contentclass self._copy(target, trans, clear_inherited=True) # update parent target.modified = time.time() _db.put_item(target, trans) else: raise exceptions.PermissionDenied, \ 'The object was not copied.\n' + \ 'The user has insufficient permissions.'
def restore_to(self, parent_id, trans): """ Restores the deleted object to the specified container. @param parent_id: The ID of the container in which the item will be restored @type parent_id: str @param trans: A valid transaction handle @return: None @raise L{porcupine.exceptions.ObjectNotFound}: If the original location or the original item no longer exists. """ deleted = _db.get_item(self._deletedId, trans) if deleted == None: raise exceptions.ObjectNotFound, ( 'Cannot locate original item.\n' + 'It seems that this item resided in a container\n' + 'that has been permanently deleted or it is shortcut\n' + 'having its target permanently deleted.', False) parent = _db.get_item(parent_id or deleted._parentid, trans) if parent == None or parent._isDeleted: raise exceptions.ObjectNotFound, ( 'Cannot locate target container.\n' + 'It seems that this container is deleted.', False) if isinstance(deleted, Shortcut): contentclass = deleted.get_target_contentclass(trans) else: contentclass = deleted.get_contentclass() if contentclass and not(contentclass in parent.containment): raise exceptions.ContainmentError, \ 'The target container does not accept ' + \ 'objects of type\n"%s".' % contentclass # try to restore original item self._restore(deleted, parent, trans) # update parent parent.modified = time.time() _db.put_item(parent, trans) # delete self self.delete(trans, _removeDeleted=False)
def move_to(self, target_id, trans): """ Moves the item to the designated target. @param target_id: The ID of the destination container @type target_id: str @param trans: A valid transaction handle @return: None @raise L{porcupine.exceptions.ObjectNotFound}: If the target container does not exist. """ user = currentThread().context.user user_role = permsresolver.get_access(self, user) can_move = (user_role > permsresolver.AUTHOR) ## or (user_role == permsresolver.AUTHOR and oItem.owner == user.id) parent_id = self._parentid target = _db.get_item(target_id, trans) if target == None or target._isDeleted: raise exceptions.ObjectNotFound, ( 'The target container "%s" does not exist.' % target_id , False) if isinstance(self, Shortcut): contentclass = self.get_target_contentclass(trans) else: contentclass = self.get_contentclass() user_role2 = permsresolver.get_access(target, user) if self.isCollection and target.is_contained_in(self._id, trans): raise exceptions.ContainmentError, \ 'Cannot move item to destination.\n' + \ 'The destination is contained in the source.' if (not(self._isSystem) and can_move and user_role2 > permsresolver.READER): if not(contentclass in target.containment): raise exceptions.ContainmentError, \ 'The target container does not accept ' + \ 'objects of type\n"%s".' % contentclass self._parentid = target._id self.inheritRoles = False self.modified = time.time() _db.check_unique(self, None, trans) _db.put_item(self, trans) # update target target.modified = time.time() _db.put_item(target, trans) # update parent parent = _db.get_item(parent_id, trans) parent.modified = time.time() _db.put_item(parent, trans) else: raise exceptions.PermissionDenied, \ 'The object was not moved.\n' + \ 'The user has insufficient permissions.'
def _undelete(self, trans): """ Undeletes a logically deleted item. Bypasses security checks. @return: None """ if int(self._isDeleted) == 1: _db.handle_undelete(self, trans) self._isDeleted = int(self._isDeleted) - 1 if self.isCollection: cursor = None try: cursor = _db.query_index('_parentid', self._id, trans) cursor.fetch_all = True [child._undelete(trans) for child in cursor] finally: if cursor != None: cursor.close() _db.put_item(self, trans)
def _recycle(self, trans): """ Deletes an item logically. Bypasses security checks. @return: None """ if not self._isDeleted: _db.handle_delete(self, trans, False) self._isDeleted = int(self._isDeleted) + 1 if self.isCollection: cursor = None try: cursor = _db.query_index('_parentid', self._id, trans) cursor.fetch_all = True [child._recycle(trans) for child in cursor] finally: if cursor != None: cursor.close() _db.put_item(self, trans)