Merge pull request #13777 from edx/douglashall/fix_session_cookie_domain_middleware

Refactored middleware that supports SESSION_COOKIE_DOMAIN overrides.
This commit is contained in:
Douglas Hall
2016-10-18 11:20:43 -04:00
committed by GitHub
7 changed files with 88 additions and 61 deletions

View File

@@ -36,50 +36,3 @@ class MicrositeMiddleware(object):
"""
microsite.clear()
return response
class MicrositeSessionCookieDomainMiddleware(object):
"""
Special case middleware which should be at the very end of the MIDDLEWARE list (so that it runs first
on the process_response chain). This middleware will define a wrapper function for the set_cookie() function
on the HttpResponse object, if the request is running in a middleware.
This wrapped set_cookie will change the SESSION_COOKIE_DOMAIN setting so that the cookie can be bound to a
fully customized URL.
"""
def process_response(self, request, response):
"""
Standard Middleware entry point
"""
# See if we are running in a Microsite *AND* we have a custom SESSION_COOKIE_DOMAIN defined
# in configuration
if microsite.has_override_value('SESSION_COOKIE_DOMAIN'):
# define wrapper function for the standard set_cookie()
def _set_cookie_wrapper(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False):
# only override if we are setting the cookie name to be the one the Django Session Middleware uses
# as defined in settings.SESSION_COOKIE_NAME
if key == settings.SESSION_COOKIE_NAME:
domain = microsite.get_value('SESSION_COOKIE_DOMAIN', domain)
# then call down into the normal Django set_cookie method
return response.set_cookie_wrapped_func(
key,
value,
max_age=max_age,
expires=expires,
path=path,
domain=domain,
secure=secure,
httponly=httponly
)
# then point the HttpResponse.set_cookie to point to the wrapper and keep
# the original around
response.set_cookie_wrapped_func = response.set_cookie
response.set_cookie = _set_cookie_wrapper
return response

View File

@@ -1,81 +0,0 @@
# -*- coding: utf-8 -*-
"""
Test Microsite middleware.
"""
import ddt
import unittest
from mock import patch
from django.conf import settings
from django.test.client import Client
from django.test.utils import override_settings
from student.tests.factories import UserFactory
from microsite_configuration.microsite import (
get_backend,
)
from microsite_configuration.backends.base import BaseMicrositeBackend
from microsite_configuration.tests.tests import (
DatabaseMicrositeTestCase,
side_effect_for_get_value,
MICROSITE_BACKENDS,
)
# NOTE: We set SESSION_SAVE_EVERY_REQUEST to True in order to make sure
# Sessions are always started on every request
# pylint: disable=no-member, protected-access
@ddt.ddt
@override_settings(SESSION_SAVE_EVERY_REQUEST=True)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class MicrositeSessionCookieTests(DatabaseMicrositeTestCase):
"""
Tests regarding the session cookie management in the middlware for Microsites
"""
def setUp(self):
super(MicrositeSessionCookieTests, self).setUp()
# Create a test client, and log it in so that it will save some session
# data.
self.user = UserFactory.create()
self.user.set_password('password')
self.user.save()
self.client = Client()
self.client.login(username=self.user.username, password="password")
@ddt.data(*MICROSITE_BACKENDS)
def test_session_cookie_domain_no_microsite(self, site_backend):
"""
Tests that non-microsite behaves according to default behavior
"""
with patch('microsite_configuration.microsite.BACKEND',
get_backend(site_backend, BaseMicrositeBackend)):
response = self.client.get('/')
self.assertNotIn('test_site.localhost', str(response.cookies['sessionid']))
self.assertNotIn('Domain', str(response.cookies['sessionid']))
@ddt.data(*MICROSITE_BACKENDS)
def test_session_cookie_domain(self, site_backend):
"""
Makes sure that the cookie being set in a Microsite
is the one specially overridden in configuration
"""
with patch('microsite_configuration.microsite.BACKEND',
get_backend(site_backend, BaseMicrositeBackend)):
response = self.client.get('/', HTTP_HOST=settings.MICROSITE_TEST_HOSTNAME)
self.assertIn('test_site.localhost', str(response.cookies['sessionid']))
@ddt.data(*MICROSITE_BACKENDS)
def test_microsite_none_cookie_domain(self, site_backend):
"""
Tests to make sure that a Microsite that specifies None for 'SESSION_COOKIE_DOMAIN' does not
set a domain on the session cookie
"""
with patch('microsite_configuration.microsite.get_value') as mock_get_value:
mock_get_value.side_effect = side_effect_for_get_value('SESSION_COOKIE_DOMAIN', None)
with patch('microsite_configuration.microsite.BACKEND',
get_backend(site_backend, BaseMicrositeBackend)):
response = self.client.get('/', HTTP_HOST=settings.MICROSITE_TEST_HOSTNAME)
self.assertNotIn('test_site.localhost', str(response.cookies['sessionid']))
self.assertNotIn('Domain', str(response.cookies['sessionid']))