예제 #1
0
    def lift_embargo(self, identity, _id, uow=None):
        """Lifts embargo from the record and draft (if exists).

        It's an error if you try to lift an embargo that has not yet expired.
        Use this method in combination with scan_expired_embargos().
        """
        # Get the record
        record = self.record_cls.pid.resolve(_id)

        # Check permissions
        self.require_permission(identity, "lift_embargo", record=record)

        # Modify draft embargo if draft exists and it's the same as the record.
        draft = None
        if record.has_draft:
            draft = self.draft_cls.pid.resolve(_id, registered_only=False)
            if record.access == draft.access:
                if not draft.access.lift_embargo():
                    raise EmbargoNotLiftedError(_id)
                uow.register(RecordCommitOp(draft, indexer=self.indexer))

        if not record.access.lift_embargo():
            raise EmbargoNotLiftedError(_id)

        uow.register(RecordCommitOp(record, indexer=self.indexer))
예제 #2
0
    def delete(
        self,
        identity,
        id_,
        link_id,
        links_config=None,
        uow=None
    ):
        """Delete a secret link for a record (resp. its parent)."""
        record, parent = self.get_parent_and_record_or_draft(id_)

        # Permissions
        self.require_permission(identity, "manage", record=record)

        # Fetching
        link_ids = [link.link_id for link in parent.access.links]
        if str(link_id) not in link_ids:
            raise LookupError(str(link_id))

        link_idx = link_ids.index(link_id)
        link = parent.access.links[link_idx].resolve()

        # Deletion
        parent.access.links.pop(link_idx)
        link.revoke()

        # Commit
        uow.register(RecordCommitOp(parent))
        if record:
            uow.register(RecordCommitOp(record))

        # Index all child records of the parent
        self._index_related_records(record, parent, uow=uow)

        return True
예제 #3
0
    def update(
        self,
        identity,
        id_,
        link_id,
        data,
        links_config=None,
        uow=None,
    ):
        """Update a secret link for a record (resp. its parent)."""
        record, parent = self.get_parent_and_record_or_draft(id_)

        # Permissions
        self.require_permission(identity, "manage", record=record)

        # Fetching (required for parts of the validation)
        link_ids = [link.link_id for link in parent.access.links]
        if str(link_id) not in link_ids:
            raise LookupError(str(link_id))

        link_idx = link_ids.index(link_id)
        link = parent.access.links[link_idx].resolve()

        # Validation
        data, __ = self.schema_secret_link.load(
            data, context=dict(identity=identity), raise_errors=True
        )
        permission = data.get("permission")
        expires_at = self._validate_secret_link_expires_at(
            data.get("expires_at"),
            is_specified=("expires_at" in data),
            secret_link=link,
        )

        # Update
        # we can't update the link's extra data, as that is encoded
        # in the token and would thus require a new token
        link.expires_at = expires_at or link.expires_at
        link.permission_level = permission or link.permission_level

        # Commit
        uow.register(RecordCommitOp(parent))
        if record:
            uow.register(RecordCommitOp(record))

        # Index all child records of the parent
        self._index_related_records(record, parent, uow=uow)

        return self.link_result_item(
            self,
            identity,
            link,
            links_config=links_config,
        )
예제 #4
0
    def create(
        self,
        identity,
        id_,
        data,
        links_config=None,
        uow=None
    ):
        """Create a secret link for a record (resp. its parent)."""
        record, parent = self.get_parent_and_record_or_draft(id_)

        # Permissions
        self.require_permission(identity, "manage", record=record)

        # Validation
        data, __ = self.schema_secret_link.load(
            data, context=dict(identity=identity), raise_errors=True
        )
        expires_at = self._validate_secret_link_expires_at(
            data.get("expires_at")
        )
        if "permission" not in data:
            raise ValidationError(
                _("An access permission level is required"),
                field_name="permission",
            )

        # Creation
        try:
            link = parent.access.links.create(
                permission_level=data["permission"],
                expires_at=expires_at,
                extra_data=data.get("extra_data", {}),
            )
        except InvalidPermissionLevelError:
            raise ValidationError(
                _("Invalid access permission level."),
                field_name="permission",
            )

        # Commit
        uow.register(RecordCommitOp(parent))
        if record:
            uow.register(RecordCommitOp(record))

        # Index all child records of the parent
        self._index_related_records(record, parent, uow=uow)

        return self.link_result_item(
            self,
            identity,
            link,
            links_config=links_config,
        )
예제 #5
0
    def delete(self, identity, id_, revision_id=None, uow=None):
        """Delete a review."""
        draft = self.draft_cls.pid.resolve(id_, registered_only=False)
        self.require_permission(identity, 'update_draft', record=draft)

        # Preconditions
        if draft.parent.review is None:
            raise ReviewNotFoundError()

        if draft.is_published:
            raise ReviewStateError(
                _("You cannot delete a review for a draft that has already "
                  "been published.")
            )

        if draft.parent.review.is_open:
            raise ReviewStateError(_("An open review cannot be deleted."))

        # Keep the request when not open or not closed so that the user can see
        # the request's events. The request is deleted only when in `draft`
        # status
        if not (draft.parent.review.is_closed or draft.parent.review.is_open):
            current_requests_service.delete(
                identity,
                draft.parent.review.id,
                uow=uow
            )
        # Unset on record
        draft.parent.review = None
        uow.register(RecordCommitOp(draft.parent))
        uow.register(RecordIndexOp(draft, indexer=self.indexer))
        return True
예제 #6
0
    def execute(self, identity, uow):
        """Accept record into community."""
        # Resolve the topic and community - the request type only allow for
        # community receivers and record topics.
        draft = self.request.topic.resolve()
        community = self.request.receiver.resolve()
        service._validate_draft(identity, draft)

        # Unset review from record (still accessible from request)
        # The curator (receiver) should still have access, via the community
        # The creator (uploader) should also still have access, because
        # they're the uploader
        draft.parent.review = None

        # TODO:
        # - Put below into a service method
        # - Check permissions

        # Add community to record.
        is_default = self.request.type.set_as_default
        draft.parent.communities.add(community,
                                     request=self.request,
                                     default=is_default)
        uow.register(RecordCommitOp(draft.parent))

        # Publish the record
        # TODO: Ensure that the accpeting user has permissions to publish.
        service.publish(identity, draft.pid.pid_value, uow=uow)
        super().execute(identity, uow)
예제 #7
0
    def create(self, identity, data, record, uow=None):
        """Create a new review request in draft state (to be completed."""
        if record.parent.review is not None:
            raise ReviewExistsError(
                _('A review already exists for this record'))
        # Validate that record has not been published.
        if record.is_published or record.versions.index > 1:
            raise ReviewStateError(
                _("You cannot create a review for an already published "
                  "record."))

        # Validate the review type (only review requests are valid)
        type_ = current_request_type_registry.lookup(data.pop('type', None),
                                                     quiet=True)
        if type_ is None or type_.type_id not in self.supported_types:
            raise ValidationError(_('Invalid review type.'), field_name='type')

        # Resolve receiver
        receiver = ResolverRegistry.resolve_entity_proxy(
            data.pop('receiver', None)).resolve()

        # Delegate to requests service to create the request
        request_item = current_requests_service.create(
            identity,
            data,
            type_,
            receiver,
            topic=record,
            uow=uow,
        )

        # Set the request on the record and commit the record
        record.parent.review = request_item._request
        uow.register(RecordCommitOp(record.parent))
        return request_item
예제 #8
0
 def execute(self, identity, uow):
     """Execute action."""
     # Remove draft from request
     # Same reasoning as in 'decline'
     draft = self.request.topic.resolve()
     draft.parent.review = None
     uow.register(RecordCommitOp(draft.parent))
     super().execute(identity, uow)
예제 #9
0
    def execute(self, identity, uow):
        """Execute action."""
        # Same reasoning as in 'decline'
        draft = self.request.topic.resolve()

        # TODO: What more to do? simply close the request? Similarly to
        # decline, how does a user resubmits the request to the same community.
        super().execute(identity, uow)

        # TODO: this shouldn't be required BUT because of the caching mechanism
        # in the review systemfield, the review should be set with the updated
        # request object
        draft.parent.review = self.request
        uow.register(RecordCommitOp(draft.parent))
예제 #10
0
    def execute(self, identity, uow):
        """Execute action."""
        # Keeps the record and the review connected so the user can see the
        # outcome of the request
        # The receiver (curator) won't have access anymore to the draft
        # The creator (uploader) should still have access to the record/draft
        draft = self.request.topic.resolve()
        super().execute(identity, uow)

        # TODO: this shouldn't be required BUT because of the caching mechanism
        # in the review systemfield, the review should be set with the updated
        # request object
        draft.parent.review = self.request
        uow.register(RecordCommitOp(draft.parent))
예제 #11
0
    def create(self, identity, id_, scheme, provider=None, uow=None):
        """Create a `NEW` PID for a given record."""
        draft = self.draft_cls.pid.resolve(id_, registered_only=False)
        self.require_permission(identity, "pid_create", record=draft)
        draft.pids[scheme] = self._manager.create(draft,
                                                  scheme,
                                                  provider_name=provider)

        uow.register(RecordCommitOp(draft, indexer=self.indexer))

        return self.result_item(
            self,
            identity,
            draft,
            links_tpl=self.links_item_tpl,
        )
예제 #12
0
    def submit(self, identity, id_, data=None, revision_id=None, uow=None):
        """Submit record for review."""
        # Get record and check permission
        draft = self.draft_cls.pid.resolve(id_, registered_only=False)
        self.require_permission(identity, 'update_draft', record=draft)

        # Preconditions
        if draft.parent.review is None:
            raise ReviewNotFoundError()

        # All other preconditions can be checked by the action itself which can
        # raise appropriate exceptions.
        request_item = current_requests_service.execute_action(
            identity, draft.parent.review.id, 'submit', data=data, uow=uow)

        # TODO: this shouldn't be required BUT because of the caching mechanism
        # in the review systemfield, the review should be set with the updated
        # request object
        draft.parent.review = request_item._request
        uow.register(RecordCommitOp(draft.parent))

        return request_item
예제 #13
0
    def discard(self, identity, id_, scheme, provider=None, uow=None):
        """Discard a PID for a given draft.

        If the status was `NEW` it will be hard deleted. Otherwise,
        it will be soft deleted (`RESERVED`/`REGISTERED`).
        """
        draft = self.draft_cls.pid.resolve(id_, registered_only=False)
        self.require_permission(identity,
                                "pid_discard",
                                record=draft,
                                scheme=scheme)
        self.pid_manager.validate(draft.pids, draft, raise_errors=True)
        identifier = draft.pids.get(scheme, {}).get("identifier")
        self._manager.discard(scheme, identifier, provider)
        draft.pids.pop(scheme)

        uow.register(RecordCommitOp(draft, indexer=self.indexer))

        return self.result_item(
            self,
            identity,
            draft,
            links_tpl=self.links_item_tpl,
        )