def on_update(item, new_attr, old_attr): from porcupine.systemObjects import Composite # load objects dctObjects = {} for i, obj in enumerate(new_attr.value): if isinstance(obj, Composite): obj._pid = ':' + item._id elif isinstance(obj, str): obj = db._db.get_item(obj) 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 is not None: old_ids = set(old_attr.value) else: old_ids = set() new_ids = set([obj._id for obj in new_attr.value]) # calculate removed composites lstRemoved = list(old_ids - new_ids) [ CompositionEventHandler._removeComposite(db._db.get_item(id)) for id in lstRemoved ] # calculate added composites lstAdded = list(new_ids - old_ids) for obj_id in lstAdded: db._db.handle_update(dctObjects[obj_id], None) db._db.put_item(dctObjects[obj_id]) # calculate constant composites lstConstant = list(new_ids & old_ids) for obj_id in lstConstant: db._db.handle_update(dctObjects[obj_id], db._db.get_item(obj_id)) db._db.put_item(dctObjects[obj_id]) new_attr.value = list(new_ids)
def copy_to(self, target): """ Copies the item to the designated target. @param target: The id of the target container or the container object itself @type target: str OR L{Container} @return: None @raise L{porcupine.exceptions.ObjectNotFound}: If the target container does not exist. """ if isinstance(target, (str, bytes)): target = db._db.get_item(target) if target is None or target._isDeleted: raise exceptions.ObjectNotFound( 'The target container does not exist.') contentclass = self.get_contentclass() if self.isCollection and target.is_contained_in(self._id): raise exceptions.ContainmentError( 'Cannot copy item to destination.\n' 'The destination is contained in the source.') # check permissions on target folder user = context.user user_role = permsresolver.get_access(target, user) if not (self._isSystem) and user_role > permsresolver.READER: if contentclass not in target.containment: raise exceptions.ContainmentError( 'The target container does not accept ' 'objects of type\n"%s".' % contentclass) self._copy(target, clear_inherited=True) # update parent if self.isCollection: target._nc += 1 else: target._ni += 1 target.modified = time.time() db._db.put_item(target) else: raise exceptions.PermissionDenied( 'The object was not copied.\n' 'The user has insufficient permissions.')
def update(self): parent = db._db.get_item(self._pid) contentclass = self.get_target_contentclass() if contentclass not in parent.containment: raise exceptions.ContainmentError( 'The parent container does not accept ' 'objects of type\n"%s".' % contentclass) else: return super(Shortcut, self).update()
def move_to(self, target): if isinstance(target, (str, bytes)): target = db._db.get_item(target) contentclass = self.get_target_contentclass() if contentclass not in target.containment: raise exceptions.ContainmentError( 'The target container does not accept ' 'objects of type\n"%s".' % contentclass) else: return super(Shortcut, self).move_to(target)
def append_to(self, *args, **kwargs): """ Calling this method raises an ContainmentError. This is happening because you can not add a DeletedItem directly to the store. This type of item is added in the database only if the L{Removable.recycle} method is called. @warning: DO NOT USE. @raise L{porcupine.exceptions.ContainmentError}: Always """ raise exceptions.ContainmentError( 'Cannot directly add this item to the store.\n' 'Use the "recycle" method instead.')
def append_to(self, parent): """ 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} @return: None """ if isinstance(parent, basestring): parent = db._db.get_item(parent) contentclass = self.get_contentclass() user = 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 contentclass not 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._apply_security(parent, True) 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._pid = parent._id db._db.handle_update(self, None) db._db.put_item(self) if self.isCollection: parent._nc += 1 else: parent._ni += 1 parent.modified = self.modified db._db.put_item(parent) db._db.handle_post_update(self, None)
def restore_to(self, parent_id): """ 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 @return: None @raise L{porcupine.exceptions.ObjectNotFound}: If the original location or the original item no longer exists. """ deleted = db._db.get_item(self._deletedId) if deleted is 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.') parent = db._db.get_item(parent_id or deleted._pid) if parent is None or parent._isDeleted: raise exceptions.ObjectNotFound( 'Cannot locate target container.\n' 'It seems that this container is deleted.') if isinstance(deleted, Shortcut): contentclass = deleted.get_target_contentclass() else: contentclass = deleted.get_contentclass() if contentclass and contentclass not in parent.containment: raise exceptions.ContainmentError( 'The target container does not accept ' 'objects of type\n"%s".' % contentclass) if parent_id is not None and not isinstance(deleted, Shortcut): # restoring to a designated container deleted._isDeleted = 1 if parent_id is not None and parent_id != deleted._pid: # restoring to a another container db._db.delete_item(deleted) deleted.modified = time.time() # try to restore original item self._restore(deleted, parent) # delete self self.delete(_remove_deleted=False)
def append_to(self, parent): """ A lighter append_to """ if isinstance(parent, basestring): parent = db._db.get_item(parent) if not (self.get_contentclass() in parent.containment): raise exceptions.ContainmentError( 'The target container does not accept ' + 'objects of type\n"%s".' % contentclass) self._owner = 'system' self._created = time.time() self.modifiedBy = 'SYSTEM' self.modified = time.time() self._pid = parent._id db._db.put_item(self)
def recycle(self, rb_id): """ 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 @return: None """ user = context.user self_ = db._db.get_item(self._id) 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_) deleted._owner = user._id deleted._created = time.time() deleted.modifiedBy = user.displayName.value deleted.modified = time.time() deleted._pid = rb_id # check recycle bin's containment recycle_bin = db._db.get_item(rb_id) if deleted.get_contentclass() not in recycle_bin.containment: raise exceptions.ContainmentError( 'The target container does not accept ' 'objects of type\n"%s".' % deleted.get_contentclass()) db._db.handle_update(deleted, None) db._db.put_item(deleted) db._db.handle_post_update(deleted, None) # delete item logically self_._recycle() else: raise exceptions.PermissionDenied( 'The object was not deleted.\n' 'The user has insufficient permissions.')
def move_to(self, target): """ Moves the item to the designated target. @param target: The id of the target container or the container object itself @type target: str OR L{Container} @return: None @raise L{porcupine.exceptions.ObjectNotFound}: If the target container does not exist. """ user = 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._pid if isinstance(target, (str, bytes)): target = db._db.get_item(target) if target is None or target._isDeleted: raise exceptions.ObjectNotFound( 'The target container does not exist.') contentclass = self.get_contentclass() user_role2 = permsresolver.get_access(target, user) if self.isCollection and target.is_contained_in(self._id): 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 contentclass not in target.containment: raise exceptions.ContainmentError( 'The target container does not accept ' 'objects of type\n"%s".' % contentclass) db._db.delete_item(self) self._pid = target._id self.inheritRoles = False self.modified = time.time() db._db.put_item(self) # update target if self.isCollection: target._nc += 1 else: target._ni += 1 target.modified = time.time() db._db.put_item(target) # update parent parent = db._db.get_item(parent_id) parent.modified = time.time() db._db.put_item(parent) else: raise exceptions.PermissionDenied( 'The object was not moved.\n' 'The user has insufficient permissions.')