Commit c3c86b8b by sanfordstudent Committed by GitHub

Merge pull request #14276 from edx/sstudent/me

Add /me endpoint for retrieving own username when logged in.
parents e36cf4a5 68daaf43
...@@ -112,28 +112,6 @@ class UserAPITestCase(APITestCase): ...@@ -112,28 +112,6 @@ class UserAPITestCase(APITestCase):
legacy_profile.language_proficiencies.add(LanguageProficiency(code='en')) legacy_profile.language_proficiencies.add(LanguageProficiency(code='en'))
legacy_profile.save() legacy_profile.save()
@ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Account APIs are only supported in LMS')
@patch('openedx.core.djangoapps.user_api.accounts.image_helpers._PROFILE_IMAGE_SIZES', [50, 10])
@patch.dict(
'openedx.core.djangoapps.user_api.accounts.image_helpers.PROFILE_IMAGE_SIZES_MAP',
{'full': 50, 'small': 10},
clear=True
)
@attr(shard=2)
class TestAccountAPI(CacheIsolationTestCase, UserAPITestCase):
"""
Unit tests for the Account API.
"""
ENABLED_CACHES = ['default']
def setUp(self):
super(TestAccountAPI, self).setUp()
self.url = reverse("accounts_api", kwargs={'username': self.user.username})
def _verify_profile_image_data(self, data, has_profile_image): def _verify_profile_image_data(self, data, has_profile_image):
""" """
Verify the profile image data in a GET response for self.user Verify the profile image data in a GET response for self.user
...@@ -160,6 +138,81 @@ class TestAccountAPI(CacheIsolationTestCase, UserAPITestCase): ...@@ -160,6 +138,81 @@ class TestAccountAPI(CacheIsolationTestCase, UserAPITestCase):
} }
) )
@ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Account APIs are only supported in LMS')
@attr(shard=2)
class TestOwnUsernameAPI(CacheIsolationTestCase, UserAPITestCase):
"""
Unit tests for the Accounts API.
"""
ENABLED_CACHES = ['default']
def setUp(self):
super(TestOwnUsernameAPI, self).setUp()
self.url = reverse("own_username_api")
def _verify_get_own_username(self, queries, expected_status=200):
"""
Internal helper to perform the actual assertion
"""
with self.assertNumQueries(queries):
response = self.send_get(self.client, expected_status=expected_status)
if expected_status == 200:
data = response.data
self.assertEqual(1, len(data))
self.assertEqual(self.user.username, data["username"])
def test_get_username(self):
"""
Test that a client (logged in) can get her own username.
"""
self.client.login(username=self.user.username, password=self.test_password)
self._verify_get_own_username(15)
def test_get_username_inactive(self):
"""
Test that a logged-in client can get their
username, even if inactive.
"""
self.client.login(username=self.user.username, password=self.test_password)
self.user.is_active = False
self.user.save()
self._verify_get_own_username(15)
def test_get_username_not_logged_in(self):
"""
Test that a client (not logged in) gets a 401
when trying to retrieve their username.
"""
# verify that the endpoint is inaccessible when not logged in
self._verify_get_own_username(12, expected_status=401)
@ddt.ddt
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Account APIs are only supported in LMS')
@patch('openedx.core.djangoapps.user_api.accounts.image_helpers._PROFILE_IMAGE_SIZES', [50, 10])
@patch.dict(
'openedx.core.djangoapps.user_api.accounts.image_helpers.PROFILE_IMAGE_SIZES_MAP',
{'full': 50, 'small': 10},
clear=True
)
@attr(shard=2)
class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
"""
Unit tests for the Accounts API.
"""
ENABLED_CACHES = ['default']
def setUp(self):
super(TestAccountsAPI, self).setUp()
self.url = reverse("accounts_api", kwargs={'username': self.user.username})
def _verify_full_shareable_account_response(self, response, account_privacy=None, badges_enabled=False): def _verify_full_shareable_account_response(self, response, account_privacy=None, badges_enabled=False):
""" """
Verify that the shareable fields from the account are returned Verify that the shareable fields from the account are returned
...@@ -311,6 +364,7 @@ class TestAccountAPI(CacheIsolationTestCase, UserAPITestCase): ...@@ -311,6 +364,7 @@ class TestAccountAPI(CacheIsolationTestCase, UserAPITestCase):
Test that a client (logged in) can get her own account information (using default legacy profile information, Test that a client (logged in) can get her own account information (using default legacy profile information,
as created by the test UserFactory). as created by the test UserFactory).
""" """
def verify_get_own_information(queries): def verify_get_own_information(queries):
""" """
Internal helper to perform the actual assertions Internal helper to perform the actual assertions
......
...@@ -29,12 +29,22 @@ class AccountViewSet(ViewSet): ...@@ -29,12 +29,22 @@ class AccountViewSet(ViewSet):
**Example Requests** **Example Requests**
GET /api/user/v1/me[?view=shared]
GET /api/user/v1/accounts?usernames={username1,username2}[?view=shared] GET /api/user/v1/accounts?usernames={username1,username2}[?view=shared]
GET /api/user/v1/accounts/{username}/[?view=shared] GET /api/user/v1/accounts/{username}/[?view=shared]
PATCH /api/user/v1/accounts/{username}/{"key":"value"} "application/merge-patch+json" PATCH /api/user/v1/accounts/{username}/{"key":"value"} "application/merge-patch+json"
**Response Values for GET** **Response Values for GET requests to the /me endpoint**
If the user is not logged in, an HTTP 401 "Not Authorized" response
is returned.
Otherwise, an HTTP 200 "OK" response is returned. The response
contains the following value:
* username: The username associated with the account.
**Response Values for GET requests to /accounts endpoints**
If no user exists with the specified username, an HTTP 404 "Not If no user exists with the specified username, an HTTP 404 "Not
Found" response is returned. Found" response is returned.
...@@ -147,6 +157,12 @@ class AccountViewSet(ViewSet): ...@@ -147,6 +157,12 @@ class AccountViewSet(ViewSet):
permission_classes = (permissions.IsAuthenticated,) permission_classes = (permissions.IsAuthenticated,)
parser_classes = (MergePatchParser,) parser_classes = (MergePatchParser,)
def get(self, request):
"""
GET /api/user/v1/me
"""
return Response({'username': request.user.username})
def list(self, request): def list(self, request):
""" """
GET /api/user/v1/accounts?username={username1,username2} GET /api/user/v1/accounts?username={username1,username2}
......
...@@ -10,6 +10,9 @@ from .accounts.views import AccountViewSet ...@@ -10,6 +10,9 @@ from .accounts.views import AccountViewSet
from .preferences.views import PreferencesView, PreferencesDetailView from .preferences.views import PreferencesView, PreferencesDetailView
from .verification_api.views import PhotoVerificationStatusView from .verification_api.views import PhotoVerificationStatusView
ME = AccountViewSet.as_view({
'get': 'get',
})
ACCOUNT_LIST = AccountViewSet.as_view({ ACCOUNT_LIST = AccountViewSet.as_view({
'get': 'list', 'get': 'list',
...@@ -22,6 +25,7 @@ ACCOUNT_DETAIL = AccountViewSet.as_view({ ...@@ -22,6 +25,7 @@ ACCOUNT_DETAIL = AccountViewSet.as_view({
urlpatterns = patterns( urlpatterns = patterns(
'', '',
url(r'^v1/me$', ME, name='own_username_api'),
url(r'^v1/accounts/{}$'.format(settings.USERNAME_PATTERN), ACCOUNT_DETAIL, name='accounts_api'), url(r'^v1/accounts/{}$'.format(settings.USERNAME_PATTERN), ACCOUNT_DETAIL, name='accounts_api'),
url(r'^v1/accounts$', ACCOUNT_LIST, name='accounts_detail_api'), url(r'^v1/accounts$', ACCOUNT_LIST, name='accounts_detail_api'),
url( url(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment