def test_editor_role_submission_when_requires_auth(self): self._publish_xls_form_to_project() paths = [ os.path.join(self.main_directory, 'fixtures', 'transportation', 'instances_w_uuid', s, s + '.xml') for s in [ 'transport_2011-07-25_19-05-36', 'transport_2011-07-25_19-05-36-edited' ] ] self._make_submission(paths[0]) self.user.profile.require_auth = True self.user.profile.save() alice_data = { 'username': '******', 'email': '*****@*****.**', 'password1': 'alice', 'password2': 'alice' } self._login_user_and_profile(extra_post_data=alice_data) client = DigestClient() client.set_authorization('alice', 'alice', 'Digest') self._make_submission(paths[1], username='******', client=client) self.assertEqual(self.response.status_code, 403) role.EditorRole.add(self.user, self.xform) self._make_submission(paths[1], username='******', client=client) self.assertEqual(self.response.status_code, 201)
def test_submission_to_require_auth_without_perm(self): """ test submission to a private form by non-owner without perm is forbidden. """ view = XFormViewSet.as_view({ 'patch': 'partial_update' }) data = {'require_auth': True} self.assertFalse(self.xform.require_auth) request = self.factory.patch('/', data=data, **{ 'HTTP_AUTHORIZATION': 'Token %s' % self.user.auth_token}) view(request, pk=self.xform.id) self.xform.reload() self.assertTrue(self.xform.require_auth) xml_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "../fixtures/tutorial/instances/tutorial_2012-06-27_11-27-53.xml" ) # create a new user username = '******' self._create_user(username, username) client = DigestClient() client.set_authorization(username, username, 'Digest') self._make_submission(xml_submission_file_path, client=client) self.assertEqual(self.response.status_code, 403)
def _get_digest_client(self): self.user.profile.require_auth = True self.user.profile.save() client = DigestClient() client.set_authorization(self.profile_data['username'], self.profile_data['password1'], 'Digest') return client
def _download_xform(self): client = DigestClient() client.set_authorization('bob', 'bob') response = client.get(self.download_url) response_doc = minidom.parseString(response.content) xml_path = os.path.join(self.this_directory, "fixtures", "transportation", "transportation.xml") with open(xml_path) as xml_file: expected_doc = minidom.parse(xml_file) model_node = [ n for n in response_doc.getElementsByTagName("h:head")[0].childNodes if n.nodeType == Node.ELEMENT_NODE and n.tagName == "model" ][0] # check for UUID and remove uuid_nodes = [ node for node in model_node.childNodes if node.nodeType == Node.ELEMENT_NODE and node.getAttribute("nodeset") == "/transportation/formhub/uuid" ] self.assertEqual(len(uuid_nodes), 1) uuid_node = uuid_nodes[0] uuid_node.setAttribute("calculate", "''") # check content without UUID self.assertEqual(response_doc.toxml(), expected_doc.toxml())
def _get_authenticated_client( self, url, username='******', password='******', extra={}): client = DigestClient() # request with no credentials req = client.get(url, {}, **extra) self.assertEqual(req.status_code, 401) # apply credentials client.set_authorization(username, password, 'Digest') return client
def test_edited_submission(self): """ Test submissions that have been edited """ xml_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "fixtures", "tutorial", "instances", "tutorial_2012-06-27_11-27-53_w_uuid.xml") num_instances_history = InstanceHistory.objects.count() num_instances = Instance.objects.count() query_args = { 'username': self.user.username, 'id_string': self.xform.id_string, 'query': '{}', 'fields': '[]', 'sort': '[]', 'count': True } cursor = ParsedInstance.query_mongo(**query_args) num_mongo_instances = cursor[0]['count'] # make first submission self._make_submission(xml_submission_file_path) self.assertEqual(self.response.status_code, 201) self.assertEqual(Instance.objects.count(), num_instances + 1) # no new record in instances history self.assertEqual(InstanceHistory.objects.count(), num_instances_history) # check count of mongo instances after first submission cursor = ParsedInstance.query_mongo(**query_args) self.assertEqual(cursor[0]['count'], num_mongo_instances + 1) # edited submission xml_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "fixtures", "tutorial", "instances", "tutorial_2012-06-27_11-27-53_w_uuid_edited.xml") client = DigestClient() client.set_authorization('bob', 'bob', 'Digest') self._make_submission(xml_submission_file_path, client=client) self.assertEqual(self.response.status_code, 201) # we must have the same number of instances self.assertEqual(Instance.objects.count(), num_instances + 1) # should be a new record in instances history self.assertEqual(InstanceHistory.objects.count(), num_instances_history + 1) cursor = ParsedInstance.query_mongo(**query_args) self.assertEqual(cursor[0]['count'], num_mongo_instances + 1) # make sure we edited the mongo db record and NOT added a new row query_args['count'] = False cursor = ParsedInstance.query_mongo(**query_args) record = cursor[0] with open(xml_submission_file_path, "r") as f: xml_str = f.read() xml_str = clean_and_parse_xml(xml_str).toxml() edited_name = re.match(r"^.+?<name>(.+?)</name>", xml_str).groups()[0] self.assertEqual(record['name'], edited_name)
def test_attachment_url_with_digest_auth(self): self.client.logout() response = self.client.get(self.url, {'media_file': self.attachment_media_file}) self.assertEqual(response.status_code, 401) # nginx is used as proxy self.assertTrue('WWW-Authenticate' in response) digest_client = DigestClient() digest_client.set_authorization(self.login_username, self.login_password) response = digest_client.get( self.url, {'media_file': self.attachment_media_file}) self.assertEqual(response.status_code, 200)
def instances_xml(url, request, **kwargs): response = requests.Response() client = DigestClient() client.set_authorization('bob', 'bob', 'Digest') res = client.get('%s?%s' % (url.path, url.query)) if res.status_code == 302: res = client.get(res['Location']) response.encoding = res.get('content-type') response._content = get_streaming_content(res) else: response._content = res.content response.status_code = 200 return response
def test_retrieve_xform_manifest_linked_form(self): # for linked forms check if manifest media download url for csv # has a group_delimiter param data_type = 'media' data_value = 'xform {} transportation'.format(self.xform.pk) media = self._add_form_metadata(self.xform, data_type, data_value) self.view = XFormListViewSet.as_view( { "get": "manifest", "head": "manifest" } ) # sign in bob request = self.factory.head('/') auth_response = self.view(request, pk=self.xform.pk) auth = DigestAuth('bob', 'bobbob') # set up bob's request request = self.factory.get('/xformsManifest') request.META.update(auth(request.META, auth_response)) # make request response = self.view(request, pk=self.xform.pk, format='csv') # test manifest_media_url = '{}{}'.format( media.data['media_url'], '?group_delimiter=.&repeat_index_tags=_,_') download_url = response.data[0]['downloadUrl'] self.assertEqual(manifest_media_url, download_url) url = '/bob/xformsMedia/{}/{}.csv?group_delimiter=.'\ .format(self.xform.pk, self.metadata.pk) username = '******' password = '******' client = DigestClient() client.set_authorization(username, password, 'Digest') req = client.get(url) self.assertEqual(req.status_code, 200) # enable meta perms data_value = "editor-minor|dataentry" MetaData.xform_meta_permission(self.xform, data_value=data_value) req = client.get(url) self.assertEqual(req.status_code, 401)
def _authenticated_client(self, url, username='******', password='******', extra={}): client = DigestClient() # request with no credentials req = client.get(url, {}, **extra) self.assertEqual(req.status_code, 401) # apply credentials client.set_authorization(username, password, 'Digest') req = client.get(url, {}, **extra) # if 204 authorization successfull, proceed self.assertEqual(req.status_code, 204) # submissions should use this authenticated client return client
def _check_formlist(self): url = '/%s/formList' % self.user.username client = DigestClient() client.set_authorization('bob', 'bob') response = client.get(url) self.download_url = \ 'http://testserver/%s/forms/%s/form.xml'\ % (self.user.username, self.xform.pk) md5_hash = md5(self.xform.xml.encode('utf-8')).hexdigest() expected_content = """<?xml version="1.0" encoding="utf-8"?> <xforms xmlns="http://openrosa.org/xforms/xformsList"><xform><formID>transportation_2011_07_25</formID><name>transportation_2011_07_25</name><version>2014111</version><hash>md5:%(hash)s</hash><descriptionText></descriptionText><downloadUrl>%(download_url)s</downloadUrl><manifestUrl></manifestUrl></xform></xforms>""" # noqa expected_content = expected_content % { 'download_url': self.download_url, 'hash': md5_hash } self.assertEqual(response.content.decode('utf-8'), expected_content) self.assertTrue(response.has_header('X-OpenRosa-Version')) self.assertTrue(response.has_header('Date'))
def test_submission_when_requires_auth(self): self.user.profile.require_auth = True self.user.profile.save() # create a new user alice = self._create_user('alice', 'alice') # assign report perms to user assign_perm('report_xform', alice, self.xform) xml_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "../fixtures/tutorial/instances/tutorial_2012-06-27_11-27-53.xml" ) client = DigestClient() client.set_authorization('alice', 'alice', 'Digest') self._make_submission( xml_submission_file_path, client=client) self.assertEqual(self.response.status_code, 201)
def test_unicode_submission(self): """Test xml submissions that contain unicode characters """ xml_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "fixtures", "tutorial", "instances", "tutorial_unicode_submission.xml") self.user.profile.require_auth = True self.user.profile.save() # create a new user alice = self._create_user('alice', 'alice') # assign report perms to user assign_perm('report_xform', alice, self.xform) client = DigestClient() client.set_authorization('alice', 'alice', 'Digest') self._make_submission(xml_submission_file_path) self.assertEqual(self.response.status_code, 201)
def test_readonly_role_submission_when_requires_auth(self): self._publish_xls_form_to_project() self.user.profile.require_auth = True self.user.profile.save() alice_data = { 'username': '******', 'email': '*****@*****.**', 'password1': 'alice', 'password2': 'alice' } self._login_user_and_profile(extra_post_data=alice_data) role.ReadOnlyRole.add(self.user, self.xform) paths = [ os.path.join(self.main_directory, 'fixtures', 'transportation', 'instances', s, s + '.xml') for s in self.surveys ] client = DigestClient() client.set_authorization('alice', 'alice', 'Digest') self._make_submission(paths[0], username='******', client=client) self.assertEqual(self.response.status_code, 403)
def test_submission_to_require_auth_with_perm(self): """ test submission to a private form by non-owner is forbidden. TODO send authentication challenge when xform.require_auth is set. This is non-trivial because we do not know the xform until we have parsed the XML. """ raise SkipTest view = XFormViewSet.as_view({ 'patch': 'partial_update' }) data = {'require_auth': True} self.assertFalse(self.xform.require_auth) request = self.factory.patch('/', data=data, **{ 'HTTP_AUTHORIZATION': 'Token %s' % self.user.auth_token}) view(request, pk=self.xform.id) self.xform.reload() self.assertTrue(self.xform.require_auth) # create a new user username = '******' alice = self._create_user(username, username) # assign report perms to user assign_perm('report_xform', alice, self.xform) client = DigestClient() client.set_authorization(username, username, 'Digest') xml_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "../fixtures/tutorial/instances/tutorial_2012-06-27_11-27-53.xml" ) self._make_submission(xml_submission_file_path, client=client) self.assertEqual(self.response.status_code, 201)
def test_edited_submission(self): """ Test submissions that have been edited """ # Delete all previous instance history objects InstanceHistory.objects.all().delete() xml_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "fixtures", "tutorial", "instances", "tutorial_2012-06-27_11-27-53_w_uuid.xml") num_instances_history = InstanceHistory.objects.count() num_instances = Instance.objects.count() query_args = { 'xform': self.xform, 'query': '{}', 'fields': '[]', 'count': True } cursor = [r for r in query_data(**query_args)] num_data_instances = cursor[0]['count'] # make first submission self._make_submission(xml_submission_file_path) self.assertEqual(self.response.status_code, 201) self.assertEqual(Instance.objects.count(), num_instances + 1) # Take initial instance from DB initial_instance = self.xform.instances.first() # check that '_last_edited' key is not in the json self.assertIsNone(initial_instance.json.get(LAST_EDITED)) # no new record in instances history self.assertEqual(InstanceHistory.objects.count(), num_instances_history) # check count of mongo instances after first submission cursor = query_data(**query_args) self.assertEqual(cursor[0]['count'], num_data_instances + 1) # edited submission xml_edit_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "fixtures", "tutorial", "instances", "tutorial_2012-06-27_11-27-53_w_uuid_edited.xml") client = DigestClient() client.set_authorization('bob', 'bob', 'Digest') with catch_signal(process_submission) as handler: self._make_submission(xml_edit_submission_file_path, client=client) self.assertEqual(self.response.status_code, 201) # we must have the same number of instances self.assertEqual(Instance.objects.count(), num_instances + 1) # should be a new record in instances history self.assertEqual(InstanceHistory.objects.count(), num_instances_history + 1) instance_history_1 = InstanceHistory.objects.first() edited_instance = self.xform.instances.first() self.assertDictEqual(initial_instance.get_dict(), instance_history_1.get_dict()) handler.assert_called_once_with(instance=edited_instance, sender=Instance, signal=ANY) self.assertNotEqual(edited_instance.uuid, instance_history_1.uuid) # check that instance history's submission_date is equal to instance's # date_created - last_edited by default is null for an instance self.assertEquals(edited_instance.date_created, instance_history_1.submission_date) # check that '_last_edited' key is not in the json self.assertIn(LAST_EDITED, edited_instance.json) cursor = query_data(**query_args) self.assertEqual(cursor[0]['count'], num_data_instances + 1) # make sure we edited the mongo db record and NOT added a new row query_args['count'] = False cursor = query_data(**query_args) record = cursor[0] with open(xml_edit_submission_file_path, "r") as f: xml_str = f.read() xml_str = clean_and_parse_xml(xml_str).toxml() edited_name = re.match(ur"^.+?<name>(.+?)</name>", xml_str).groups()[0] self.assertEqual(record['name'], edited_name) instance_before_second_edit = edited_instance xml_edit_submission_file_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..", "fixtures", "tutorial", "instances", "tutorial_2012-06-27_11-27-53_w_uuid_edited_again.xml") self._make_submission(xml_edit_submission_file_path) cursor = query_data(**query_args) record = cursor[0] edited_instance = self.xform.instances.first() instance_history_2 = InstanceHistory.objects.last() self.assertEquals(instance_before_second_edit.last_edited, instance_history_2.submission_date) # check that '_last_edited' key is not in the json self.assertIn(LAST_EDITED, edited_instance.json) self.assertEqual(record['name'], 'Tom and Jerry') self.assertEqual(InstanceHistory.objects.count(), num_instances_history + 2) # submitting original submission is treated as a duplicate # does not add a new record # does not change data self._make_submission(xml_submission_file_path) self.assertEqual(self.response.status_code, 202) self.assertEqual(Instance.objects.count(), num_instances + 1) self.assertEqual(InstanceHistory.objects.count(), num_instances_history + 2)
def setUp(self): super(TestFormList, self).setUp() self.profile = UserProfile.objects.create(user=self.user, require_auth=True) self.profile.save() self.digest_client = DigestClient()
def setUp(self): self.client = DigestClient() self.client.set_authorization('*****@*****.**','tester150411', 'Digest') self.test_data = os.path.join(DIR, 'testdata') self.XFORM_XML = os.path.join(self.test_data,'xform-024.xml') self.XFORM_XML_ALL_FIELDS = os.path.join(self.test_data,'xform_all_fields.xml')
def _get_digest_client(self): self._set_require_auth(True) client = DigestClient() client.set_authorization('bob', 'bob', 'Digest') return client