Skip to content
Snippets Groups Projects
Commit be189e60 authored by Diana Huang's avatar Diana Huang Committed by Julia Hansbrough
Browse files

Store user preferences for languages

Also, refactor tests such that we're not deleting users or prefs
parent 77cce3aa
No related merge requests found
......@@ -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'/>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment