예제 #1
0
    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)
예제 #2
0
    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)
예제 #3
0
 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
예제 #4
0
    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())
예제 #5
0
 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
예제 #6
0
    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)
예제 #7
0
 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)
예제 #8
0
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
예제 #9
0
    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)
예제 #10
0
 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
예제 #11
0
    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'))
예제 #12
0
    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)
예제 #13
0
    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)
예제 #14
0
    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)
예제 #15
0
    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)
예제 #16
0
    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)
예제 #17
0
 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