Merge pull request #27 from revsys/nicholasserra-middleware-tests

Middleware option session fix and tests
This commit is contained in:
Nicholas Serra 2017-04-04 15:42:30 -04:00 committed by GitHub
commit 0b48ae3938
7 changed files with 99 additions and 7 deletions

View file

@ -47,7 +47,16 @@ if not settings.configured:
],
ROOT_URLCONF='tos.tests.test_urls',
LOGIN_URL='/login/',
SITE_ID='1'
SITE_ID='1',
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
},
'tos': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
},
TOS_CACHE_NAME = 'tos'
)

View file

@ -41,6 +41,15 @@ def get_library():
return Library
def get_cache(cache_name):
if django.VERSION >= (1, 7):
from django.core.cache import caches
return caches[cache_name]
else:
from django.core.cache import get_cache
return get_cache(cache_name)
if django.VERSION < (1, 5):
from django.templatetags.future import url
else:

View file

@ -1,15 +1,15 @@
from django import VERSION as DJANGO_VERSION
from django.conf import settings
from django.contrib.auth import SESSION_KEY as session_key
from django.core.cache import caches
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.utils import deprecation
from django.utils.cache import add_never_cache_headers
from .compat import get_cache
from .models import UserAgreement
cache = caches[getattr(settings, 'TOS_CACHE_NAME', 'default')]
cache = get_cache(getattr(settings, 'TOS_CACHE_NAME', 'default'))
tos_check_url = reverse('tos_check_tos')
@ -38,18 +38,19 @@ class UserAgreementMiddleware(deprecation.MiddlewareMixin if DJANGO_VERSION >= (
# for the user object.
# NOTE: We use the user ID because it's not user-settable and it won't
# ever change (usernames and email addresses can change)
user_id = request.session.get(session_key)
user_id = int(request.session['_auth_user_id'])
user_auth_backend = request.session['_auth_user_backend']
# Get the cache prefix
key_version = cache.get('django:tos:key_version')
# Skip if the user is allowed to skip - for instance, if the user is an
# admin or a staff member
if cache.get('django:tos:skip_tos_check:{}'.format(str(user_id)), False, version=key_version):
if cache.get('django:tos:skip_tos_check:{0}'.format(str(user_id)), False, version=key_version):
return None
# Ping the cache for the user agreement
user_agreed = cache.get('django:tos:agreed:{}'.format(str(user_id)), None, version=key_version)
user_agreed = cache.get('django:tos:agreed:{0}'.format(str(user_id)), None, version=key_version)
# If the cache is missing this user
if user_agreed is None:
@ -59,9 +60,14 @@ class UserAgreementMiddleware(deprecation.MiddlewareMixin if DJANGO_VERSION >= (
terms_of_service__active=True).exists()
# Set the value in the cache
cache.set('django:tos:agreed:{}'.format(user_id), user_agreed, version=key_version)
cache.set('django:tos:agreed:{0}'.format(user_id), user_agreed, version=key_version)
if not user_agreed:
# Confirm view uses these session keys. Non-middleware flow sets them in login view,
# so we need to set them here.
request.session['tos_user'] = user_id
request.session['tos_backend'] = user_auth_backend
response = HttpResponseRedirect(tos_check_url)
add_never_cache_headers(response)
return response

View file

View file

@ -0,0 +1,62 @@
from django.conf import settings
from django.core.urlresolvers import reverse
from django.test import TestCase
from django.test.utils import override_settings
from tos.compat import get_runtime_user_model
from tos.models import TermsOfService, UserAgreement
@override_settings(
MIDDLEWARE_CLASSES=settings.MIDDLEWARE_CLASSES + [
'tos.middleware.UserAgreementMiddleware',
]
)
class TestMiddleware(TestCase):
def setUp(self):
# User that has agreed to TOS
self.user1 = get_runtime_user_model().objects.create_user('user1', 'user1@example.com', 'user1pass')
# User that has not yet agreed to TOS
self.user2 = get_runtime_user_model().objects.create_user('user2', 'user2@example.com', 'user2pass')
self.tos1 = TermsOfService.objects.create(
content="first edition of the terms of service",
active=True
)
self.tos2 = TermsOfService.objects.create(
content="second edition of the terms of service",
active=False
)
self.login_url = getattr(settings, 'LOGIN_URL', '/login/')
UserAgreement.objects.create(
terms_of_service=self.tos1,
user=self.user1
)
def test_middleware_redirects(self):
"""
User that hasn't accepted TOS should be redirected to confirm. Also make sure
confirm works.
"""
self.client.login(username='user2', password='user2pass')
response = self.client.get(reverse('index'))
self.assertRedirects(response, reverse('tos_check_tos'))
# Make sure confirm works after middleware redirect.
response = self.client.post(reverse('tos_check_tos'), {'accept': 'accept'})
# Confirm redirects.
self.assertEqual(response.status_code, 302)
def test_middleware_doesnt_redirect(self):
"""User that has accepted TOS should get 200."""
self.client.login(username='user1', password='user1pass')
response = self.client.get(reverse('index'))
self.assertEqual(response.status_code, 200)
def test_anonymous_user_200(self):
response = self.client.get(reverse('index'))
self.assertEqual(response.status_code, 200)

View file

@ -1,9 +1,12 @@
from django.conf.urls import include, url
from django.views.generic import TemplateView
from tos.compat import patterns
from tos import views
urlpatterns = patterns('',
url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
url(r'^login/$', views.login, {}, 'login'),
url(r'^tos/', include('tos.urls')),
)

View file

@ -9,7 +9,10 @@ from tos.models import TermsOfService, UserAgreement, has_user_agreed_latest_tos
class TestViews(TestCase):
def setUp(self):
# User that has agreed to TOS
self.user1 = get_runtime_user_model().objects.create_user('user1', 'user1@example.com', 'user1pass')
# User that has not yet agreed to TOS
self.user2 = get_runtime_user_model().objects.create_user('user2', 'user2@example.com', 'user2pass')
self.tos1 = TermsOfService.objects.create(