From 12e5244720aa00cc8a54725da68162e9acc50400 Mon Sep 17 00:00:00 2001 From: Rene Sorel Date: Thu, 8 Sep 2016 13:16:49 +0200 Subject: [PATCH] user api endpoint for logged in users info --- .../user_api/accounts/tests/test_views.py | 142 ++++++++++-------- .../djangoapps/user_api/accounts/views.py | 13 ++ openedx/core/djangoapps/user_api/urls.py | 4 + 3 files changed, 99 insertions(+), 60 deletions(-) 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 72c03d0f8e..f3642b319a 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_views.py @@ -112,28 +112,6 @@ class UserAPITestCase(APITestCase): legacy_profile.language_proficiencies.add(LanguageProficiency(code='en')) 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): """ Verify the profile image data in a GET response for self.user @@ -160,6 +138,88 @@ class TestAccountAPI(CacheIsolationTestCase, UserAPITestCase): } ) + +@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 Accounts API. + """ + + ENABLED_CACHES = ['default'] + + def setUp(self): + super(TestAccountAPI, self).setUp() + + self.url = reverse("account_api") + + def test_get_account_default(self): + """ + Test that a client (logged in) can get her own account information (using default legacy profile information, + as created by the test UserFactory). + """ + def verify_get_own_information(queries): + """ + Internal helper to perform the actual assertions + """ + with self.assertNumQueries(queries): + response = self.send_get(self.client) + data = response.data + self.assertEqual(17, len(data)) + self.assertEqual(self.user.username, data["username"]) + self.assertEqual(self.user.first_name + " " + self.user.last_name, data["name"]) + for empty_field in ("year_of_birth", "level_of_education", "mailing_address", "bio"): + self.assertIsNone(data[empty_field]) + self.assertIsNone(data["country"]) + self.assertEqual("m", data["gender"]) + self.assertEqual("Learn a lot", data["goals"]) + self.assertEqual(self.user.email, data["email"]) + self.assertIsNotNone(data["date_joined"]) + self.assertEqual(self.user.is_active, data["is_active"]) + self._verify_profile_image_data(data, False) + self.assertTrue(data["requires_parental_consent"]) + self.assertEqual([], data["language_proficiencies"]) + self.assertEqual(PRIVATE_VISIBILITY, data["account_privacy"]) + # Badges aren't on by default, so should not be present. + self.assertEqual(False, data["accomplishments_shared"]) + + self.client.login(username=self.user.username, password=self.test_password) + verify_get_own_information(17) + + # Now make sure that the user can get the same information, even if not active + self.user.is_active = False + self.user.save() + verify_get_own_information(11) + + +@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): """ Verify that the shareable fields from the account are returned @@ -306,44 +366,6 @@ class TestAccountAPI(CacheIsolationTestCase, UserAPITestCase): response = self.send_get(client, query_parameters='view=shared') verify_fields_visible_to_all_users(response) - def test_get_account_default(self): - """ - Test that a client (logged in) can get her own account information (using default legacy profile information, - as created by the test UserFactory). - """ - def verify_get_own_information(queries): - """ - Internal helper to perform the actual assertions - """ - with self.assertNumQueries(queries): - response = self.send_get(self.client) - data = response.data - self.assertEqual(17, len(data)) - self.assertEqual(self.user.username, data["username"]) - self.assertEqual(self.user.first_name + " " + self.user.last_name, data["name"]) - for empty_field in ("year_of_birth", "level_of_education", "mailing_address", "bio"): - self.assertIsNone(data[empty_field]) - self.assertIsNone(data["country"]) - self.assertEqual("m", data["gender"]) - self.assertEqual("Learn a lot", data["goals"]) - self.assertEqual(self.user.email, data["email"]) - self.assertIsNotNone(data["date_joined"]) - self.assertEqual(self.user.is_active, data["is_active"]) - self._verify_profile_image_data(data, False) - self.assertTrue(data["requires_parental_consent"]) - self.assertEqual([], data["language_proficiencies"]) - self.assertEqual(PRIVATE_VISIBILITY, data["account_privacy"]) - # Badges aren't on by default, so should not be present. - self.assertEqual(False, data["accomplishments_shared"]) - - self.client.login(username=self.user.username, password=self.test_password) - verify_get_own_information(17) - - # Now make sure that the user can get the same information, even if not active - self.user.is_active = False - self.user.save() - verify_get_own_information(11) - def test_get_account_empty_string(self): """ Test the conversion of empty strings to None for certain fields. diff --git a/openedx/core/djangoapps/user_api/accounts/views.py b/openedx/core/djangoapps/user_api/accounts/views.py index a95a1b6646..abf46ffef5 100644 --- a/openedx/core/djangoapps/user_api/accounts/views.py +++ b/openedx/core/djangoapps/user_api/accounts/views.py @@ -29,6 +29,7 @@ class AccountViewSet(ViewSet): **Example Requests** + GET /api/user/v1/me[?view=shared] GET /api/user/v1/accounts?usernames={username1,username2}[?view=shared] GET /api/user/v1/accounts/{username}/[?view=shared] @@ -147,6 +148,18 @@ class AccountViewSet(ViewSet): permission_classes = (permissions.IsAuthenticated,) parser_classes = (MergePatchParser,) + def get(self, request): + """ + GET /api/user/v1/me + """ + try: + account_settings = get_account_settings( + request, [request.user.username], view=request.query_params.get('view')) + except UserNotFound: + return Response(status=status.HTTP_403_FORBIDDEN if request.user.is_staff else status.HTTP_404_NOT_FOUND) + + return Response(account_settings[0]) + def list(self, request): """ GET /api/user/v1/accounts?username={username1,username2} diff --git a/openedx/core/djangoapps/user_api/urls.py b/openedx/core/djangoapps/user_api/urls.py index 8aa44ad9ec..9655a6e523 100644 --- a/openedx/core/djangoapps/user_api/urls.py +++ b/openedx/core/djangoapps/user_api/urls.py @@ -10,6 +10,9 @@ from .accounts.views import AccountViewSet from .preferences.views import PreferencesView, PreferencesDetailView from .verification_api.views import PhotoVerificationStatusView +ME = AccountViewSet.as_view({ + 'get': 'get', +}) ACCOUNT_LIST = AccountViewSet.as_view({ 'get': 'list', @@ -22,6 +25,7 @@ ACCOUNT_DETAIL = AccountViewSet.as_view({ urlpatterns = patterns( '', + url(r'^v1/me$', ME, name='account_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(