Beispiel #1
0
    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)
Beispiel #2
0
    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.')
Beispiel #3
0
 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()
Beispiel #4
0
    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)
Beispiel #5
0
    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.')
Beispiel #6
0
    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)
Beispiel #7
0
    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)
Beispiel #8
0
    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)
Beispiel #9
0
    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.')
Beispiel #10
0
    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.')