Commit a03baee2 by Will Daly

Merge pull request #4976 from edx/will/ecom-128

Embargo based on country code in the user's profile.
parents 12e2d442 31a65661
...@@ -6,26 +6,35 @@ import mock ...@@ -6,26 +6,35 @@ import mock
import pygeoip import pygeoip
import unittest import unittest
from django.core.urlresolvers import reverse
from django.conf import settings from django.conf import settings
from django.test import TestCase, Client
from django.test.utils import override_settings from django.test.utils import override_settings
from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE import ddt
from student.models import CourseEnrollment from student.models import CourseEnrollment
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import (
ModuleStoreTestCase, mixed_store_config
)
# Explicitly import the cache from ConfigurationModel so we can reset it after each test # Explicitly import the cache from ConfigurationModel so we can reset it after each test
from config_models.models import cache from config_models.models import cache
from embargo.models import EmbargoedCourse, EmbargoedState, IPFilter from embargo.models import EmbargoedCourse, EmbargoedState, IPFilter
@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE) # Since we don't need any XML course fixtures, use a modulestore configuration
class EmbargoMiddlewareTests(TestCase): # that disables the XML modulestore.
MODULESTORE_CONFIG = mixed_store_config(settings.COMMON_TEST_DATA_ROOT, {}, include_xml=False)
@ddt.ddt
@override_settings(MODULESTORE=MODULESTORE_CONFIG)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class EmbargoMiddlewareTests(ModuleStoreTestCase):
""" """
Tests of EmbargoMiddleware Tests of EmbargoMiddleware
""" """
def setUp(self): def setUp(self):
self.client = Client()
self.user = UserFactory(username='fred', password='secret') self.user = UserFactory(username='fred', password='secret')
self.client.login(username='fred', password='secret') self.client.login(username='fred', password='secret')
self.embargo_course = CourseFactory.create() self.embargo_course = CourseFactory.create()
...@@ -69,7 +78,6 @@ class EmbargoMiddlewareTests(TestCase): ...@@ -69,7 +78,6 @@ class EmbargoMiddlewareTests(TestCase):
} }
return ip_dict.get(ip_addr, 'US') return ip_dict.get(ip_addr, 'US')
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
def test_countries(self): def test_countries(self):
# Accessing an embargoed page from a blocked IP should cause a redirect # Accessing an embargoed page from a blocked IP should cause a redirect
response = self.client.get(self.embargoed_page, HTTP_X_FORWARDED_FOR='1.0.0.0', REMOTE_ADDR='1.0.0.0') response = self.client.get(self.embargoed_page, HTTP_X_FORWARDED_FOR='1.0.0.0', REMOTE_ADDR='1.0.0.0')
...@@ -95,7 +103,6 @@ class EmbargoMiddlewareTests(TestCase): ...@@ -95,7 +103,6 @@ class EmbargoMiddlewareTests(TestCase):
response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='5.0.0.0', REMOTE_ADDR='5.0.0.0') response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='5.0.0.0', REMOTE_ADDR='5.0.0.0')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
def test_countries_ipv6(self): def test_countries_ipv6(self):
# Accessing an embargoed page from a blocked IP should cause a redirect # Accessing an embargoed page from a blocked IP should cause a redirect
response = self.client.get(self.embargoed_page, HTTP_X_FORWARDED_FOR='2001:1340::', REMOTE_ADDR='2001:1340::') response = self.client.get(self.embargoed_page, HTTP_X_FORWARDED_FOR='2001:1340::', REMOTE_ADDR='2001:1340::')
...@@ -121,7 +128,6 @@ class EmbargoMiddlewareTests(TestCase): ...@@ -121,7 +128,6 @@ class EmbargoMiddlewareTests(TestCase):
response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='2001:250::', REMOTE_ADDR='2001:250::') response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='2001:250::', REMOTE_ADDR='2001:250::')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
def test_ip_exceptions(self): def test_ip_exceptions(self):
# Explicitly whitelist/blacklist some IPs # Explicitly whitelist/blacklist some IPs
IPFilter( IPFilter(
...@@ -157,7 +163,6 @@ class EmbargoMiddlewareTests(TestCase): ...@@ -157,7 +163,6 @@ class EmbargoMiddlewareTests(TestCase):
response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='5.0.0.0', REMOTE_ADDR='5.0.0.0') response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='5.0.0.0', REMOTE_ADDR='5.0.0.0')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
def test_ip_network_exceptions(self): def test_ip_network_exceptions(self):
# Explicitly whitelist/blacklist some IP networks # Explicitly whitelist/blacklist some IP networks
IPFilter( IPFilter(
...@@ -213,7 +218,54 @@ class EmbargoMiddlewareTests(TestCase): ...@@ -213,7 +218,54 @@ class EmbargoMiddlewareTests(TestCase):
response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='5.0.0.0', REMOTE_ADDR='5.0.0.0') response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='5.0.0.0', REMOTE_ADDR='5.0.0.0')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @ddt.data(
("", False),
("us", False),
("CU", True),
("Ir", True),
("sy", True),
("sd", True)
)
@ddt.unpack
def test_embargo_profile_country(self, profile_country, is_embargoed):
# Set the country in the user's profile
profile = self.user.profile
profile.country = profile_country
profile.save()
# Attempt to access an embargoed course
response = self.client.get(self.embargoed_page)
# If the user is from an embargoed country, verify that
# they are redirected to the embargo page.
if is_embargoed:
embargo_url = reverse('embargo')
self.assertRedirects(response, embargo_url)
# Otherwise, verify that the student can access the page
else:
self.assertEqual(response.status_code, 200)
# For non-embargoed courses, the student should be able to access
# the page, even if he/she is from an embargoed country.
response = self.client.get(self.regular_page)
self.assertEqual(response.status_code, 200)
def test_embargo_profile_country_cache(self):
# Set the country in the user's profile
profile = self.user.profile
profile.country = "us"
profile.save()
# Warm the cache
with self.assertNumQueries(18):
self.client.get(self.embargoed_page)
# Access the page multiple times, but expect that we hit
# the database to check the user's profile only once
with self.assertNumQueries(12):
self.client.get(self.embargoed_page)
@mock.patch.dict(settings.FEATURES, {'EMBARGO': False}) @mock.patch.dict(settings.FEATURES, {'EMBARGO': False})
def test_countries_embargo_off(self): def test_countries_embargo_off(self):
# When the middleware is turned off, all requests should go through # When the middleware is turned off, all requests should go through
...@@ -242,7 +294,6 @@ class EmbargoMiddlewareTests(TestCase): ...@@ -242,7 +294,6 @@ class EmbargoMiddlewareTests(TestCase):
response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='5.0.0.0', REMOTE_ADDR='5.0.0.0') response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='5.0.0.0', REMOTE_ADDR='5.0.0.0')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@mock.patch.dict(settings.FEATURES, {'EMBARGO': False, 'SITE_EMBARGOED': True}) @mock.patch.dict(settings.FEATURES, {'EMBARGO': False, 'SITE_EMBARGOED': True})
def test_embargo_off_embargo_site_on(self): def test_embargo_off_embargo_site_on(self):
# When the middleware is turned on with SITE, main site access should be restricted # When the middleware is turned on with SITE, main site access should be restricted
...@@ -254,7 +305,6 @@ class EmbargoMiddlewareTests(TestCase): ...@@ -254,7 +305,6 @@ class EmbargoMiddlewareTests(TestCase):
response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='5.0.0.0', REMOTE_ADDR='5.0.0.0') response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='5.0.0.0', REMOTE_ADDR='5.0.0.0')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@mock.patch.dict(settings.FEATURES, {'EMBARGO': False, 'SITE_EMBARGOED': True}) @mock.patch.dict(settings.FEATURES, {'EMBARGO': False, 'SITE_EMBARGOED': True})
@override_settings(EMBARGO_SITE_REDIRECT_URL='https://www.edx.org/') @override_settings(EMBARGO_SITE_REDIRECT_URL='https://www.edx.org/')
def test_embargo_off_embargo_site_on_with_redirect_url(self): def test_embargo_off_embargo_site_on_with_redirect_url(self):
......
...@@ -724,7 +724,7 @@ class CourseEnrollment(models.Model): ...@@ -724,7 +724,7 @@ class CourseEnrollment(models.Model):
else: else:
unenroll_done.send(sender=None, course_enrollment=self) unenroll_done.send(sender=None, course_enrollment=self)
self.emit_event(EVENT_NAME_ENROLLMENT_DEACTIVATED) self.emit_event(EVENT_NAME_ENROLLMENT_DEACTIVATED)
dog_stats_api.increment( dog_stats_api.increment(
......
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
<%block name="pagetitle">${_("This Course Unavailable In Your Country")}</%block> <%block name="pagetitle">${_("This Course Unavailable In Your Country")}</%block>
<section class="outside-app"> <section class="outside-app">
<p>${_("Our system indicates that you are trying to access an edX course from an IP address associated with a country currently subjected to U.S. economic and trade sanctions. Unfortunately, at this time edX must comply with export controls, and we cannot allow you to access this particular course. Feel free to browse our catalogue to find other courses you may be interested in taking.")}</p> <p>${_("Our system indicates that you are trying to access an edX course from a country currently subject to U.S. economic and trade sanctions. Unfortunately, at this time edX must comply with export controls, and we cannot allow you to access this particular course. Feel free to browse our catalogue to find other courses you may be interested in taking.")}</p>
</section> </section>
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