From 953c29c12dc19daef6fcdba2bd5b902680f3bd16 Mon Sep 17 00:00:00 2001 From: mkdk Date: Wed, 19 Sep 2018 23:08:40 +0300 Subject: [PATCH 1/6] added request.method == 'options' --- rest_framework/permissions.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index a48058e66..898bd0e95 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -44,8 +44,10 @@ class IsAuthenticated(BasePermission): """ Allows access only to authenticated users. """ - + # DRF should authorize all OPTIONS requests by default #5616 def has_permission(self, request, view): + if request.method == 'OPTIONS': + return True return request.user and request.user.is_authenticated From cc7deac7677fee24bf047121336081cce0b8e83a Mon Sep 17 00:00:00 2001 From: mkdk Date: Fri, 21 Sep 2018 21:42:17 +0300 Subject: [PATCH 2/6] #ref 5616. Add IsAuthenticatedOrOptionsOnly class in permissions, and made tests for that --- rest_framework/permissions.py | 11 +++++++++++ tests/test_permissions.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 898bd0e95..8b6e92215 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -51,6 +51,17 @@ class IsAuthenticated(BasePermission): return request.user and request.user.is_authenticated +class IsAuthenticatedOrOptionsOnly(BasePermission): + """ + Allows access only to authenticated users. + """ + + def has_permission(self, request, view): + if request.method == 'OPTIONS': + return True + return request.user and request.user.is_authenticated + + class IsAdminUser(BasePermission): """ Allows access only to admin users. diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 37540eb8e..96926ed70 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -522,3 +522,36 @@ class CustomPermissionsTests(TestCase): detail = response.data.get('detail') self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(detail, self.custom_message) + + +class IsAuthenticatedOrOptionsOnlyAllowedView(generics.RetrieveUpdateDestroyAPIView): + queryset = BasicModel.objects.all() + serializer_class = BasicSerializer + authentication_classes = [authentication.BasicAuthentication] + permissions_classes = (permissions.IsAuthenticatedOrOptionsOnly,) + + +options_view = IsAuthenticatedOrOptionsOnlyAllowedView.as_view() + + +class IsAuthenticatedOrOptionsOnlyAllowedTests(TestCase): + def setUp(self): + BasicModel(text='foo').save() + User.objects.create_user('username', 'username@example.com', 'password') + + def test_options_allowed_if_not_authentificated(self): + self.request = factory.options('/1', format='json') + response = options_view(self.request, pk=1) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_options_get_not_allowed_if_not_authentificated(self): + credentials = basic_auth_header('username', 'wrongpassword') + self.request = factory.get('/1', format='json', HTTP_AUTHORIZATION=credentials) + response = options_view(self.request, pk=1) + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + + def test_options_get_allowed_if_authentificated(self): + credentials = basic_auth_header('username', 'password') + self.request = factory.get('/1', format='json', HTTP_AUTHORIZATION=credentials) + response = options_view(self.request, pk=1) + self.assertEqual(response.status_code, status.HTTP_200_OK) \ No newline at end of file From 6a8ee5fe5b73e72d6794f9703ff36089f8a6a58c Mon Sep 17 00:00:00 2001 From: mkdk Date: Fri, 21 Sep 2018 21:46:34 +0300 Subject: [PATCH 3/6] fix docstring --- rest_framework/permissions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py index 8b6e92215..2dd8633db 100644 --- a/rest_framework/permissions.py +++ b/rest_framework/permissions.py @@ -53,7 +53,7 @@ class IsAuthenticated(BasePermission): class IsAuthenticatedOrOptionsOnly(BasePermission): """ - Allows access only to authenticated users. + Allows access only to authenticated users or for OPTIONS method. """ def has_permission(self, request, view): From 4da1486836e934f2e235d3bc30b5705e8558209c Mon Sep 17 00:00:00 2001 From: mkdk Date: Sat, 22 Sep 2018 00:09:43 +0300 Subject: [PATCH 4/6] invocation error --- .gitignore | 2 ++ tests/test_permissions.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 41768084c..4e3d8072a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ *.db *~ .* +.tox/ +.venv/ /site/ /htmlcov/ diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 96926ed70..decfacd41 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -554,4 +554,5 @@ class IsAuthenticatedOrOptionsOnlyAllowedTests(TestCase): credentials = basic_auth_header('username', 'password') self.request = factory.get('/1', format='json', HTTP_AUTHORIZATION=credentials) response = options_view(self.request, pk=1) - self.assertEqual(response.status_code, status.HTTP_200_OK) \ No newline at end of file + self.assertEqual(response.status_code, status.HTTP_200_OK) + \ No newline at end of file From 6825950664f286fb6c6d476a32a1bc08b2590e7d Mon Sep 17 00:00:00 2001 From: mkdk Date: Sat, 22 Sep 2018 08:00:29 +0300 Subject: [PATCH 5/6] whitespace error flake8 --- tests/test_permissions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index decfacd41..feed5760f 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -555,4 +555,3 @@ class IsAuthenticatedOrOptionsOnlyAllowedTests(TestCase): self.request = factory.get('/1', format='json', HTTP_AUTHORIZATION=credentials) response = options_view(self.request, pk=1) self.assertEqual(response.status_code, status.HTTP_200_OK) - \ No newline at end of file From 27bcc39da3bb21e9e3a447f03591bb2d506f6897 Mon Sep 17 00:00:00 2001 From: mkdk Date: Fri, 12 Oct 2018 11:28:09 +0300 Subject: [PATCH 6/6] flake8 fix --- tests/test_permissions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 67337d333..91430cc7a 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -573,7 +573,8 @@ class IsAuthenticatedOrOptionsOnlyAllowedTests(TestCase): self.request = factory.get('/1', format='json', HTTP_AUTHORIZATION=credentials) response = options_view(self.request, pk=1) self.assertEqual(response.status_code, status.HTTP_200_OK) - + + class FakeUser: def __init__(self, auth=False): self.is_authenticated = auth