def restore_backup_from_xml_file(xml_instance_path, username): # check if its a valid xml instance file_name = os.path.basename(xml_instance_path) xml_file = django_file(xml_instance_path, field_name="xml_file", content_type="text/xml") media_files = [] try: date_created = _date_created_from_filename(file_name) except ValueError as e: sys.stderr.write( "Couldn't determine date created from filename: '%s'\n" % file_name) date_created = datetime.now() sys.stdout.write("Creating instance from '%s'\n" % file_name) try: create_instance(username, xml_file, media_files, date_created_override=date_created) return 1 except Exception as e: sys.stderr.write("Could not restore %s, create instance said: %s\n" % (file_name, e)) return 0
def restore_backup_from_xml_file(xml_instance_path, username): # check if its a valid xml instance file_name = os.path.basename(xml_instance_path) xml_file = django_file( xml_instance_path, field_name="xml_file", content_type="text/xml") media_files = [] try: date_created = _date_created_from_filename(file_name) except ValueError: sys.stderr.write( "Couldn't determine date created from filename: '%s'\n" % file_name) date_created = datetime.now() sys.stdout.write("Creating instance from '%s'\n" % file_name) try: create_instance( username, xml_file, media_files, date_created_override=date_created) return 1 except Exception as e: sys.stderr.write( "Could not restore %s, create instance said: %s\n" % (file_name, e)) return 0
def _submit_at_hour(self, hour): st_xml = '<?xml version=\'1.0\' ?><start_time id="start_time"><st'\ 'art_time>2012-01-11T%d:00:00.000+00</start_time></start'\ '_time>' % hour try: create_instance(self.user.username, TempFileProxy(st_xml), []) except DuplicateInstance: pass
def submit_at_hour(hour): st_xml = """ <?xml version='1.0' ?><start_time id="start_time"><start_time>2012-01-11T%d:00:00.000+00</start_time></start_time> """.strip() % hour try: create_instance(self.user.username, TempFileProxy(st_xml), []) except DuplicateInstance: pass
def test_attachment_tracking(self): """ Test that when a submission with many attachments is made, we keep track of the total number of attachments expected and if we have received all of them """ md = """ | survey | | | | | | type | name | label | | | image | image1 | Photo | | | image | image2 | Photo | """ self._create_user_and_login() self.xform = self._publish_markdown(md, self.user) xml_string = """ <data id="{}"> <meta> <instanceID>uuid:UJ5jSMAJ1Jz4EszdgHy8n851AsKaqBPO5</instanceID> </meta> <image1>1300221157303.jpg</image1> <image2>1300375832136.jpg</image2> </data> """.format(self.xform.id_string) file_path = "{}/apps/logger/tests/Health_2011_03_13."\ "xml_2011-03-15_20-30-28/1300221157303"\ ".jpg".format(settings.PROJECT_ROOT) media_file = django_file(path=file_path, field_name="image1", content_type="image/jpeg") instance = create_instance(self.user.username, StringIO(xml_string.strip()), media_files=[media_file]) self.assertFalse(instance.json[MEDIA_ALL_RECEIVED]) self.assertEquals(instance.json[TOTAL_MEDIA], 2) self.assertEquals(instance.json[MEDIA_COUNT], 1) self.assertEquals(instance.json[TOTAL_MEDIA], instance.total_media) self.assertEquals(instance.json[MEDIA_COUNT], instance.media_count) self.assertEquals(instance.json[MEDIA_ALL_RECEIVED], instance.media_all_received) file2_path = "{}/apps/logger/tests/Water_2011_03_17_2011-03-17_16-29"\ "-59/1300375832136.jpg".format(settings.PROJECT_ROOT) media2_file = django_file(path=file2_path, field_name="image2", content_type="image/jpeg") create_instance(self.user.username, StringIO(xml_string.strip()), media_files=[media2_file]) instance2 = Instance.objects.get(pk=instance.pk) self.assertTrue(instance2.json[MEDIA_ALL_RECEIVED]) self.assertEquals(instance2.json[TOTAL_MEDIA], 2) self.assertEquals(instance2.json[MEDIA_COUNT], 2) self.assertEquals(instance2.json[TOTAL_MEDIA], instance2.total_media) self.assertEquals(instance2.json[MEDIA_COUNT], instance2.media_count) self.assertEquals(instance2.json[MEDIA_ALL_RECEIVED], instance2.media_all_received)
def _tutorial_form_submission(self): tutorial_folder = os.path.join( os.path.dirname(__file__), '..', 'fixtures', 'forms', 'tutorial') self._publish_xls_file_and_set_xform(os.path.join(tutorial_folder, 'tutorial.xls')) instance_paths = [os.path.join(tutorial_folder, 'instances', i) for i in ['1.xml', '2.xml', '3.xml']] for path in instance_paths: create_instance(self.user.username, open(path), []) self.assertEqual(self.xform.instances.count(), 3)
def test_attachment_tracking_duplicate(self): """ Test that duplicate attachments does not affect if all attachments were received. """ md = """ | survey | | | | | | type | name | label | | | image | image1 | Photo | | | image | image2 | Photo | """ self._create_user_and_login() self.xform = self._publish_markdown(md, self.user) xml_string = """ <data id="{}"> <meta> <instanceID>uuid:UJ5jSMAJ1Jz4EszdgHy8n851AsKaqBPO5</instanceID> </meta> <image1>1300221157303.jpg</image1> <image2>1300375832136.jpg</image2> </data> """.format(self.xform.id_string) file_path = "{}/apps/logger/tests/Health_2011_03_13."\ "xml_2011-03-15_20-30-28/1300221157303"\ ".jpg".format(settings.PROJECT_ROOT) media_file = django_file(path=file_path, field_name="image1", content_type="image/jpeg") instance = create_instance(self.user.username, BytesIO(xml_string.strip().encode('utf-8')), media_files=[media_file]) self.assertFalse(instance.json[MEDIA_ALL_RECEIVED]) self.assertEquals(instance.json[TOTAL_MEDIA], 2) self.assertEquals(instance.json[MEDIA_COUNT], 1) self.assertEquals(instance.json[TOTAL_MEDIA], instance.total_media) self.assertEquals(instance.json[MEDIA_COUNT], instance.media_count) self.assertEquals(instance.json[MEDIA_ALL_RECEIVED], instance.media_all_received) media2_file = django_file(path=file_path, field_name="image1", content_type="image/jpeg") create_instance(self.user.username, BytesIO(xml_string.strip().encode('utf-8')), media_files=[media2_file]) instance2 = Instance.objects.get(pk=instance.pk) self.assertFalse(instance2.json[MEDIA_ALL_RECEIVED]) self.assertEquals(instance2.json[TOTAL_MEDIA], 2) self.assertEquals(instance2.json[MEDIA_COUNT], 1) self.assertEquals(instance2.json[TOTAL_MEDIA], instance2.total_media) self.assertEquals(instance2.json[MEDIA_COUNT], instance2.media_count) self.assertEquals(instance2.json[MEDIA_ALL_RECEIVED], instance2.media_all_received)
def _contributions_form_submissions(self): count = XForm.objects.count() path = os.path.join(os.path.dirname(__file__), '..', 'fixtures', 'forms', 'contributions') form_path = os.path.join(path, 'contributions.xml') f = open(form_path) xml_file = ContentFile(f.read()) f.close() xml_file.name = 'contributions.xml' self.xform = publish_xml_form(xml_file, self.user) self.assertTrue(XForm.objects.count() > count) instances_path = os.path.join(path, 'instances') for uuid in os.listdir(instances_path): s_path = os.path.join(instances_path, uuid, 'submission.xml') create_instance(self.user.username, open(s_path), []) self.assertEqual(self.xform.instances.count(), 6)
def test_get_first_record(self): """ Test get_first_record() function. """ xform_md = """ | survey | | | | | | type | name | label | | | text | name | Photo | """ self._create_user_and_login() xform = self._publish_markdown(xform_md, self.user) self.assertIsNone(get_first_record(Instance.objects.all().only('id'))) xml_string = """ <data id="{}"> <name>Alice</name> </data> """.format(xform.id_string) instance = create_instance(self.user.username, BytesIO(xml_string.strip().encode('utf-8')), media_files=[]) record = get_first_record(Instance.objects.all().only('id')) self.assertIsNotNone(record) self.assertEqual(record.id, instance.id)
def import_instance(username, xform_path, photos, osm_files, status, raise_exception): """ This callback is passed an instance of a XFormInstanceFS. See xform_fs.py for more info. """ with django_file(xform_path, field_name="xml_file", content_type="text/xml") as xml_file: images = [django_file(jpg, field_name="image", content_type="image/jpeg") for jpg in photos] images += [ django_file(osm, field_name='image', content_type='text/xml') for osm in osm_files ] try: instance = create_instance(username, xml_file, images, status) except Exception as e: if raise_exception: raise e for i in images: i.close() if instance: return 1 else: return 0
def import_instance(username, xform_path, photos, osm_files, status, raise_exception): """ This callback is passed an instance of a XFormInstanceFS. See xform_fs.py for more info. """ with django_file(xform_path, field_name="xml_file", content_type="text/xml") as xml_file: images = [ django_file(jpg, field_name="image", content_type="image/jpeg") for jpg in photos ] images += [ django_file(osm, field_name='image', content_type='text/xml') for osm in osm_files ] try: instance = create_instance(username, xml_file, images, status) except Exception as e: if raise_exception: raise e for i in images: i.close() if instance: return 1 else: return 0
def _contributions_form_submissions(self): count = XForm.objects.count() path = os.path.join(os.path.dirname(__file__), '..', 'fixtures', 'forms', 'contributions') form_path = os.path.join(path, 'contributions.xml') with open(form_path, encoding='utf-8') as f: xml_file = ContentFile(f.read()) xml_file.name = 'contributions.xml' project = get_user_default_project(self.user) self.xform = publish_xml_form(xml_file, self.user, project) self.assertTrue(XForm.objects.count() > count) instances_path = os.path.join(path, 'instances') for uuid in os.listdir(instances_path): s_path = os.path.join(instances_path, uuid, 'submission.xml') create_instance(self.user.username, open(s_path, 'rb'), []) self.assertEqual(self.xform.instances.count(), 6)
def callback(xform_fs): """ This callback is passed an instance of a XFormInstanceFS. See xform_fs.py for more info. """ with django_file(xform_fs.path, field_name="xml_file", content_type="text/xml") as xml_file: images = [ django_file(jpg, field_name="image", content_type="image/jpeg") for jpg in xform_fs.photos ] # TODO: if an instance has been submitted make sure all the # files are in the database. # there shouldn't be any instances with a submitted status in the # import. instance = create_instance(user.username, xml_file, images, status) for i in images: i.close() if instance: return 1 else: return 0
def generate_instance(username, xml_file, media_files, uuid=None): ''' Process an XForm submission as if done via HTTP :param IO xml_file: file-like object containing XML XForm :param string username: username of the Form's owner :param list media_files: a list of UploadedFile objects :param string uuid: an optionnal uuid for the instance. :returns a (status, message) tuple. ''' try: instance = create_instance( username, xml_file, media_files, uuid=uuid ) except InstanceInvalidUserError: return {'code': SMS_SUBMISSION_REFUSED, 'text': _(u"Username or ID required.")} except InstanceEmptyError: return {'code': SMS_INTERNAL_ERROR, 'text': _(u"Received empty submission. " u"No instance was created")} except FormInactiveError: return {'code': SMS_SUBMISSION_REFUSED, 'text': _(u"Form is not active")} except XForm.DoesNotExist: return {'code': SMS_SUBMISSION_REFUSED, 'text': _(u"Form does not exist on this account")} except ExpatError: return {'code': SMS_INTERNAL_ERROR, 'text': _(u"Improperly formatted XML.")} except DuplicateInstance: return {'code': SMS_SUBMISSION_REFUSED, 'text': _(u"Duplicate submission")} if instance is None: return {'code': SMS_INTERNAL_ERROR, 'text': _(u"Unable to create submission.")} user = User.objects.get(username=username) audit = { "xform": instance.xform.id_string } audit_log(Actions.SUBMISSION_CREATED, user, instance.xform.user, _("Created submission on form %(id_string)s.") % {"id_string": instance.xform.id_string}, audit, HttpRequest()) xml_file.close() if len(media_files): [_file.close() for _file in media_files] return {'code': SMS_SUBMISSION_ACCEPTED, 'text': _(u"[SUCCESS] Your submission has been accepted."), 'id': get_sms_instance_id(instance)}
def test_numeric_types_are_rendered_as_required(self): tutorial_folder = os.path.join(os.path.dirname(__file__), '..', 'fixtures', 'forms', 'tutorial') self._publish_xls_file_and_set_xform( os.path.join(tutorial_folder, 'tutorial.xls')) instance_path = os.path.join(tutorial_folder, 'instances', '1.xml') create_instance(self.user.username, open(instance_path), []) self.assertEqual(self.xform.instances.count(), 1) view = DataViewSet.as_view({'get': 'list'}) request = self.factory.get('/', **self.extra) response = view(request, pk=self.xform.id) self.assertEqual(response.status_code, 200) # check that ONLY values with numeric and decimal types are converted self.assertEqual(response.data[0].get('age'), 35) self.assertEqual(response.data[0].get('net_worth'), 100000.00) self.assertEqual(response.data[0].get('imei'), u'351746052009472')
def test_numeric_types_are_rendered_as_required(self): tutorial_folder = os.path.join( os.path.dirname(__file__), '..', 'fixtures', 'forms', 'tutorial') self._publish_xls_file_and_set_xform(os.path.join(tutorial_folder, 'tutorial.xls')) instance_path = os.path.join(tutorial_folder, 'instances', '1.xml') create_instance(self.user.username, open(instance_path), []) self.assertEqual(self.xform.instances.count(), 1) view = DataViewSet.as_view({'get': 'list'}) request = self.factory.get('/', **self.extra) response = view(request, pk=self.xform.id) self.assertEqual(response.status_code, 200) # check that ONLY values with numeric and decimal types are converted self.assertEqual(response.data[0].get('age'), 35) self.assertEqual(response.data[0].get('net_worth'), 100000.00) self.assertEqual(response.data[0].get('imei'), u'351746052009472')
def _upload_instance(self, xml_file, instance_dir_path, files): xml_doc = clean_and_parse_xml(xml_file.read()) xml = StringIO() de_node = xml_doc.documentElement for node in de_node.firstChild.childNodes: xml.write(node.toxml()) new_xml_file = ContentFile(xml.getvalue()) new_xml_file.content_type = "text/xml" xml.close() attachments = [] for attach in de_node.getElementsByTagName("mediaFile"): filename_node = attach.getElementsByTagName("filename") filename = filename_node[0].childNodes[0].nodeValue if filename in files: file_obj = default_storage.open(os.path.join(instance_dir_path, filename)) mimetype, encoding = mimetypes.guess_type(file_obj.name) media_obj = django_file(file_obj, "media_files[]", mimetype) attachments.append(media_obj) create_instance(self.user.username, new_xml_file, attachments)
def test_recovers_wrongly_deleted_attachments(self): """ Test that the command recovers the correct attachment """ md = """ | survey | | | | | | type | name | label | | | file | file | File | | | image | image | Image | """ # pylint: disable=invalid-name self._create_user_and_login() xform = self._publish_markdown(md, self.user) xml_string = f""" <data id="{xform.id_string}"> <meta> <instanceID>uuid:UJ5jz4EszdgH8uhy8nss1AsKaqBPO5VN7</instanceID> </meta> <file>Health_2011_03_13.xml_2011-03-15_20-30-28.xml</file> <image>1300221157303.jpg</image> </data> """ media_root = (f'{settings.PROJECT_ROOT}/apps/logger/tests/Health' '_2011_03_13.xml_2011-03-15_20-30-28/') image_media = django_file( path=f'{media_root}1300221157303.jpg', field_name='image', content_type='image/jpeg') file_media = django_file( path=f'{media_root}Health_2011_03_13.xml_2011-03-15_20-30-28.xml', field_name='file', content_type='text/xml') instance = create_instance( self.user.username, BytesIO(xml_string.strip().encode('utf-8')), media_files=[file_media, image_media]) self.assertEqual( instance.attachments.filter(deleted_at__isnull=True).count(), 2) attachment = instance.attachments.first() # Soft delete attachment attachment.deleted_at = datetime.now() attachment.deleted_by = self.user attachment.save() self.assertEqual( instance.attachments.filter(deleted_at__isnull=True).count(), 1) # Attempt recovery of attachment recover_deleted_attachments(form_id=instance.xform.id) self.assertEqual( instance.attachments.filter(deleted_at__isnull=True).count(), 2) attachment.refresh_from_db() self.assertIsNone(attachment.deleted_at) self.assertIsNone(attachment.deleted_by)
def _upload_instance(self, xml_file, instance_dir_path, files): xml_doc = clean_and_parse_xml(xml_file.read()) xml = StringIO() de_node = xml_doc.documentElement for node in de_node.firstChild.childNodes: xml.write(node.toxml()) new_xml_file = ContentFile(xml.getvalue()) new_xml_file.content_type = 'text/xml' xml.close() attachments = [] for attach in de_node.getElementsByTagName('mediaFile'): filename_node = attach.getElementsByTagName('filename') filename = filename_node[0].childNodes[0].nodeValue if filename in files: file_obj = default_storage.open( os.path.join(instance_dir_path, filename)) mimetype, encoding = mimetypes.guess_type(file_obj.name) media_obj = django_file(file_obj, 'media_files[]', mimetype) attachments.append(media_obj) create_instance(self.user.username, new_xml_file, attachments)
def test_attachment_file_name_validation(self): """ Test that a clear exception is raised when an attachement is received whose file name exceeds 100 chars """ md = """ | survey | | | | | | type | name | label | | | image | image1 | Photo | | | image | image2 | Photo | """ self._create_user_and_login() self.xform = self._publish_markdown(md, self.user) xml_string = """ <data id="{}"> <meta> <instanceID>uuid:UJ5jSMAJ1Jz4EszdgHy8n851AsKaqBPO5</instanceID> </meta> <image1>1300221157303.jpg</image1> <image2>1300375832136.jpg</image2> </data> """.format(self.xform.id_string) file_path = "{}/apps/logger/tests/Health_2011_03_13."\ "xml_2011-03-15_20-30-28/1300221157303"\ ".jpg".format(settings.PROJECT_ROOT) f = open(file_path, 'rb') media_file = InMemoryUploadedFile( file=f, field_name="image1", name=f'{f.name} +\ test_file_name_test_file_name_test_file_name_test_file_name_test_file_name_test_file_name', # noqa content_type="image/jpeg", size=os.path.getsize(file_path), charset=None) with self.assertRaises(AttachmentNameError): create_instance(self.user.username, BytesIO(xml_string.strip().encode('utf-8')), media_files=[media_file])
def restore_backup_from_path(dir_path, username, status): """ Only restores xml submissions, media files are assumed to still be in storage and will be retrieved by the filename stored within the submission """ num_instances = 0 num_restored = 0 for dir_path, dir_names, file_names in os.walk(dir_path): for file_name in file_names: # check if its a valid xml instance xml_instance_path = os.path.join(dir_path, file_name) num_instances += 1 xml_file = django_file( xml_instance_path, field_name="xml_file", content_type="text/xml") media_files = [] date_created = None try: date_created = _date_created_from_filename(file_name) except ValueError as e: sys.stderr.write( "Couldn't determine date created from filename: '%s'\n" % file_name) else: sys.stdout.write("Creating instance from '%s'\n" % file_name) try: create_instance( username, xml_file, media_files, date_created_override=date_created) num_restored += 1 except Exception as e: sys.stderr.write( "Could not restore %s, create instance said: %s\n" % (file_name, e)) return num_instances, num_restored
def callback(xform_fs): """ This callback is passed an instance of a XFormInstanceFS. See xform_fs.py for more info. """ with django_file(xform_fs.path, field_name="xml_file", content_type="text/xml") as xml_file: images = [django_file(jpg, field_name="image", content_type="image/jpeg") for jpg in xform_fs.photos] # TODO: if an instance has been submitted make sure all the # files are in the database. # there shouldn't be any instances with a submitted status in the # import. instance = create_instance(user.username, xml_file, images, status) for i in images: i.close() if instance: return 1 else: return 0
def _submit_simple_yes(self): create_instance( self.user.username, TempFileProxy( '<?xml version=\'1.0\' ?><yes_or_no id="yes_or_no"><yesno>Yes<' '/yesno></yes_or_no>'), [])
def test_replaced_attachments_not_tracked(self): """ Test that when a submission with an attachments is made, and later edited, whereby the attachment is replaced, the replaced attachment is no longer tracked for that submission """ md = """ | survey | | | | | | type | name | label | | | file | file | File | | | image | image | Image | """ self._create_user_and_login() self.xform = self._publish_markdown(md, self.user) xml_string = """ <data id="{}"> <meta> <instanceID>uuid:UJ5jz4EszdgH8uhy8nss1AsKaqBPO5VN7</instanceID> </meta> <file>Health_2011_03_13.xml_2011-03-15_20-30-28.xml</file> <image>1300221157303.jpg</image> </data> """.format(self.xform.id_string) media_root = (f'{settings.PROJECT_ROOT}/apps/logger/tests/Health' '_2011_03_13.xml_2011-03-15_20-30-28/') image_media = django_file(path=f'{media_root}1300221157303.jpg', field_name='image', content_type='image/jpeg') file_media = django_file( path=f'{media_root}Health_2011_03_13.xml_2011-03-15_20-30-28.xml', field_name='file', content_type='text/xml') instance = create_instance(self.user.username, BytesIO(xml_string.strip().encode('utf-8')), media_files=[file_media, image_media]) self.assertTrue(instance.json[MEDIA_ALL_RECEIVED]) self.assertEqual( instance.attachments.filter(deleted_at__isnull=True).count(), 2) self.assertEquals(instance.json[TOTAL_MEDIA], 2) self.assertEquals(instance.json[MEDIA_COUNT], 2) self.assertEquals(instance.json[TOTAL_MEDIA], instance.total_media) self.assertEquals(instance.json[MEDIA_COUNT], instance.media_count) self.assertEquals(instance.json[MEDIA_ALL_RECEIVED], instance.media_all_received) patch_value = 'onadata.apps.logger.models.Instance.get_expected_media' with patch(patch_value) as get_expected_media: get_expected_media.return_value = ['1300375832136.jpg'] updated_xml_string = """ <data id="{}"> <meta> <instanceID>uuid:UJ5jz4EszdgH8uhy8nss1AsKaqBPO5VN7</instanceID> </meta> <images> <image1>1300375832136.jpg</image1> </images> </data> """.format(self.xform.id_string) file2_path = "{}/apps/logger/tests/Water_2011_03_17_2011"\ "-03-17_16-29-59/1300375832136.jpg".format( settings.PROJECT_ROOT) media2_file = django_file(path=file2_path, field_name="image1", content_type="image/jpeg") create_instance(self.user.username, BytesIO( updated_xml_string.strip().encode('utf-8')), media_files=[media2_file]) instance2 = Instance.objects.get(pk=instance.pk) self.assertTrue(instance2.json[MEDIA_ALL_RECEIVED]) # Test that only one attachment is recognised for this submission # Since the file is no longer present in the submission self.assertEquals(instance2.json[TOTAL_MEDIA], 1) self.assertEquals(instance2.json[MEDIA_COUNT], 1) self.assertEquals(instance2.json[TOTAL_MEDIA], instance2.total_media) self.assertEquals(instance2.json[MEDIA_COUNT], instance2.media_count) self.assertEquals(instance2.json[MEDIA_ALL_RECEIVED], instance2.media_all_received)
def submission(request, username=None): if username and username.lower() != 'crowdforms': formlist_user = get_object_or_404(User, username=username.lower()) profile, created = \ UserProfile.objects.get_or_create(user=formlist_user) if profile.require_auth: authenticator = HttpDigestAuthenticator() if not authenticator.authenticate(request): return authenticator.build_challenge_response() if request.method == 'HEAD': response = OpenRosaResponse(status=204) if username: response['Location'] = request.build_absolute_uri().replace( request.get_full_path(), '/%s/submission' % username) else: response['Location'] = request.build_absolute_uri().replace( request.get_full_path(), '/submission') return response context = RequestContext(request) xml_file_list = [] media_files = [] # request.FILES is a django.utils.datastructures.MultiValueDict # for each key we have a list of values try: xml_file_list = request.FILES.pop("xml_submission_file", []) if len(xml_file_list) != 1: return OpenRosaResponseBadRequest( _(u"There should be a single XML submission file.") ) # save this XML file and media files as attachments media_files = request.FILES.values() # get uuid from post request uuid = request.POST.get('uuid') try: instance = create_instance( username, xml_file_list[0], media_files, uuid=uuid, request=request ) except InstanceInvalidUserError: return OpenRosaResponseBadRequest(_(u"Username or ID required.")) except IsNotCrowdformError: return OpenRosaResponseNotAllowed( _(u"Sorry but the crowd form you submitted to is closed.") ) except InstanceEmptyError: return OpenRosaResponseBadRequest( _(u"Received empty submission. No instance was created") ) except FormInactiveError: return OpenRosaResponseNotAllowed(_(u"Form is not active")) except XForm.DoesNotExist: return OpenRosaResponseNotFound( _(u"Form does not exist on this account") ) except ExpatError: return OpenRosaResponseBadRequest(_(u"Improperly formatted XML.")) except DuplicateInstance: response = OpenRosaResponse(_(u"Duplicate submission")) response.status_code = 202 response['Location'] = request.build_absolute_uri(request.path) return response except PermissionDenied, e: return OpenRosaResponseNotAllowed(e.message) if instance is None: return OpenRosaResponseBadRequest( _(u"Unable to create submission.")) audit = { "xform": instance.xform.id_string } audit_log( Actions.SUBMISSION_CREATED, request.user, instance.xform.user, _("Created submission on form %(id_string)s.") % { "id_string": instance.xform.id_string }, audit, request) # response as html if posting with a UUID if not username and uuid: response = _html_submission_response(context, instance) else: response = _submission_response(context, instance) # ODK needs two things for a form to be considered successful # 1) the status code needs to be 201 (created) # 2) The location header needs to be set to the host it posted to response.status_code = 201 response['Location'] = request.build_absolute_uri(request.path) return response
def submission(request, username=None): if username and username.lower() != 'crowdforms': formlist_user = get_object_or_404(User, username=username.lower()) profile, created = \ UserProfile.objects.get_or_create(user=formlist_user) if profile.require_auth: authenticator = HttpDigestAuthenticator() if not authenticator.authenticate(request): return authenticator.build_challenge_response() if request.method == 'HEAD': response = OpenRosaResponse(status=204) if username: response['Location'] = request.build_absolute_uri().replace( request.get_full_path(), '/%s/submission' % username) else: response['Location'] = request.build_absolute_uri().replace( request.get_full_path(), '/submission') return response context = RequestContext(request) xml_file_list = [] media_files = [] # request.FILES is a django.utils.datastructures.MultiValueDict # for each key we have a list of values try: xml_file_list = request.FILES.pop("xml_submission_file", []) if len(xml_file_list) != 1: return OpenRosaResponseBadRequest( _(u"There should be a single XML submission file.")) # save this XML file and media files as attachments media_files = request.FILES.values() # get uuid from post request uuid = request.POST.get('uuid') try: instance = create_instance(username, xml_file_list[0], media_files, uuid=uuid, request=request) except InstanceInvalidUserError: return OpenRosaResponseBadRequest(_(u"Username or ID required.")) except IsNotCrowdformError: return OpenRosaResponseNotAllowed( _(u"Sorry but the crowd form you submitted to is closed.")) except InstanceEmptyError: return OpenRosaResponseBadRequest( _(u"Received empty submission. No instance was created")) except FormInactiveError: return OpenRosaResponseNotAllowed(_(u"Form is not active")) except XForm.DoesNotExist: return OpenRosaResponseNotFound( _(u"Form does not exist on this account")) except ExpatError: return OpenRosaResponseBadRequest(_(u"Improperly formatted XML.")) except DuplicateInstance: response = OpenRosaResponse(_(u"Duplicate submission")) response.status_code = 202 response['Location'] = request.build_absolute_uri(request.path) return response except PermissionDenied, e: return OpenRosaResponseNotAllowed(e.message) if instance is None: return OpenRosaResponseBadRequest( _(u"Unable to create submission.")) audit = {"xform": instance.xform.id_string} audit_log( Actions.SUBMISSION_CREATED, request.user, instance.xform.user, _("Created submission on form %(id_string)s.") % {"id_string": instance.xform.id_string}, audit, request) # response as html if posting with a UUID if not username and uuid: response = _html_submission_response(context, instance) else: response = _submission_response(context, instance) # ODK needs two things for a form to be considered successful # 1) the status code needs to be 201 (created) # 2) The location header needs to be set to the host it posted to response.status_code = 201 response['Location'] = request.build_absolute_uri(request.path) return response
def _submit_simple_yes(self): create_instance(self.user.username, TempFileProxy( '<?xml version=\'1.0\' ?><yes_or_no id="yes_or_no"><yesno>Yes<' '/yesno></yes_or_no>'), [])
def submit_simple_yes(): create_instance(self.user.username, TempFileProxy(""" <?xml version='1.0' ?><yes_or_no id="yes_or_no"><yesno>Yes</yesno></yes_or_no> """.strip()), [])