Beispiel #1
0
    def modify(self, request, *args, **kwargs):

        xform = self.get_object()
        http_status = status.HTTP_200_OK
        response = {}

        if request.user.has_perm("validate_xform", xform):

            owner = xform.user
            userform_id = "{}_{}".format(owner.username, xform.id_string)
            query = {ParsedInstance.USERFORM_ID: userform_id}  # Query used for MongoDB
            filter_ = {"xform_id": xform.id}  # Filter for Django ORM
            payload = {}

            try:
                payload = json.loads(request.data.get("payload", "{}"))
            except ValueError:
                http_status = status.HTTP_400_BAD_REQUEST
                response = {"detail": _("Invalid payload")}

            if http_status == status.HTTP_200_OK:

                if request.data.get("reset"):
                    new_validation_status_uid = {}
                else:
                    new_validation_status_uid = payload.get("validation_status.uid")

                if new_validation_status_uid is None:
                    http_status = status.HTTP_400_BAD_REQUEST
                    response = {"detail": _("No validation_status.uid provided")}
                else:
                    # Create new validation_status object
                    new_validation_status = get_validation_status(
                        new_validation_status_uid, xform, request.user.username)

                    # 3 scenarios to update submissions

                    # First scenario / Modify submissions based on user's query
                    if payload.get("query"):
                        # Validate if query is valid.
                        try:
                            query.update(payload.get("query"))
                        except ValueError:
                            raise ParseError(_("Invalid query: %(query)s"
                                               % {'query': json.dumps(payload.get("query"))}))

                        query_kwargs = {
                            "query": json.dumps(query),
                            "fields": '["_id"]'
                        }

                        cursor = ParsedInstance.query_mongo_no_paging(**query_kwargs)
                        submissions_ids = [record.get("_id") for record in list(cursor)]
                        filter_.update({"id__in": submissions_ids})

                    # Second scenario / Modify submissions based on list of ids
                    elif payload.get("submissions_ids"):
                        try:
                            # Use int() to test if list of integers is valid.
                            submissions_ids = payload.get("submissions_ids", [])
                            or_ = {u"$or": [{u"_id": int(submission_id)} for submission_id in submissions_ids]}
                            query.update(or_)
                        except ValueError:
                            raise ParseError(_("Invalid submissions ids: %(submissions_ids)s"
                                               % {'submissions_ids': json.dumps(payload.get("submissions_ids"))}))

                        filter_.update({"id__in": submissions_ids})
                    # Third scenario / Modify all submissions in form, but confirmation param must be among payload
                    elif payload.get("confirm", False) is not True:
                        http_status = status.HTTP_400_BAD_REQUEST
                        response = {"detail": _("No confirmations provided")}

                    # If everything is OK, submit data to DBs
                    if http_status == status.HTTP_200_OK:
                        # Update Postgres & Mongo
                        updated_records_count = Instance.objects.\
                            filter(**filter_).update(validation_status=new_validation_status)
                        ParsedInstance.bulk_update_validation_statuses(query, new_validation_status)
                        response = {"detail": _("{} submissions have been updated").format(updated_records_count)}

            return Response(response, http_status)

        else:
            raise PermissionDenied(_(u"You do not have validate permissions."))
Beispiel #2
0
    def modify(self, request, *args, **kwargs):

        xform = self.get_object()
        http_status = status.HTTP_200_OK
        response = {}

        if request.user.has_perm("validate_xform", xform):

            owner = xform.user
            userform_id = "{}_{}".format(owner.username, xform.id_string)
            query = {ParsedInstance.USERFORM_ID: userform_id}  # Query used for MongoDB
            filter_ = {"xform_id": xform.id}  # Filter for Django ORM
            payload = {}

            try:
                payload = json.loads(request.data.get("payload", "{}"))
            except ValueError:
                http_status = status.HTTP_400_BAD_REQUEST
                response = {"detail": _("Invalid payload")}

            if http_status == status.HTTP_200_OK:

                new_validation_status_uid = payload.get("validation_status.uid")

                if new_validation_status_uid is None:
                    http_status = status.HTTP_400_BAD_REQUEST
                    response = {"detail": _("No validation_status.uid provided")}
                else:
                    # Create new validation_status object
                    new_validation_status = get_validation_status(
                        new_validation_status_uid, xform, request.user.username)

                    # 3 scenarios to update submissions

                    # First scenario / Modify submissions based on user's query
                    if payload.get("query"):
                        # Validate if query is valid.
                        try:
                            query.update(payload.get("query"))
                        except ValueError:
                            raise ParseError(_("Invalid query: %(query)s"
                                               % {'query': json.dumps(payload.get("query"))}))

                        query_kwargs = {
                            "query": json.dumps(query),
                            "fields": '["_id"]'
                        }

                        cursor = ParsedInstance.query_mongo_no_paging(**query_kwargs)
                        submissions_ids = [record.get("_id") for record in list(cursor)]
                        filter_.update({"id__in": submissions_ids})

                    # Second scenario / Modify submissions based on list of ids
                    elif payload.get("submissions_ids"):
                        try:
                            # Use int() to test if list of integers is valid.
                            submissions_ids = payload.get("submissions_ids", [])
                            or_ = {u"$or": [{u"_id": int(submission_id)} for submission_id in submissions_ids]}
                            query.update(or_)
                        except ValueError:
                            raise ParseError(_("Invalid submissions ids: %(submissions_ids)s"
                                               % {'submissions_ids': json.dumps(payload.get("submissions_ids"))}))

                        filter_.update({"id__in": submissions_ids})
                    # Third scenario / Modify all submissions in form, but confirmation param must be among payload
                    elif payload.get("confirm", False) is not True:
                        http_status = status.HTTP_400_BAD_REQUEST
                        response = {"detail": _("No confirmations provided")}

                    # If everything is OK, submit data to DBs
                    if http_status == status.HTTP_200_OK:
                        # Update Postgres & Mongo
                        updated_records_count = Instance.objects.\
                            filter(**filter_).update(validation_status=new_validation_status)
                        ParsedInstance.bulk_update_validation_statuses(query, new_validation_status)
                        response = {"detail": _("{} submissions have been updated").format(updated_records_count)}

            return Response(response, http_status)

        else:
            raise PermissionDenied(_(u"You do not have validate permissions."))
Beispiel #3
0
    def __build_db_queries(xform_, payload):
        """
        Gets instance ids based on the request payload.
        Useful to narrow down set of instances for bulk actions

        Args:
            xform_ (XForm)
            payload (dict)

        Returns:
            tuple(<dict>, <dict>): PostgreSQL filters, Mongo filters.
               They are meant to be used respectively with Django Queryset
               and PyMongo query.

        """

        mongo_query = ParsedInstance.get_base_query(xform_.user.username,
                                                    xform_.id_string)
        postgres_query = {'xform_id': xform_.id}
        instance_ids = None

        ###################################################
        # Submissions can be retrieve in 3 different ways #
        ###################################################
        # First of all, users can't mix `query` and `submission_ids` in `payload`
        if all(key_ in payload for key_ in ('query', 'submission_ids')):
            raise ValidationError({
                'payload':
                _("`query` and `instance_ids` can't be used together")
            })

        # First scenario / Get submissions based on user's query
        try:
            query = payload['query']
        except KeyError:
            pass
        else:
            try:
                query.update(mongo_query)  # Overrides `_userform_id` if exists
            except AttributeError:
                raise ValidationError({
                    'payload': _('Invalid query: %(query)s') % {
                        'query': json.dumps(query)
                    }
                })

            query_kwargs = {'query': json.dumps(query), 'fields': '["_id"]'}

            cursor = ParsedInstance.query_mongo_no_paging(**query_kwargs)
            instance_ids = [record.get('_id') for record in list(cursor)]

        # Second scenario / Get submissions based on list of ids
        try:
            submission_ids = payload['submission_ids']
        except KeyError:
            pass
        else:
            try:
                # Use int() to test if list of integers is valid.
                instance_ids = [
                    int(submission_id) for submission_id in submission_ids
                ]
            except ValueError:
                raise ValidationError({
                    'payload':
                    _('Invalid submission ids: %(submission_ids)s') % {
                        'submission_ids': json.dumps(payload['submission_ids'])
                    }
                })

        if instance_ids is not None:
            # Narrow down queries with list of ids.
            postgres_query.update({'id__in': instance_ids})
            mongo_query.update({'_id': {'$in': instance_ids}})
        elif payload.get('confirm', False) is not True:
            # Third scenario / get all submissions in form,
            # but confirmation param must be among payload
            raise NoConfirmationProvidedException()

        return postgres_query, mongo_query