diff --git a/openedx/core/djangoapps/user_api/accounts/permissions.py b/openedx/core/djangoapps/user_api/accounts/permissions.py index 459f0129fb..8c99911f32 100644 --- a/openedx/core/djangoapps/user_api/accounts/permissions.py +++ b/openedx/core/djangoapps/user_api/accounts/permissions.py @@ -36,13 +36,13 @@ class CanReplaceUsername(permissions.BasePermission): return request.user.username == getattr(settings, "USERNAME_REPLACEMENT_WORKER", False) -class CanGetAccountInfoUsingId(permissions.BasePermission): +class CanGetAccountInfo(permissions.BasePermission): """ Grants access to AccountViewSet if the requesting user is a superuser/staff - and reqesting to get account info based on LMS User id + and requesting to get account info based on non-public information. """ def has_permission(self, request, view): - return request.GET.get('lms_user_id') is None or ( - request.GET.get('lms_user_id') and (request.user.is_staff or request.user.is_superuser) + return (request.GET.get('lms_user_id') is None and request.GET.get('email') is None) or ( + request.user.is_staff or request.user.is_superuser ) 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 75ee16ffe4..341da0aeae 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_views.py @@ -370,15 +370,12 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): assert response.data["activation_key"] is not None - @ddt.data( - ("client", "user"), - ("staff_client", "staff_user"), - ) - @ddt.unpack - def test_get_account_by_email(self, api_client, user): + def test_successful_get_account_by_email(self): """ - Test that requesting a user email search works. + Test that request using email by a staff user successfully retrieves Account Info. """ + api_client = "staff_client" + user = "staff_user" client = self.login_client(api_client, user) self.create_mock_profile(self.user) set_user_preference(self.user, ACCOUNT_VISIBILITY_PREF_KEY, PRIVATE_VISIBILITY) @@ -386,6 +383,21 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): response = self.send_get(client, query_parameters=f'email={self.user.email}') self._verify_full_account_response(response) + def test_unsuccessful_get_account_by_email(self): + """ + Test that request using email by a normal user fails to retrieve Account Info. + """ + api_client = "client" + user = "user" + client = self.login_client(api_client, user) + self.create_mock_profile(self.user) + set_user_preference(self.user, ACCOUNT_VISIBILITY_PREF_KEY, PRIVATE_VISIBILITY) + + response = self.send_get( + client, query_parameters=f'email={self.user.email}', expected_status=status.HTTP_403_FORBIDDEN + ) + assert response.data.get('detail') == 'You do not have permission to perform this action.' + def test_successful_get_account_by_user_id(self): """ Test that request using lms user id by a staff user successfully retrieves Account Info. @@ -514,7 +526,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase): response = self.send_get(client, query_parameters='view=shared') verify_fields_visible_to_all_users(response) - response = self.send_get(client, query_parameters=f'view=shared&email={self.user.email}') + response = self.send_get(client, query_parameters=f'view=shared&username={self.user.username}') verify_fields_visible_to_all_users(response) @ddt.data( diff --git a/openedx/core/djangoapps/user_api/accounts/views.py b/openedx/core/djangoapps/user_api/accounts/views.py index 840e3db372..7d932cc475 100644 --- a/openedx/core/djangoapps/user_api/accounts/views.py +++ b/openedx/core/djangoapps/user_api/accounts/views.py @@ -73,7 +73,7 @@ from ..models import ( UserRetirementStatus ) from .api import get_account_settings, update_account_settings -from .permissions import CanDeactivateUser, CanGetAccountInfoUsingId, CanReplaceUsername, CanRetireUser +from .permissions import CanDeactivateUser, CanGetAccountInfo, CanReplaceUsername, CanRetireUser from .serializers import ( PendingNameChangeSerializer, UserRetirementPartnerReportSerializer, @@ -290,7 +290,7 @@ class AccountViewSet(ViewSet): authentication_classes = ( JwtAuthentication, BearerAuthenticationAllowInactiveUser, SessionAuthenticationAllowInactiveUser ) - permission_classes = (permissions.IsAuthenticated, CanGetAccountInfoUsingId) + permission_classes = (permissions.IsAuthenticated, CanGetAccountInfo) parser_classes = (JSONParser, MergePatchParser,) def get(self, request): @@ -302,7 +302,7 @@ class AccountViewSet(ViewSet): def list(self, request): """ GET /api/user/v1/accounts?username={username1,username2} - GET /api/user/v1/accounts?email={user_email} + GET /api/user/v1/accounts?email={user_email} (Staff Only) GET /api/user/v1/accounts?lms_user_id={lms_user_id} (Staff Only) """ usernames = request.GET.get('username')