Exemplo n.º 1
0
def save_submission(xform, xml, media_files, new_uuid, submitted_by, status,
                    date_created_override):
    if not date_created_override:
        date_created_override = get_submission_date_from_xml(xml)

    instance = _get_instance(xml, new_uuid, submitted_by, status, xform)

    for f in media_files:
        Attachment.objects.get_or_create(
            instance=instance, media_file=f, mimetype=f.content_type)

    # override date created if required
    if date_created_override:
        if not timezone.is_aware(date_created_override):
            # default to utc?
            date_created_override = timezone.make_aware(
                date_created_override, timezone.utc)
        instance.date_created = date_created_override
        instance.save()

    if instance.xform is not None:
        pi, created = ParsedInstance.objects.get_or_create(
            instance=instance)

    if not created:
        pi.save(async=False)

    return instance
Exemplo n.º 2
0
def save_submission(xform, xml, media_files, new_uuid, submitted_by, status,
                    date_created_override):
    if not date_created_override:
        date_created_override = get_submission_date_from_xml(xml)

    instance = _get_instance(xml, new_uuid, submitted_by, status, xform)
    save_attachments(xform, instance, media_files)

    # override date created if required
    if date_created_override:
        if not timezone.is_aware(date_created_override):
            # default to utc?
            date_created_override = timezone.make_aware(
                date_created_override, timezone.utc)
        instance.date_created = date_created_override
        instance.save()

    if instance.xform is not None:
        instance.save()
        pi, created = ParsedInstance.objects.get_or_create(instance=instance)

    if not created:
        pi.save(async=False)

    return instance
def save_submission(xform, xml, media_files, new_uuid, submitted_by, status,
                    date_created_override, fxid, site, fs_poj_id=None, project=None):
    if not date_created_override:
        date_created_override = get_submission_date_from_xml(xml)

    instance = _get_instance(xml, new_uuid, submitted_by, status, xform, fxid, fs_poj_id, site, project)

    for f in media_files:
        Attachment.objects.get_or_create(
            instance=instance, media_file=f, mimetype=f.content_type)

    # override date created if required
    if date_created_override:
        if not timezone.is_aware(date_created_override):
            # default to utc?
            date_created_override = timezone.make_aware(
                date_created_override, timezone.utc)
        instance.date_created = date_created_override
        instance.save()
    if instance.xform is not None:
        if fs_poj_id:
            fs_poj_id = str(fs_poj_id)
        pi, created = FieldSightParsedInstance.get_or_create(instance,
                                                             update_data={'fs_uuid': fxid, 'fs_status': 0,
                                                                          'fs_site':site, 'fs_project':project,
                                                                          'fs_project_uuid':fs_poj_id})
    if not created:
        pi.save(async=False)
    return instance
Exemplo n.º 4
0
def save_submission(xform, xml, media_files, new_uuid, submitted_by, status,
                    date_created_override):
    if not date_created_override:
        date_created_override = get_submission_date_from_xml(xml)

    # We have to save the `Instance` to the database before we can associate
    # any `Attachment`s with it, but we are inside a transaction and saving
    # attachments is slow! Usually creating an `Instance` updates the
    # submission count of the parent `XForm` automatically via a `post_save`
    # signal, but that takes a lock on `logger_xform` that persists until the
    # end of the transaction.  We must avoid doing that until all attachments
    # are saved, and we are as close as possible to the end of the transaction.
    # See https://github.com/kobotoolbox/kobocat/issues/490.
    #
    # `_get_instance(..., defer_counting=True)` skips incrementing the
    # submission counters and returns an `Instance` with a `defer_counting`
    # attribute set to `True` *if* a new instance was created. We are
    # responsible for calling `update_xform_submission_count()` if the returned
    # `Instance` has `defer_counting = True`.
    instance = _get_instance(xml,
                             new_uuid,
                             submitted_by,
                             status,
                             xform,
                             defer_counting=True)

    save_attachments(instance, media_files)

    # override date created if required
    if date_created_override:
        if not timezone.is_aware(date_created_override):
            # default to utc?
            date_created_override = timezone.make_aware(
                date_created_override, timezone.utc)
        instance.date_created = date_created_override
        instance.save()

    if instance.xform is not None:
        pi, created = ParsedInstance.objects.get_or_create(instance=instance)

    if not created:
        pi.save(async=False)

    # Now that the slow tasks are complete and we are (hopefully!) close to the
    # end of the transaction, update the submission count if the `Instance` was
    # newly created
    if getattr(instance, 'defer_counting', False):
        # Remove the Python-only attribute
        del instance.defer_counting
        update_xform_submission_count(sender=None,
                                      instance=instance,
                                      created=True)

    return instance
Exemplo n.º 5
0
def save_submission(xform, xml, media_files, new_uuid, submitted_by, status,
                    date_created_override):
    if not date_created_override:
        date_created_override = get_submission_date_from_xml(xml)

    # We have to save the `Instance` to the database before we can associate
    # any `Attachment`s with it, but we are inside a transaction and saving
    # attachments is slow! Usually creating an `Instance` updates the
    # submission count of the parent `XForm` automatically via a `post_save`
    # signal, but that takes a lock on `logger_xform` that persists until the
    # end of the transaction.  We must avoid doing that until all attachments
    # are saved, and we are as close as possible to the end of the transaction.
    # See https://github.com/kobotoolbox/kobocat/issues/490.
    #
    # `_get_instance(..., defer_counting=True)` skips incrementing the
    # submission counters and returns an `Instance` with a `defer_counting`
    # attribute set to `True` *if* a new instance was created. We are
    # responsible for calling `update_xform_submission_count()` if the returned
    # `Instance` has `defer_counting = True`.
    instance = _get_instance(xml, new_uuid, submitted_by, status, xform,
                             defer_counting=True)

    save_attachments(instance, media_files)

    # override date created if required
    if date_created_override:
        if not timezone.is_aware(date_created_override):
            # default to utc?
            date_created_override = timezone.make_aware(
                date_created_override, timezone.utc)
        instance.date_created = date_created_override
        instance.save()

    if instance.xform is not None:
        pi, created = ParsedInstance.objects.get_or_create(
            instance=instance)

    if not created:
        pi.save(async=False)

    # Now that the slow tasks are complete and we are (hopefully!) close to the
    # end of the transaction, update the submission count if the `Instance` was
    # newly created
    if getattr(instance, 'defer_counting', False):
        # Remove the Python-only attribute
        del instance.defer_counting
        update_xform_submission_count(sender=None, instance=instance,
                                      created=True)

    return instance
Exemplo n.º 6
0
def create_instance(username, xml_file, media_files,
                    status=u'submitted_via_web', uuid=None,
                    date_created_override=None, request=None):
    """
    I used to check if this file had been submitted already, I've
    taken this out because it was too slow. Now we're going to create
    a way for an admin to mark duplicate instances. This should
    simplify things a bit.
    Submission cases:
        If there is a username and no uuid, submitting an old ODK form.
        If there is no username and a uuid, submitting a touchform.
        If there is a username and a uuid, submitting a new ODK form.
    """
    try:
        if username:
            username = username.lower()
        xml = xml_file.read()
        is_touchform = False
        # check alternative form submission ids
        if not uuid:
            # parse UUID from uploaded XML
            split_xml = uuid_regex.split(xml)

            # check that xml has UUID, then it is a crowdform
            if len(split_xml) > 1:
                uuid = split_xml[1]
        else:
            # is a touchform
            is_touchform = True

        if not username and not uuid:
            raise InstanceInvalidUserError()

        if uuid:
            # try find the form by its uuid which is the ideal condition
            if XForm.objects.filter(uuid=uuid).count() > 0:
                xform = XForm.objects.get(uuid=uuid)
                xform_username = xform.user.username

                if xform_username != username and not xform.is_crowd_form \
                        and not is_touchform:
                    raise IsNotCrowdformError()

                username = xform_username

        # Else, since we have a username, the Instance creation logic will
        # handle checking for the forms existence by its id_string
        if username and request and request.user.is_authenticated():
            id_string = get_id_string_from_xml_str(xml)
            xform = XForm.objects.get(
                id_string=id_string, user__username=username)
            if not xform.is_crowd_form and not is_touchform \
                    and xform.user.profile.require_auth \
                    and xform.user != request.user:
                raise PermissionDenied(
                    _(u"%(request_user)s is not allowed to make submissions "
                      u"to %(form_user)s's %(form_title)s form." % {
                          'request_user': request.user,
                          'form_user': xform.user,
                          'form_title': xform.title}))

        user = get_object_or_404(User, username=username)
        existing_instance_count = Instance.objects.filter(
            xml=xml, user=user).count()

        if existing_instance_count == 0:
            proceed_to_create_instance = True
        else:
            existing_instance = Instance.objects.filter(xml=xml, user=user)[0]
            if existing_instance.xform and\
                    not existing_instance.xform.has_start_time:
                proceed_to_create_instance = True
            else:
                # Ignore submission as a duplicate IFF
                #  * a submission's XForm collects start time
                #  * the submitted XML is an exact match with one that
                #    has already been submitted for that user.
                proceed_to_create_instance = False
                raise DuplicateInstance()

        # get new and depracated uuid's
        new_uuid = get_uuid_from_xml(xml)
        duplicate_instances = Instance.objects.filter(uuid=new_uuid)
        if duplicate_instances:
            for f in media_files:
                Attachment.objects.get_or_create(
                    instance=duplicate_instances[0],
                    media_file=f, mimetype=f.content_type)
            # ensure we have saved the extra attachments
            transaction.commit()
            raise DuplicateInstance()

        if proceed_to_create_instance:
            # check if its an edit submission
            old_uuid = get_deprecated_uuid_from_xml(xml)
            instances = Instance.objects.filter(uuid=old_uuid)
            if not date_created_override:
                date_created_override = get_submission_date_from_xml(xml)
            if instances:
                instance = instances[0]
                InstanceHistory.objects.create(
                    xml=instance.xml, xform_instance=instance, uuid=old_uuid)
                instance.xml = xml
                instance.uuid = new_uuid
                instance.save()
            else:
                # new submission
                instance = Instance.objects.create(
                    xml=xml, user=user, status=status)
            for f in media_files:
                Attachment.objects.get_or_create(
                    instance=instance, media_file=f, mimetype=f.content_type)

            # override date created if required
            if date_created_override:
                if not timezone.is_aware(date_created_override):
                    # default to utc?
                    date_created_override = timezone.make_aware(
                        date_created_override, timezone.utc)
                instance.date_created = date_created_override
                instance.save()

            if instance.xform is not None:
                pi, created = ParsedInstance.objects.get_or_create(
                    instance=instance)
            if not created:
                pi.save(async=False)
        # commit all changes
        transaction.commit()
        return instance
    except Exception:
        transaction.rollback()
        raise
    return None
Exemplo n.º 7
0
def create_instance(username, xml_file, media_files,
                    status=u'submitted_via_web', uuid=None,
                    date_created_override=None, request=None):
    """
    I used to check if this file had been submitted already, I've
    taken this out because it was too slow. Now we're going to create
    a way for an admin to mark duplicate instances. This should
    simplify things a bit.
    Submission cases:
        If there is a username and no uuid, submitting an old ODK form.
        If there is no username and a uuid, submitting a touchform.
        If there is a username and a uuid, submitting a new ODK form.
    """
    try:
        if username:
            username = username.lower()
        xml = xml_file.read()
        is_touchform = False
        # check alternative form submission ids
        if not uuid:
            # parse UUID from uploaded XML
            split_xml = uuid_regex.split(xml)

            # check that xml has UUID, then it is a crowdform
            if len(split_xml) > 1:
                uuid = split_xml[1]
        else:
            # is a touchform
            is_touchform = True

        if not username and not uuid:
            raise InstanceInvalidUserError()

        if uuid:
            # try find the form by its uuid which is the ideal condition
            if XForm.objects.filter(uuid=uuid).count() > 0:
                xform = XForm.objects.get(uuid=uuid)
                xform_username = xform.user.username

                if xform_username != username and not xform.is_crowd_form \
                        and not is_touchform:
                    raise IsNotCrowdformError()

                username = xform_username

        # Else, since we have a username, the Instance creation logic will
        # handle checking for the forms existence by its id_string
        if username and request and request.user.is_authenticated():
            id_string = get_id_string_from_xml_str(xml)
            xform = XForm.objects.get(
                id_string=id_string, user__username=username)
            if not xform.is_crowd_form and not is_touchform \
                    and xform.user.profile.require_auth \
                    and xform.user != request.user:
                raise PermissionDenied(
                    _(u"%(request_user)s is not allowed to make submissions "
                      u"to %(form_user)s's %(form_title)s form." % {
                          'request_user': request.user,
                          'form_user': xform.user,
                          'form_title': xform.title}))

        user = get_object_or_404(User, username=username)
        existing_instance_count = Instance.objects.filter(
            xml=xml, user=user).count()

        if existing_instance_count == 0:
            proceed_to_create_instance = True
        else:
            existing_instance = Instance.objects.filter(xml=xml, user=user)[0]
            if existing_instance.xform and\
                    not existing_instance.xform.has_start_time:
                proceed_to_create_instance = True
            else:
                # Ignore submission as a duplicate IFF
                #  * a submission's XForm collects start time
                #  * the submitted XML is an exact match with one that
                #    has already been submitted for that user.
                proceed_to_create_instance = False
                raise DuplicateInstance()

        # get new and depracated uuid's
        new_uuid = get_uuid_from_xml(xml)
        duplicate_instances = Instance.objects.filter(uuid=new_uuid)
        if duplicate_instances:
            for f in media_files:
                Attachment.objects.get_or_create(
                    instance=duplicate_instances[0],
                    media_file=f, mimetype=f.content_type)
            # ensure we have saved the extra attachments
            transaction.commit()
            raise DuplicateInstance()

        if proceed_to_create_instance:
            # check if its an edit submission
            old_uuid = get_deprecated_uuid_from_xml(xml)
            instances = Instance.objects.filter(uuid=old_uuid)
            if not date_created_override:
                date_created_override = get_submission_date_from_xml(xml)
            if instances:
                instance = instances[0]
                InstanceHistory.objects.create(
                    xml=instance.xml, xform_instance=instance, uuid=old_uuid)
                instance.xml = xml
                instance.uuid = new_uuid
                instance.save()
            else:
                # new submission
                instance = Instance.objects.create(
                    xml=xml, user=user, status=status)
            for f in media_files:
                Attachment.objects.get_or_create(
                    instance=instance, media_file=f, mimetype=f.content_type)

            # override date created if required
            if date_created_override:
                if not timezone.is_aware(date_created_override):
                    # default to utc?
                    date_created_override = timezone.make_aware(
                        date_created_override, timezone.utc)
                instance.date_created = date_created_override
                instance.save()

            if instance.xform is not None:
                pi, created = ParsedInstance.objects.get_or_create(
                    instance=instance)
            if not created:
                pi.save(async=False)
        # commit all changes
        transaction.commit()
        return instance
    except Exception:
        transaction.rollback()
        raise
    return None