Store user preferences for languages
Also, refactor tests such that we're not deleting users or prefs
This commit is contained in:
committed by
Julia Hansbrough
parent
77cce3aa1a
commit
be189e607e
@@ -2,8 +2,6 @@
|
||||
Middleware for UserPreferences
|
||||
"""
|
||||
|
||||
from django.utils.translation.trans_real import parse_accept_lang_header
|
||||
|
||||
from user_api.models import UserPreference, LANGUAGE_KEY
|
||||
|
||||
|
||||
@@ -17,11 +15,10 @@ class UserPreferenceMiddleware(object):
|
||||
|
||||
def process_request(self, request):
|
||||
"""
|
||||
If a user's UserPreference contains a language preference,
|
||||
stick that preference in the session.
|
||||
If a user's UserPreference contains a language preference and there is
|
||||
no language set on the session, use the user's preference.
|
||||
"""
|
||||
|
||||
query = UserPreference.objects.filter(user=request.user, key=LANGUAGE_KEY)
|
||||
if query.exists():
|
||||
# there should only be one result for query
|
||||
request.session['django_language'] = query[0].value
|
||||
if 'django_language' not in request.session and request.user.is_authenticated():
|
||||
user_pref = UserPreference.get_preference(request.user, LANGUAGE_KEY)
|
||||
if user_pref:
|
||||
request.session['django_language'] = user_pref
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
|
||||
LANGUAGE_KEY = 'pref-lang'
|
||||
|
||||
|
||||
class UserPreference(models.Model):
|
||||
"""A user's preference, stored as generic text to be processed by client"""
|
||||
@@ -10,3 +12,26 @@ class UserPreference(models.Model):
|
||||
|
||||
class Meta:
|
||||
unique_together = ("user", "key")
|
||||
|
||||
@classmethod
|
||||
def set_preference(cls, user, preference_key, preference_value):
|
||||
"""
|
||||
Sets the user preference for a given key
|
||||
"""
|
||||
user_pref, _ = cls.objects.get_or_create(user=user, key=preference_key)
|
||||
user_pref.value = preference_value
|
||||
user_pref.save()
|
||||
|
||||
@classmethod
|
||||
def get_preference(cls, user, preference_key):
|
||||
"""
|
||||
Gets the user preference value for a given key
|
||||
|
||||
Returns None if there isn't a preference for the given key
|
||||
"""
|
||||
|
||||
try:
|
||||
user_pref = cls.objects.get(user=user, key=preference_key)
|
||||
return user_pref.value
|
||||
except cls.DoesNotExist:
|
||||
return None
|
||||
|
||||
42
common/djangoapps/user_api/tests/test_middleware.py
Normal file
42
common/djangoapps/user_api/tests/test_middleware.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.contrib.sessions.middleware import SessionMiddleware
|
||||
|
||||
from user_api.middleware import UserPreferenceMiddleware
|
||||
from user_api.models import UserPreference, LANGUAGE_KEY
|
||||
from student.tests.factories import UserFactory
|
||||
|
||||
|
||||
class TestUserPreferenceMiddleware(TestCase):
|
||||
"""
|
||||
Tests to make sure user preferences are getting properly set in the middleware
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.middleware = UserPreferenceMiddleware()
|
||||
self.request_factory = RequestFactory()
|
||||
self.session_middleware = SessionMiddleware()
|
||||
self.user = UserFactory.create()
|
||||
self.request = self.request_factory.get('/somewhere')
|
||||
self.request.user = self.user
|
||||
self.session_middleware.process_request(self.request)
|
||||
|
||||
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('django_language', self.request.session)
|
||||
|
||||
def test_language_in_user_prefs(self):
|
||||
# language set in the user preferences and not the session
|
||||
UserPreference.set_preference(self.user, LANGUAGE_KEY, 'eo')
|
||||
self.middleware.process_request(self.request)
|
||||
self.assertEquals(self.request.session['django_language'], 'eo')
|
||||
|
||||
def test_language_in_session(self):
|
||||
# language set in both the user preferences and session,
|
||||
# session should get precedence
|
||||
self.request.session['django_language'] = 'en'
|
||||
UserPreference.set_preference(self.user, LANGUAGE_KEY, 'eo')
|
||||
self.middleware.process_request(self.request)
|
||||
|
||||
self.assertEquals(self.request.session['django_language'], 'en')
|
||||
@@ -2,6 +2,7 @@ from django.db import IntegrityError
|
||||
from django.test import TestCase
|
||||
from student.tests.factories import UserFactory
|
||||
from user_api.tests.factories import UserPreferenceFactory
|
||||
from user_api.models import UserPreference
|
||||
|
||||
|
||||
class UserPreferenceModelTest(TestCase):
|
||||
@@ -26,3 +27,18 @@ class UserPreferenceModelTest(TestCase):
|
||||
key="testkey3",
|
||||
value="\xe8\xbf\x99\xe6\x98\xaf\xe4\xb8\xad\xe5\x9b\xbd\xe6\x96\x87\xe5\xad\x97'"
|
||||
)
|
||||
|
||||
def test_get_set_preference(self):
|
||||
user = UserFactory.create()
|
||||
key = 'testkey'
|
||||
value = 'testvalue'
|
||||
|
||||
# does a round trip
|
||||
UserPreference.set_preference(user, key, value)
|
||||
pref = UserPreference.get_preference(user, key)
|
||||
|
||||
self.assertEqual(pref, value)
|
||||
|
||||
# get preference for key that doesn't exist for user
|
||||
pref = UserPreference.get_preference(user, 'testkey_none')
|
||||
self.assertIsNone(pref)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import base64
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
from django.core.urlresolvers import reverse
|
||||
import json
|
||||
import re
|
||||
from student.tests.factories import UserFactory
|
||||
from unittest import SkipTest
|
||||
from user_api.models import UserPreference
|
||||
from user_api.models import UserPreference, LANGUAGE_KEY
|
||||
from user_api.tests.factories import UserPreferenceFactory
|
||||
|
||||
|
||||
@@ -17,21 +17,9 @@ USER_PREFERENCE_LIST_URI = "/user_api/v1/user_prefs/"
|
||||
|
||||
|
||||
@override_settings(EDX_API_KEY=TEST_API_KEY)
|
||||
class UserApiTestCase(TestCase):
|
||||
def setUp(self):
|
||||
super(UserApiTestCase, self).setUp()
|
||||
self.users = [
|
||||
UserFactory.create(
|
||||
email="test{0}@test.org".format(i),
|
||||
profile__name="Test {0}".format(i)
|
||||
)
|
||||
for i in range(5)
|
||||
]
|
||||
self.prefs = [
|
||||
UserPreferenceFactory.create(user=self.users[0], key="key0"),
|
||||
UserPreferenceFactory.create(user=self.users[0], key="key1"),
|
||||
UserPreferenceFactory.create(user=self.users[1], key="key0")
|
||||
]
|
||||
class ApiTestCase(TestCase):
|
||||
|
||||
LIST_URI = USER_LIST_URI
|
||||
|
||||
def basic_auth(self, username, password):
|
||||
return {'HTTP_AUTHORIZATION': 'Basic ' + base64.b64encode('%s:%s' % (username, password))}
|
||||
@@ -100,6 +88,32 @@ class UserApiTestCase(TestCase):
|
||||
self.assertEqual(response.status_code, 405)
|
||||
|
||||
|
||||
class NoUserApiTestCase(ApiTestCase):
|
||||
def test_get_list_empty(self):
|
||||
result = self.get_json(self.LIST_URI)
|
||||
self.assertEqual(result["count"], 0)
|
||||
self.assertIsNone(result["next"])
|
||||
self.assertIsNone(result["previous"])
|
||||
self.assertEqual(result["results"], [])
|
||||
|
||||
|
||||
class UserApiTestCase(ApiTestCase):
|
||||
def setUp(self):
|
||||
super(UserApiTestCase, self).setUp()
|
||||
self.users = [
|
||||
UserFactory.create(
|
||||
email="test{0}@test.org".format(i),
|
||||
profile__name="Test {0}".format(i)
|
||||
)
|
||||
for i in range(5)
|
||||
]
|
||||
self.prefs = [
|
||||
UserPreferenceFactory.create(user=self.users[0], key="key0"),
|
||||
UserPreferenceFactory.create(user=self.users[0], key="key1"),
|
||||
UserPreferenceFactory.create(user=self.users[1], key="key0")
|
||||
]
|
||||
|
||||
|
||||
class UserViewSetTest(UserApiTestCase):
|
||||
LIST_URI = USER_LIST_URI
|
||||
|
||||
@@ -137,17 +151,10 @@ class UserViewSetTest(UserApiTestCase):
|
||||
def test_basic_auth(self):
|
||||
# ensure that having basic auth headers in the mix does not break anything
|
||||
self.assertHttpOK(
|
||||
self.request_with_auth("get", self.LIST_URI, **self.basic_auth('someuser', 'somepass')))
|
||||
self.request_with_auth("get", self.LIST_URI,
|
||||
**self.basic_auth('someuser', 'somepass')))
|
||||
self.assertHttpForbidden(
|
||||
self.client.get(self.LIST_URI, **self.basic_auth('someuser', 'somepass')))
|
||||
|
||||
def test_get_list_empty(self):
|
||||
User.objects.all().delete()
|
||||
result = self.get_json(self.LIST_URI)
|
||||
self.assertEqual(result["count"], 0)
|
||||
self.assertIsNone(result["next"])
|
||||
self.assertIsNone(result["previous"])
|
||||
self.assertEqual(result["results"], [])
|
||||
self.client.get(self.LIST_URI, **self.basic_auth('someuser', 'somepass')))
|
||||
|
||||
def test_get_list_nonempty(self):
|
||||
result = self.get_json(self.LIST_URI)
|
||||
@@ -245,14 +252,6 @@ class UserPreferenceViewSetTest(UserApiTestCase):
|
||||
def test_debug_auth(self):
|
||||
self.assertHttpOK(self.client.get(self.LIST_URI))
|
||||
|
||||
def test_get_list_empty(self):
|
||||
UserPreference.objects.all().delete()
|
||||
result = self.get_json(self.LIST_URI)
|
||||
self.assertEqual(result["count"], 0)
|
||||
self.assertIsNone(result["next"])
|
||||
self.assertIsNone(result["previous"])
|
||||
self.assertEqual(result["results"], [])
|
||||
|
||||
def test_get_list_nonempty(self):
|
||||
result = self.get_json(self.LIST_URI)
|
||||
self.assertEqual(result["count"], 3)
|
||||
@@ -357,3 +356,29 @@ class UserPreferenceViewSetTest(UserApiTestCase):
|
||||
"url": uri,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class TestLanguageSetting(TestCase):
|
||||
"""
|
||||
Test setting languages
|
||||
"""
|
||||
def test_set_preference_happy(self):
|
||||
user = UserFactory.create()
|
||||
self.client.login(username=user.username, password='test')
|
||||
|
||||
lang = 'en'
|
||||
response = self.client.post(reverse('user_api_set_language'), {'language': lang})
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
user_pref = UserPreference.get_preference(user, LANGUAGE_KEY)
|
||||
self.assertEqual(user_pref, lang)
|
||||
|
||||
def test_set_preference_missing_lang(self):
|
||||
user = UserFactory.create()
|
||||
self.client.login(username=user.username, password='test')
|
||||
|
||||
response = self.client.post(reverse('user_api_set_language'))
|
||||
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
self.assertIsNone(UserPreference.get_preference(user, LANGUAGE_KEY))
|
||||
|
||||
@@ -9,4 +9,5 @@ user_api_router.register(r'user_prefs', user_api_views.UserPreferenceViewSet)
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^v1/', include(user_api_router.urls)),
|
||||
url(r'^setlang/', 'user_api.views.set_language', name='user_api_set_language')
|
||||
)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpResponse, HttpResponseBadRequest
|
||||
from rest_framework import authentication
|
||||
from rest_framework import filters
|
||||
from rest_framework import permissions
|
||||
from rest_framework import viewsets
|
||||
from user_api.models import UserPreference
|
||||
from user_api.models import UserPreference, LANGUAGE_KEY
|
||||
from user_api.serializers import UserSerializer, UserPreferenceSerializer
|
||||
|
||||
|
||||
@@ -43,3 +45,18 @@ class UserPreferenceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||
serializer_class = UserPreferenceSerializer
|
||||
paginate_by = 10
|
||||
paginate_by_param = "page_size"
|
||||
|
||||
|
||||
@login_required
|
||||
def set_language(request):
|
||||
"""
|
||||
This view is called when the user would like to set a language preference
|
||||
"""
|
||||
user = request.user
|
||||
lang_pref = request.POST.get('language', None)
|
||||
|
||||
if lang_pref:
|
||||
UserPreference.set_preference(user, LANGUAGE_KEY, lang_pref)
|
||||
return HttpResponse('{"success": true}')
|
||||
|
||||
return HttpResponseBadRequest('no language provided')
|
||||
|
||||
@@ -698,6 +698,10 @@ MIDDLEWARE_CLASSES = (
|
||||
# Allows us to dark-launch particular languages
|
||||
'dark_lang.middleware.DarkLangMiddleware',
|
||||
|
||||
# Allows us to set user preferences
|
||||
# should be after DarkLangMiddleware
|
||||
'user_api.middleware.UserPreferenceMiddleware',
|
||||
|
||||
# Detects user-requested locale from 'accept-language' header in http request
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
|
||||
|
||||
@@ -83,15 +83,17 @@
|
||||
});
|
||||
});
|
||||
|
||||
$("#change_language_form").submit(function(event, xhr) {
|
||||
$.post('/i18n/setlang/',
|
||||
{"language": language,},
|
||||
function(data) {
|
||||
if (data.success){
|
||||
location.reload();
|
||||
}
|
||||
})
|
||||
});
|
||||
$("#submit-lang").click(function(event, xhr) {
|
||||
event.preventDefault();
|
||||
$.post('/user_api/setlang/',
|
||||
{"language": $('#settings-language-value').val()})
|
||||
.done(
|
||||
function(data){
|
||||
// submit form as normal
|
||||
$('.settings-language-form').submit();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
$("#change_email_form").submit(function(){
|
||||
var new_email = $('#new_email_field').val();
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
<%!
|
||||
from django.core.urlresolvers import reverse
|
||||
%>
|
||||
|
||||
<%namespace name='static' file='../static_content.html'/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user