From 328a5f0875e301c0c0747e5d305e4e98c441d1a4 Mon Sep 17 00:00:00 2001 From: Ukang'a Dickson Date: Sat, 4 May 2019 22:51:49 +0300 Subject: [PATCH 1/3] Add a flake8 pre-commit.sh file --- README.rst | 7 +++++++ pre-commit.sh | 4 ++++ 2 files changed, 11 insertions(+) create mode 100755 pre-commit.sh diff --git a/README.rst b/README.rst index 01980a45b1..6eb4e192cb 100644 --- a/README.rst +++ b/README.rst @@ -56,6 +56,13 @@ Edit top level requirements in the file `requirements/base.in `_ into `.git/hooks/pre-commit`, it ensures staged python flake8 are in acceptable code style and conventions. + +.. code-block:: sh + + cp pre-commit.sh .git/hooks/pre-commit + chmod +x .git/hooks/pre-commit + **Security Acknowledgments** We would like to thank the following security researchers for responsibly disclosing security issues: diff --git a/pre-commit.sh b/pre-commit.sh new file mode 100755 index 0000000000..6d403bcc35 --- /dev/null +++ b/pre-commit.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# +# flake8 check +exec git diff --staged --name-only | grep -E '\.py$' | xargs flake8 --exclude=migrations - From 6200a24a7e351d778ed0e0a4160b83f09f3949d4 Mon Sep 17 00:00:00 2001 From: Ukang'a Dickson Date: Tue, 23 Apr 2019 18:45:09 +0300 Subject: [PATCH 2/3] Check report_xform permission on enketo URL requests --- onadata/apps/api/viewsets/xform_viewset.py | 2 +- onadata/libs/filters.py | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/onadata/apps/api/viewsets/xform_viewset.py b/onadata/apps/api/viewsets/xform_viewset.py index f80cf0998e..da946adb0c 100644 --- a/onadata/apps/api/viewsets/xform_viewset.py +++ b/onadata/apps/api/viewsets/xform_viewset.py @@ -274,7 +274,7 @@ class XFormViewSet(AnonymousUserPublicFormsMixin, permission_classes = [XFormPermissions, ] updatable_fields = set(('description', 'downloadable', 'require_auth', 'shared', 'shared_data', 'title')) - filter_backends = (filters.AnonDjangoObjectPermissionFilter, + filter_backends = (filters.EnketoAnonDjangoObjectPermissionFilter, filters.TagFilter, filters.XFormOwnerFilter, DjangoFilterBackend) diff --git a/onadata/libs/filters.py b/onadata/libs/filters.py index 8fea1ea6a5..2f17080776 100644 --- a/onadata/libs/filters.py +++ b/onadata/libs/filters.py @@ -41,6 +41,22 @@ def filter_queryset(self, request, queryset, view): .filter_queryset(request, queryset, view) +# pylint: disable=too-few-public-methods +class EnketoAnonDjangoObjectPermissionFilter(AnonDjangoObjectPermissionFilter): + """EnketoAnonDjangoObjectPermissionFilter + + Same as AnonDjangoObjectPermissionFilter but checks 'report_xform' + permission when the view 'enketo' is accessed. + """ + + def filter_queryset(self, request, queryset, view): + """Check report_xform permission when requesting for Enketo URL.""" + if view.action == 'enketo': + self.perm_format = '%(app_label)s.report_%(model_name)s' # noqa pylint: disable=W0201 + return super(EnketoAnonDjangoObjectPermissionFilter, self)\ + .filter_queryset(request, queryset, view) + + class XFormListObjectPermissionFilter(AnonDjangoObjectPermissionFilter): perm_format = '%(app_label)s.report_%(model_name)s' From e24ea13b6fcb0c8c24b689e429aa145d83a97983 Mon Sep 17 00:00:00 2001 From: Ukang'a Dickson Date: Sat, 4 May 2019 22:37:13 +0300 Subject: [PATCH 3/3] Test that read only has no access to a web form --- .../api/tests/viewsets/test_xform_viewset.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/onadata/apps/api/tests/viewsets/test_xform_viewset.py b/onadata/apps/api/tests/viewsets/test_xform_viewset.py index b9919cc9f5..5a2d97af39 100644 --- a/onadata/apps/api/tests/viewsets/test_xform_viewset.py +++ b/onadata/apps/api/tests/viewsets/test_xform_viewset.py @@ -751,6 +751,30 @@ def test_enketo_url(self): data = {"enketo_url": url, "enketo_preview_url": preview_url} self.assertEqual(response.data, data) + alice_data = {'username': 'alice', 'email': 'alice@localhost.com'} + alice_profile = self._create_user_profile(alice_data) + credentials = { + 'HTTP_AUTHORIZATION': ( + 'Token %s' % alice_profile.user.auth_token) + } + request = self.factory.get('/', **credentials) + response = view(request, pk=formid) + # Alice has no permissions to the form hence no access to web form + self.assertEqual(response.status_code, 404) + + # Give Alice read-only permissions to the form + ReadOnlyRole.add(alice_profile.user, self.xform) + response = view(request, pk=formid) + # Alice with read-only access should not have access to web form + self.assertEqual(response.status_code, 404) + + # Give Alice data-entry permissions + DataEntryRole.add(alice_profile.user, self.xform) + response = view(request, pk=formid) + # Alice with data-entry access should have access to web form + self.assertEqual(response.status_code, 200) + self.assertEqual(response.data, data) + def test_get_single_submit_url(self): with HTTMock(enketo_preview_url_mock, enketo_url_mock, enketo_single_submission_mock):