diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_views.py b/openedx/core/djangoapps/user_api/accounts/tests/test_views.py index dcdfadfafb..8b86f1823f 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_views.py @@ -27,6 +27,7 @@ from openedx.core.djangoapps.user_api.accounts import ACCOUNT_VISIBILITY_PREF_KE from openedx.core.djangoapps.user_api.models import UserPreference from openedx.core.djangoapps.user_api.preferences.api import set_user_preference from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms +from openedx.core.lib.token_utils import JwtBuilder from student.models import UserProfile, LanguageProficiency, PendingEmailChange from student.tests.factories import ( AdminFactory, ContentTypeFactory, TEST_PASSWORD, PermissionFactory, SuperuserFactory, UserFactory @@ -829,12 +830,20 @@ class TestAccountDeactivation(TestCase): def setUp(self): super(TestAccountDeactivation, self).setUp() - self.superuser = SuperuserFactory() - self.staff_user = AdminFactory() self.test_user = UserFactory() self.url = reverse('accounts_deactivation', kwargs={'username': self.test_user.username}) - def assert_activation_status(self, expected_status=status.HTTP_200_OK, expected_activation_status=False): + def build_jwt_headers(self, user): + """ + Helper function for creating headers for the JWT authentication. + """ + token = JwtBuilder(user).build_token([]) + headers = { + 'HTTP_AUTHORIZATION': 'JWT ' + token + } + return headers + + def assert_activation_status(self, headers, expected_status=status.HTTP_200_OK, expected_activation_status=False): """ Helper function for making a request to the deactivation endpoint, and asserting the status. @@ -842,7 +851,8 @@ class TestAccountDeactivation(TestCase): expected_status(int): Expected request's response status. expected_activation_status(bool): Expected user has_usable_password attribute value. """ - response = self.client.post(self.url) + self.assertTrue(self.test_user.has_usable_password()) # pylint: disable=no-member + response = self.client.post(self.url, **headers) self.assertEqual(response.status_code, expected_status) self.test_user.refresh_from_db() # pylint: disable=no-member self.assertEqual(self.test_user.has_usable_password(), expected_activation_status) # pylint: disable=no-member @@ -851,9 +861,9 @@ class TestAccountDeactivation(TestCase): """ Verify a user is deactivated when a superuser posts to the deactivation endpoint. """ - self.client.login(username=self.superuser.username, password=TEST_PASSWORD) - self.assertTrue(self.test_user.has_usable_password()) # pylint: disable=no-member - self.assert_activation_status() + superuser = SuperuserFactory() + headers = self.build_jwt_headers(superuser) + self.assert_activation_status(headers) def test_user_with_permission_deactivates_user(self): """ @@ -867,17 +877,28 @@ class TestAccountDeactivation(TestCase): ) ) user.user_permissions.add(permission) # pylint: disable=no-member - self.client.login(username=user.username, password=TEST_PASSWORD) + headers = self.build_jwt_headers(user) self.assertTrue(self.test_user.has_usable_password()) # pylint: disable=no-member - self.assert_activation_status() + self.assert_activation_status(headers) def test_unauthorized_rejection(self): """ Verify unauthorized users cannot deactivate accounts. """ - self.client.login(username=self.test_user.username, password=TEST_PASSWORD) - self.assertTrue(self.test_user.has_usable_password()) # pylint: disable=no-member + headers = self.build_jwt_headers(self.test_user) self.assert_activation_status( + headers, expected_status=status.HTTP_403_FORBIDDEN, expected_activation_status=True ) + + def test_on_jwt_headers_rejection(self): + """ + Verify users who are not JWT authenticated are rejected. + """ + user = UserFactory() + self.assert_activation_status( + {}, + expected_status=status.HTTP_401_UNAUTHORIZED, + expected_activation_status=True + ) diff --git a/openedx/core/djangoapps/user_api/accounts/views.py b/openedx/core/djangoapps/user_api/accounts/views.py index de79f61fb1..2ae88d2548 100644 --- a/openedx/core/djangoapps/user_api/accounts/views.py +++ b/openedx/core/djangoapps/user_api/accounts/views.py @@ -229,6 +229,7 @@ class AccountDeactivationView(APIView): Account deactivation viewset. Currently only supports POST requests. Only admins can deactivate accounts. """ + authentication_classes = (JwtAuthentication, ) permission_classes = (permissions.IsAuthenticated, CanDeactivateUser) def post(self, request, username):