def get_xform_from_submission(xml, username, uuid=None): # check alternative form submission ids uuid = uuid or get_uuid_from_submission(xml) 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, deleted_at__isnull=True).count() > 0: xform = XForm.objects.get(uuid=uuid, deleted_at__isnull=True) return xform id_string = get_id_string_from_xml_str(xml) try: return get_object_or_404( XForm, id_string__iexact=id_string, user__username=username, deleted_at__isnull=True) except MultipleObjectsReturned: raise NonUniqueFormIdError()
def test_get_id_string_from_xml_str(self): submission = """<?xml version="1.0" encoding="UTF-8" ?> <submission xmlns:orx="http://openrosa.org/xforms"> <data> <id_string id="id_string"> <element>data</element> <data>random</data> </id_string> </data> </submission> """ id_string = get_id_string_from_xml_str(submission) self.assertEqual(id_string, 'id_string')
def get_xform_from_submission( xml, username, uuid=None, request=None): """Gets the submissions target XForm. Retrieves the target XForm by either utilizing the `uuid` param or the `uuid` retrievable from the `xml` or the `id_string` retrievable from the XML. Only returns form if `request_user` has permission to submit. :param (str) xml: The submission in XML form :param (str) username: The owner of the target XForm :param (str) uuid: The target XForms universally unique identifier. Default: None :param (django.http.request) request: Request object. Default: None """ uuid = uuid or get_uuid_from_submission(xml) 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, deleted_at__isnull=True).count() > 0: xform = XForm.objects.get(uuid=uuid, deleted_at__isnull=True) # If request is present, verify that the request user # has the correct permissions if request: try: # Verify request user has permission # to make submissions to the XForm check_submission_permissions(request, xform) return xform except PermissionDenied as e: # Check if the owner_username is equal to the XForm owner # Assumption: If the owner_username is equal to the XForm # owner we've retrieved the correct form. if username and xform.user.username == username: raise e else: return xform id_string = get_id_string_from_xml_str(xml) try: return get_object_or_404( XForm, id_string__iexact=id_string, user__username__iexact=username, deleted_at__isnull=True) except MultipleObjectsReturned: raise NonUniqueFormIdError()
def get_xform_from_submission(xml, username, uuid=None): # check alternative form submission ids uuid = uuid or get_uuid_from_submission(xml) 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) return xform id_string = get_id_string_from_xml_str(xml) return get_object_or_404(XForm, id_string__exact=id_string)
def get_xform_from_submission(xml, username, uuid=None): # check alternative form submission ids uuid = uuid or get_uuid_from_submission(xml) 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) return xform id_string = get_id_string_from_xml_str(xml) return get_object_or_404(XForm, id_string__exact=id_string, user__username=username)
def get_xform_from_submission(xml, username, uuid=None): # check alternative form submission ids uuid = uuid or get_uuid_from_submission(xml) if not username and not uuid: raise InstanceInvalidUserError() if uuid: # try find the form by its uuid which is the ideal condition try: xform = XForm.objects.get(uuid=uuid) except XForm.DoesNotExist: pass else: return xform id_string = get_id_string_from_xml_str(xml) return get_object_or_404(XForm, id_string__exact=id_string, user__username=username)
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