From 65f13ddec4da6b6c872c5408a6294f9352fb9a08 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Wed, 26 Apr 2017 11:29:56 -0400 Subject: [PATCH] Revert "Merge pull request #14868 from cpennington/learner-542" This reverts commit 88dd85caec2d720d59c8dab424763f34e3901744, reversing changes made to bf8aef33fce0199661ce031ed5b0a976ff62799e. --- cms/envs/aws.py | 2 - cms/envs/common.py | 2 - common/djangoapps/student/cookies.py | 6 +- .../courseware/tests/test_course_info.py | 4 +- lms/djangoapps/courseware/tests/test_i18n.py | 24 +-- lms/envs/aws.py | 2 - lms/envs/common.py | 2 - lms/envs/devstack_docker.py | 1 - openedx/core/djangoapps/lang_pref/__init__.py | 4 - .../core/djangoapps/lang_pref/middleware.py | 58 ++---- .../lang_pref/tests/test_middleware.py | 194 ++++++------------ openedx/core/djangoapps/lang_pref/views.py | 11 +- openedx/core/djangoapps/user_api/helpers.py | 8 +- .../core/djangoapps/user_api/serializers.py | 7 +- .../djangoapps/user_api/tests/test_helpers.py | 22 +- openedx/core/djangoapps/user_api/views.py | 6 +- 16 files changed, 108 insertions(+), 245 deletions(-) diff --git a/cms/envs/aws.py b/cms/envs/aws.py index 68f6237cf3..9285afe7e5 100644 --- a/cms/envs/aws.py +++ b/cms/envs/aws.py @@ -221,8 +221,6 @@ GIT_REPO_EXPORT_DIR = ENV_TOKENS.get('GIT_REPO_EXPORT_DIR', '/edx/var/edxapp/exp # Translation overrides LANGUAGES = ENV_TOKENS.get('LANGUAGES', LANGUAGES) LANGUAGE_CODE = ENV_TOKENS.get('LANGUAGE_CODE', LANGUAGE_CODE) -LANGUAGE_COOKIE = ENV_TOKENS.get('LANGUAGE_COOKIE', LANGUAGE_COOKIE) - USE_I18N = ENV_TOKENS.get('USE_I18N', USE_I18N) ENV_FEATURES = ENV_TOKENS.get('FEATURES', {}) diff --git a/cms/envs/common.py b/cms/envs/common.py index 7424af8803..eecd597497 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -547,8 +547,6 @@ TIME_ZONE = 'America/New_York' # http://en.wikipedia.org/wiki/List_of_tz_zones_ LANGUAGE_CODE = 'en' # http://www.i18nguy.com/unicode/language-identifiers.html LANGUAGES_BIDI = lms.envs.common.LANGUAGES_BIDI -LANGUAGE_COOKIE = lms.envs.common.LANGUAGE_COOKIE - LANGUAGES = lms.envs.common.LANGUAGES LANGUAGE_DICT = dict(LANGUAGES) diff --git a/common/djangoapps/student/cookies.py b/common/djangoapps/student/cookies.py index d204020ab9..454ed4e486 100644 --- a/common/djangoapps/student/cookies.py +++ b/common/djangoapps/student/cookies.py @@ -17,7 +17,7 @@ from student.models import CourseEnrollment CREATE_LOGON_COOKIE = Signal(providing_args=['user', 'response']) -def standard_cookie_settings(request): +def _get_cookie_settings(request): """ Returns the common cookie settings (e.g. expiration time). """ if request.session.get_expire_at_browser_close(): @@ -73,7 +73,7 @@ def set_logged_in_cookies(request, response, user): HttpResponse """ - cookie_settings = standard_cookie_settings(request) + cookie_settings = _get_cookie_settings(request) # Backwards compatibility: set the cookie indicating that the user # is logged in. This is just a boolean value, so it's not very useful. @@ -96,7 +96,7 @@ def set_logged_in_cookies(request, response, user): def set_user_info_cookie(response, request): """ Sets the user info cookie on the response. """ - cookie_settings = standard_cookie_settings(request) + cookie_settings = _get_cookie_settings(request) # In production, TLS should be enabled so that this cookie is encrypted # when we send it. We also need to set "secure" to True so that the browser diff --git a/lms/djangoapps/courseware/tests/test_course_info.py b/lms/djangoapps/courseware/tests/test_course_info.py index 0013f5ad02..9de1a6e56b 100644 --- a/lms/djangoapps/courseware/tests/test_course_info.py +++ b/lms/djangoapps/courseware/tests/test_course_info.py @@ -367,7 +367,7 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest self.assertEqual(resp.status_code, 200) def test_num_queries_instructor_paced(self): - self.fetch_course_info_with_queries(self.instructor_paced_course, 24, 4) + self.fetch_course_info_with_queries(self.instructor_paced_course, 21, 4) def test_num_queries_self_paced(self): - self.fetch_course_info_with_queries(self.self_paced_course, 24, 4) + self.fetch_course_info_with_queries(self.self_paced_course, 21, 4) diff --git a/lms/djangoapps/courseware/tests/test_i18n.py b/lms/djangoapps/courseware/tests/test_i18n.py index cafa3ed478..1d52ae06d7 100644 --- a/lms/djangoapps/courseware/tests/test_i18n.py +++ b/lms/djangoapps/courseware/tests/test_i18n.py @@ -2,7 +2,6 @@ Tests i18n in courseware """ -import json import re from django.conf import settings @@ -15,6 +14,8 @@ from nose.plugins.attrib import attr from openedx.core.djangoapps.dark_lang.models import DarkLangConfig from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY +from openedx.core.djangoapps.user_api.preferences.api import set_user_preference +from student.models import UserProfile from student.tests.factories import UserFactory @@ -60,7 +61,8 @@ class BaseI18nTestCase(TestCase): """ # Create one user and save it to the database email = 'test@edx.org' - self.user = UserFactory.create(username='test', email=email, password=self.pwd) + self.user = UserFactory.build(username='test', email=email, password=self.pwd) + self.user.save() def user_login(self): """ @@ -117,6 +119,7 @@ class I18nRegressionTests(BaseI18nTestCase): def test_unreleased_lang_resolution(self): # Regression test; LOC-85 + UserProfile.objects.create(user=self.user) self.release_languages('fa') self.user_login() @@ -133,6 +136,7 @@ class I18nRegressionTests(BaseI18nTestCase): self.assert_tag_has_attr(response.content, "html", "lang", "fa-ir") def test_preview_lang(self): + UserProfile.objects.create(user=self.user) self.user_login() # Regression test; LOC-87 @@ -168,17 +172,9 @@ class I18nLangPrefTests(BaseI18nTestCase): """ def setUp(self): super(I18nLangPrefTests, self).setUp() + UserProfile.objects.create(user=self.user) self.user_login() - def set_lang_preference(self, language): - """Sets the user's language preference, allowing the LangPref middleware to operate to set the preference cookie.""" - response = self.client.patch( - reverse('preferences_api', args=[self.user.username]), - json.dumps({LANGUAGE_KEY: language}), - content_type="application/merge-patch+json" - ) - self.assertEqual(response.status_code, 204) - def test_lang_preference(self): # Regression test; LOC-87 self.release_languages('ar, es-419') @@ -188,13 +184,13 @@ class I18nLangPrefTests(BaseI18nTestCase): self.assert_tag_has_attr(response.content, "html", "lang", self.site_lang) # Set user language preference - self.set_lang_preference('ar') + set_user_preference(self.user, LANGUAGE_KEY, 'ar') # and verify we now get an ar response response = self.client.get(self.url) self.assert_tag_has_attr(response.content, "html", "lang", 'ar') # Verify that switching language preference gives the right language - self.set_lang_preference('es-419') + set_user_preference(self.user, LANGUAGE_KEY, 'es-419') response = self.client.get(self.url) self.assert_tag_has_attr(response.content, "html", "lang", 'es-419') @@ -203,7 +199,7 @@ class I18nLangPrefTests(BaseI18nTestCase): self.release_languages('ar, es-419') # Set user language preference - self.set_lang_preference('ar') + set_user_preference(self.user, LANGUAGE_KEY, 'ar') # Verify preview-lang takes precedence self.client.post(self.preview_language_url, {'preview_lang': 'eo', 'set_language': 'set_language'}) response = self.client.get(self.url) diff --git a/lms/envs/aws.py b/lms/envs/aws.py index a88fcd1873..de1b4a800e 100644 --- a/lms/envs/aws.py +++ b/lms/envs/aws.py @@ -314,8 +314,6 @@ TIME_ZONE = ENV_TOKENS.get('TIME_ZONE', TIME_ZONE) LANGUAGES = ENV_TOKENS.get('LANGUAGES', LANGUAGES) LANGUAGE_DICT = dict(LANGUAGES) LANGUAGE_CODE = ENV_TOKENS.get('LANGUAGE_CODE', LANGUAGE_CODE) -LANGUAGE_COOKIE = ENV_TOKENS.get('LANGUAGE_COOKIE', LANGUAGE_COOKIE) - USE_I18N = ENV_TOKENS.get('USE_I18N', USE_I18N) # Additional installed apps diff --git a/lms/envs/common.py b/lms/envs/common.py index b8f3a97e7e..fbba924d80 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -863,8 +863,6 @@ LANGUAGE_CODE = 'en' # http://www.i18nguy.com/unicode/language-identifiers.html # these languages display right to left LANGUAGES_BIDI = ("he", "ar", "fa", "ur", "fa-ir", "rtl") -LANGUAGE_COOKIE = "openedx-language-preference" - # Sourced from http://www.localeplanet.com/icu/ and wikipedia LANGUAGES = ( ('en', u'English'), diff --git a/lms/envs/devstack_docker.py b/lms/envs/devstack_docker.py index 58ecb1fff2..4a9b5e00e9 100644 --- a/lms/envs/devstack_docker.py +++ b/lms/envs/devstack_docker.py @@ -30,7 +30,6 @@ FEATURES.update({ 'ENABLE_COURSEWARE_SEARCH': False, 'ENABLE_COURSE_DISCOVERY': False, 'ENABLE_DASHBOARD_SEARCH': False, - 'SHOW_LANGUAGE_SELECTOR': True }) ENABLE_MKTG_SITE = os.environ.get('ENABLE_MARKETING_SITE', False) diff --git a/openedx/core/djangoapps/lang_pref/__init__.py b/openedx/core/djangoapps/lang_pref/__init__.py index a72ca0bb3b..4182bb6978 100644 --- a/openedx/core/djangoapps/lang_pref/__init__.py +++ b/openedx/core/djangoapps/lang_pref/__init__.py @@ -4,7 +4,3 @@ Useful information for setting the language preference # this is the UserPreference key for the user's preferred language LANGUAGE_KEY = 'pref-lang' - -LANGUAGE_HEADER = 'HTTP_ACCEPT_LANGUAGE' - -COOKIE_DURATION = 14 * 24 * 60 * 60 # 14 days in seconds diff --git a/openedx/core/djangoapps/lang_pref/middleware.py b/openedx/core/djangoapps/lang_pref/middleware.py index a0d89acfc4..e2352f0780 100644 --- a/openedx/core/djangoapps/lang_pref/middleware.py +++ b/openedx/core/djangoapps/lang_pref/middleware.py @@ -2,17 +2,12 @@ Middleware for Language Preferences """ -from django.conf import settings from django.utils.translation import LANGUAGE_SESSION_KEY from django.utils.translation.trans_real import parse_accept_lang_header -from openedx.core.djangoapps.lang_pref import ( - LANGUAGE_KEY, LANGUAGE_HEADER, COOKIE_DURATION -) -from openedx.core.djangoapps.user_api.preferences.api import ( - get_user_preference, delete_user_preference, set_user_preference -) -from openedx.core.djangoapps.user_api.errors import UserAPIInternalError, UserAPIRequestError +from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY +from openedx.core.djangoapps.lang_pref.api import released_languages +from openedx.core.djangoapps.user_api.preferences.api import get_user_preference, delete_user_preference class LanguagePreferenceMiddleware(object): @@ -26,46 +21,17 @@ class LanguagePreferenceMiddleware(object): def process_request(self, request): """ If a user's UserPreference contains a language preference, use the user's preference. - Save the current language preference cookie as the user's preferred language. """ - cookie_lang = request.COOKIES.get(settings.LANGUAGE_COOKIE, None) - if cookie_lang: - if request.user.is_authenticated(): - set_user_preference(request.user, LANGUAGE_KEY, cookie_lang) + languages = released_languages() + system_released_languages = [seq[0] for seq in languages] - accept_header = request.META.get(LANGUAGE_HEADER, None) - if accept_header: - current_langs = parse_accept_lang_header(accept_header) - # Promote the cookie_lang over any language currently in the accept header - current_langs = [(lang, qvalue) for (lang, qvalue) in current_langs if lang != cookie_lang] - current_langs.insert(0, (cookie_lang, 1)) - accept_header = ",".join("{};q={}".format(lang, qvalue) for (lang, qvalue) in current_langs) - else: - accept_header = cookie_lang - request.META[LANGUAGE_HEADER] = accept_header - - def process_response(self, request, response): # If the user is logged in, check for their language preference - if getattr(request, 'user', None) and request.user.is_authenticated(): + if request.user.is_authenticated(): # Get the user's language preference - try: - user_pref = get_user_preference(request.user, LANGUAGE_KEY) - except (UserAPIRequestError, UserAPIInternalError): - # If we can't find the user preferences, then don't modify the cookie - pass - else: - # Set it in the LANGUAGE_COOKIE - if user_pref: - response.set_cookie( - settings.LANGUAGE_COOKIE, - value=user_pref, - domain=settings.SESSION_COOKIE_DOMAIN, - max_age=COOKIE_DURATION, - ) + user_pref = get_user_preference(request.user, LANGUAGE_KEY) + # Set it to the LANGUAGE_SESSION_KEY (Django-specific session setting governing language pref) + if user_pref: + if user_pref in system_released_languages: + request.session[LANGUAGE_SESSION_KEY] = user_pref else: - response.delete_cookie( - settings.LANGUAGE_COOKIE, - domain=settings.SESSION_COOKIE_DOMAIN - ) - - return response + delete_user_preference(request.user, LANGUAGE_KEY) diff --git a/openedx/core/djangoapps/lang_pref/tests/test_middleware.py b/openedx/core/djangoapps/lang_pref/tests/test_middleware.py index e70f84e9d9..2664073fd4 100644 --- a/openedx/core/djangoapps/lang_pref/tests/test_middleware.py +++ b/openedx/core/djangoapps/lang_pref/tests/test_middleware.py @@ -2,22 +2,17 @@ Tests for lang_pref middleware. """ -import itertools import mock import ddt -from django.conf import settings from django.test import TestCase -from django.core.urlresolvers import reverse from django.test.client import RequestFactory -from django.http import HttpResponse from django.contrib.sessions.middleware import SessionMiddleware from django.utils.translation import LANGUAGE_SESSION_KEY -from django.utils.translation.trans_real import parse_accept_lang_header -from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY, COOKIE_DURATION +from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY from openedx.core.djangoapps.lang_pref.middleware import LanguagePreferenceMiddleware -from openedx.core.djangoapps.user_api.preferences.api import set_user_preference, get_user_preference, delete_user_preference +from openedx.core.djangoapps.user_api.preferences.api import set_user_preference, get_user_preference from student.tests.factories import UserFactory from student.tests.factories import AnonymousUserFactory @@ -39,134 +34,73 @@ class TestUserPreferenceMiddleware(TestCase): self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'ar;q=1.0' # pylint: disable=no-member self.session_middleware.process_request(self.request) - def test_logout_shouldnt_remove_cookie(self): + def test_no_language_set_in_session_or_prefs(self): + # nothing set in the session or the prefs + self.middleware.process_request(self.request) + self.assertNotIn(LANGUAGE_SESSION_KEY, self.request.session) # pylint: disable=no-member + @mock.patch( + 'openedx.core.djangoapps.lang_pref.middleware.released_languages', + mock.Mock(return_value=[('eo', 'esperanto')]) + ) + def test_language_in_user_prefs(self): + # language set in the user preferences and not the session + set_user_preference(self.user, LANGUAGE_KEY, 'eo') + self.middleware.process_request(self.request) + self.assertEquals(self.request.session[LANGUAGE_SESSION_KEY], 'eo') # pylint: disable=no-member + + @mock.patch( + 'openedx.core.djangoapps.lang_pref.middleware.released_languages', + mock.Mock(return_value=[('en', 'english'), ('eo', 'esperanto')]) + ) + def test_language_in_session(self): + # language set in both the user preferences and session, + # preference should get precedence. The session will hold the last value, + # which is probably the user's last preference. Look up the updated preference. + + # Dark lang middleware should run after this middleware, so it can + # set a session language as an override of the user's preference. + self.request.session[LANGUAGE_SESSION_KEY] = 'en' # pylint: disable=no-member + set_user_preference(self.user, LANGUAGE_KEY, 'eo') self.middleware.process_request(self.request) + self.assertEquals(self.request.session[LANGUAGE_SESSION_KEY], 'eo') # pylint: disable=no-member + + @mock.patch( + 'openedx.core.djangoapps.lang_pref.middleware.released_languages', + mock.Mock(return_value=[('eo', 'dummy Esperanto'), ('ar', 'arabic'), ('eu-es', 'euskara (Espainia)')]) + ) + @ddt.data('ar;q=1.0', 'eu;q=1.0', 'es-419;q=1.0') + def test_browser_language_in_session_for_unauthenticated_user(self, accept_language): + """ + test: browser language should not be set in user session for unauthenticated user. + """ + self.request.META['HTTP_ACCEPT_LANGUAGE'] = accept_language # pylint: disable=no-member self.request.user = self.anonymous_user - - response = mock.Mock(spec=HttpResponse) - self.middleware.process_response(self.request, response) - - response.delete_cookie.assert_not_called() - - @ddt.data(None, 'es', 'en') - def test_preference_setting_changes_cookie(self, lang_pref_out): - """ - Test that the LANGUAGE_COOKIE is always set to the user's current language preferences - at the end of the request, with an expiry that's the same as the users current session cookie. - """ - if lang_pref_out: - set_user_preference(self.user, LANGUAGE_KEY, lang_pref_out) - else: - delete_user_preference(self.user, LANGUAGE_KEY) - - response = mock.Mock(spec=HttpResponse) - self.middleware.process_response(self.request, response) - - if lang_pref_out: - response.set_cookie.assert_called_with( - settings.LANGUAGE_COOKIE, - value=lang_pref_out, - domain=settings.SESSION_COOKIE_DOMAIN, - max_age=COOKIE_DURATION, - ) - else: - response.delete_cookie.assert_called_with( - settings.LANGUAGE_COOKIE, - domain=settings.SESSION_COOKIE_DOMAIN, - ) - - self.assertNotIn(LANGUAGE_SESSION_KEY, self.request.session) - - @ddt.data(*itertools.product( - (None, 'eo', 'es'), # LANGUAGE_COOKIE - (None, 'es', 'en'), # Language Preference In - )) - @ddt.unpack - @mock.patch('openedx.core.djangoapps.lang_pref.middleware.set_user_preference') - def test_preference_cookie_changes_setting(self, lang_cookie, lang_pref_in, mock_set_user_preference): - self.request.COOKIES[settings.LANGUAGE_COOKIE] = lang_cookie - - if lang_pref_in: - set_user_preference(self.user, LANGUAGE_KEY, lang_pref_in) - else: - delete_user_preference(self.user, LANGUAGE_KEY) - self.middleware.process_request(self.request) + self.assertNotIn(LANGUAGE_SESSION_KEY, self.request.session) # pylint: disable=no-member - if lang_cookie is None: - self.assertEqual(mock_set_user_preference.mock_calls, []) - else: - mock_set_user_preference.assert_called_with(self.user, LANGUAGE_KEY, lang_cookie) - - @ddt.data(*( - (logged_in, ) + test_def - for logged_in in (True, False) - for test_def in [ - # (LANGUAGE_COOKIE, LANGUAGE_SESSION_KEY, Accept-Language In, Accept-Language Out) - (None, None, None, None), - (None, 'eo', None, None), - (None, 'eo', 'en', 'en'), - (None, None, 'en', 'en'), - ('en', None, None, 'en'), - ('en', None, 'eo', 'en;q=1.0,eo'), - ('en', None, 'en', 'en'), - ('en', 'eo', 'en', 'en'), - ('en', 'eo', 'eo', 'en;q=1.0,eo') - ] - )) - @ddt.unpack - def test_preference_cookie_overrides_browser(self, logged_in, lang_cookie, lang_session, accept_lang_in, accept_lang_out): - if not logged_in: - self.request.user = self.anonymous_user - if lang_cookie: - self.request.COOKIES[settings.LANGUAGE_COOKIE] = lang_cookie - if lang_session: - self.request.session[LANGUAGE_SESSION_KEY] = lang_session - if accept_lang_in: - self.request.META['HTTP_ACCEPT_LANGUAGE'] = accept_lang_in - else: - del self.request.META['HTTP_ACCEPT_LANGUAGE'] - + @mock.patch( + 'openedx.core.djangoapps.lang_pref.middleware.released_languages', + mock.Mock(return_value=[('en', 'english')]) + ) + def test_browser_language_not_be_in_session(self): + """ + test: browser language should not be set in user session if it is not supported by system. + """ + self.request.user = self.anonymous_user self.middleware.process_request(self.request) + self.assertNotEqual(self.request.session.get(LANGUAGE_SESSION_KEY), 'ar') # pylint: disable=no-member - accept_lang_result = self.request.META.get('HTTP_ACCEPT_LANGUAGE') - if accept_lang_result: - accept_lang_result = parse_accept_lang_header(accept_lang_result) - - if accept_lang_out: - accept_lang_out = parse_accept_lang_header(accept_lang_out) - - if accept_lang_out and accept_lang_result: - self.assertItemsEqual(accept_lang_result, accept_lang_out) - else: - self.assertEqual(accept_lang_result, accept_lang_out) - - self.assertEquals(self.request.session.get(LANGUAGE_SESSION_KEY), lang_session) - - @ddt.data(None, 'es', 'en') - def test_logout_preserves_cookie(self, lang_cookie): - if lang_cookie: - self.client.cookies[settings.LANGUAGE_COOKIE] = lang_cookie - elif settings.LANGUAGE_COOKIE in self.client.cookies: - del self.client.cookies[settings.LANGUAGE_COOKIE] - # Use an actual call to the logout endpoint, because the logout function - # explicitly clears all cookies - self.client.get(reverse('logout')) - if lang_cookie: - self.assertEqual( - self.client.cookies[settings.LANGUAGE_COOKIE].value, - lang_cookie - ) - else: - self.assertNotIn(settings.LANGUAGE_COOKIE, self.client.cookies) - - def test_process_response_no_user_noop(self): - del self.request.user - response = mock.Mock(spec=HttpResponse) - - result = self.middleware.process_response(self.request, response) - - self.assertIs(result, response) - self.assertEqual(response.mock_calls, []) + @mock.patch( + 'openedx.core.djangoapps.lang_pref.middleware.released_languages', + mock.Mock(return_value=[('en', 'english'), ('ar', 'arabic')]) + ) + def test_delete_user_lang_preference_not_supported_by_system(self): + """ + test: user preferred language has been removed from user preferences model if it is not supported by system + for authenticated users. + """ + set_user_preference(self.user, LANGUAGE_KEY, 'eo') + self.middleware.process_request(self.request) + self.assertEqual(get_user_preference(self.request.user, LANGUAGE_KEY), None) diff --git a/openedx/core/djangoapps/lang_pref/views.py b/openedx/core/djangoapps/lang_pref/views.py index cd47008c8a..0331ff2c8c 100644 --- a/openedx/core/djangoapps/lang_pref/views.py +++ b/openedx/core/djangoapps/lang_pref/views.py @@ -9,7 +9,7 @@ from django.http import HttpResponse from django.views.decorators.csrf import ensure_csrf_cookie from django.utils.translation import LANGUAGE_SESSION_KEY -from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY, COOKIE_DURATION +from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY @ensure_csrf_cookie @@ -17,16 +17,9 @@ def update_session_language(request): """ Update the language session key. """ - response = HttpResponse(200) if request.method == 'PATCH': data = json.loads(request.body) language = data.get(LANGUAGE_KEY, settings.LANGUAGE_CODE) if request.session.get(LANGUAGE_SESSION_KEY, None) != language: request.session[LANGUAGE_SESSION_KEY] = unicode(language) - response.set_cookie( - settings.LANGUAGE_COOKIE, - language, - domain=settings.SESSION_COOKIE_DOMAIN, - max_age=COOKIE_DURATION - ) - return response + return HttpResponse(200) diff --git a/openedx/core/djangoapps/user_api/helpers.py b/openedx/core/djangoapps/user_api/helpers.py index 851bf4914c..c2c62d6618 100644 --- a/openedx/core/djangoapps/user_api/helpers.py +++ b/openedx/core/djangoapps/user_api/helpers.py @@ -6,7 +6,6 @@ from collections import defaultdict from functools import wraps import logging import json -import traceback from django import forms from django.core.serializers.json import DjangoJSONEncoder @@ -66,19 +65,16 @@ def intercept_errors(api_error, ignore_errors=None): LOGGER.warning(msg) raise - caller = traceback.format_stack(limit=2)[0] - # Otherwise, log the error and raise the API-specific error msg = ( u"An unexpected error occurred when calling '{func_name}' " - u"with arguments '{args}' and keyword arguments '{kwargs}' from {caller}: " + u"with arguments '{args}' and keyword arguments '{kwargs}': " u"{exception}" ).format( func_name=func.func_name, args=args, kwargs=kwargs, - exception=ex.developer_message if hasattr(ex, 'developer_message') else repr(ex), - caller=caller.strip() + exception=ex.developer_message if hasattr(ex, 'developer_message') else repr(ex) ) LOGGER.exception(msg) raise api_error(msg) diff --git a/openedx/core/djangoapps/user_api/serializers.py b/openedx/core/djangoapps/user_api/serializers.py index 2ba351f4f2..f46197cb95 100644 --- a/openedx/core/djangoapps/user_api/serializers.py +++ b/openedx/core/djangoapps/user_api/serializers.py @@ -22,7 +22,12 @@ class UserSerializer(serializers.HyperlinkedModelSerializer): """ Return the name attribute from the user profile object if profile exists else none """ - return user.profile.name + try: + profile = UserProfile.objects.get(user=user) + except UserProfile.DoesNotExist: + return None + + return profile.name def get_preferences(self, user): """ diff --git a/openedx/core/djangoapps/user_api/tests/test_helpers.py b/openedx/core/djangoapps/user_api/tests/test_helpers.py index 00576d588e..a0983a0573 100644 --- a/openedx/core/djangoapps/user_api/tests/test_helpers.py +++ b/openedx/core/djangoapps/user_api/tests/test_helpers.py @@ -2,7 +2,6 @@ Tests for helper functions. """ import json -import re import mock import ddt from django import forms @@ -53,35 +52,22 @@ class InterceptErrorsTest(TestCase): @mock.patch('openedx.core.djangoapps.user_api.helpers.LOGGER') def test_logs_errors(self, mock_logger): - self.maxDiff = None exception = 'openedx.core.djangoapps.user_api.tests.test_helpers.FakeInputException' expected_log_msg = ( u"An unexpected error occurred when calling 'intercepted_function' with arguments '()' and " - u"keyword arguments '{{'raise_error': }}' " - u"from File \"{}\", line XXX, in test_logs_errors\n" - u" intercepted_function(raise_error=FakeInputException): FakeInputException()" - ).format(exception, __file__) + u"keyword arguments '{'raise_error': }': FakeInputException()" + ) # Verify that the raised exception has the error message try: intercepted_function(raise_error=FakeInputException) except FakeOutputException as ex: - actual_message = re.sub(r'line \d+', 'line XXX', ex.message, flags=re.MULTILINE) - self.assertEqual(actual_message, expected_log_msg) + self.assertEqual(ex.message, expected_log_msg) # Verify that the error logger is called # This will include the stack trace for the original exception # because it's called with log level "ERROR" - calls = mock_logger.exception.mock_calls - self.assertEqual(len(calls), 1) - name, args, kwargs = calls[0] - - self.assertEqual(name, '') - self.assertEqual(len(args), 1) - self.assertEqual(kwargs, {}) - - actual_message = re.sub(r'line \d+', 'line XXX', args[0], flags=re.MULTILINE) - self.assertEqual(actual_message, expected_log_msg) + mock_logger.exception.assert_called_once_with(expected_log_msg) class FormDescriptionTest(TestCase): diff --git a/openedx/core/djangoapps/user_api/views.py b/openedx/core/djangoapps/user_api/views.py index 5da932dad6..e6125d8e6b 100644 --- a/openedx/core/djangoapps/user_api/views.py +++ b/openedx/core/djangoapps/user_api/views.py @@ -956,7 +956,7 @@ class UserViewSet(viewsets.ReadOnlyModelViewSet): """ authentication_classes = (authentication.SessionAuthentication,) permission_classes = (ApiKeyHeaderPermission,) - queryset = User.objects.all().prefetch_related("preferences").select_related("profile") + queryset = User.objects.all().prefetch_related("preferences") serializer_class = UserSerializer paginate_by = 10 paginate_by_param = "page_size" @@ -982,7 +982,7 @@ class ForumRoleUsersListView(generics.ListAPIView): raise ParseError('course_id must be specified') course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id_string) role = Role.objects.get_or_create(course_id=course_id, name=name)[0] - users = role.users.prefetch_related("preferences").select_related("profile").all() + users = role.users.all() return users @@ -1011,7 +1011,7 @@ class PreferenceUsersListView(generics.ListAPIView): paginate_by_param = "page_size" def get_queryset(self): - return User.objects.filter(preferences__key=self.kwargs["pref_key"]).prefetch_related("preferences").select_related("profile") + return User.objects.filter(preferences__key=self.kwargs["pref_key"]).prefetch_related("preferences") class UpdateEmailOptInPreference(APIView):