Commit be189e60 by Diana Huang Committed by Julia Hansbrough

Store user preferences for languages

Also, refactor tests such that we're not deleting users or prefs
parent 77cce3aa
......@@ -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
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
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)
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')
)
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();
......
<%! from django.utils.translation import ugettext as _ %>
<%!
from django.core.urlresolvers import reverse
%>
<%namespace name='static' file='../static_content.html'/>
......
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