Commit 6e45f000 by Ivan Ivic Committed by Michael Frey

Created new embargo check api

LEARNER-1523
LEARNER-1524
parent 00ba9c70
......@@ -1133,7 +1133,7 @@ class EnrollmentEmbargoTest(EnrollmentTestMixin, UrlResetMixin, ModuleStoreTestC
self.user.profile.country = restricted_country.country
self.user.profile.save()
path = reverse('embargo_blocked_message', kwargs={'access_point': 'enrollment', 'message_key': 'default'})
path = reverse('embargo:blocked_message', kwargs={'access_point': 'enrollment', 'message_key': 'default'})
self.assert_access_denied(path)
@override_settings(EDX_API_KEY=EnrollmentTestMixin.API_KEY)
......
......@@ -813,7 +813,8 @@ urlpatterns += (
# Embargo
if settings.FEATURES.get('EMBARGO'):
urlpatterns += (
url(r'^embargo/', include('openedx.core.djangoapps.embargo.urls')),
url(r'^embargo/', include('openedx.core.djangoapps.embargo.urls', namespace='embargo')),
url(r'^api/embargo/', include('openedx.core.djangoapps.embargo.urls', namespace='api_embargo')),
)
# Survey Djangoapp
......
......@@ -98,7 +98,7 @@ class EmbargoMiddleware(object):
# If the IP is blacklisted, reject.
# This applies to any request, not just courseware URLs.
ip_blacklist_url = reverse(
'embargo_blocked_message',
'embargo:blocked_message',
kwargs={
'access_point': 'courseware',
'message_key': 'embargo'
......
......@@ -317,7 +317,7 @@ class RestrictedCourse(models.Model):
# We use generic messaging unless we find something more specific,
# but *always* return a valid URL path.
default_path = reverse(
'embargo_blocked_message',
'embargo:blocked_message',
kwargs={
'access_point': 'courseware',
'message_key': 'default'
......@@ -336,7 +336,7 @@ class RestrictedCourse(models.Model):
course = cls.objects.get(course_key=course_key)
msg_key = course.message_key_for_access_point(access_point)
return reverse(
'embargo_blocked_message',
'embargo:blocked_message',
kwargs={
'access_point': access_point,
'message_key': msg_key
......
......@@ -75,7 +75,7 @@ def restrict_course(course_key, access_point="enrollment", disable_access_check=
# Yield the redirect url so the tests don't need to know
# the embargo messaging URL structure.
redirect_url = reverse(
'embargo_blocked_message',
'embargo:blocked_message',
kwargs={
'access_point': access_point,
'message_key': 'default'
......
import factory
from factory.django import DjangoModelFactory
from xmodule.modulestore.tests.factories import CourseFactory
from ..models import Country, CountryAccessRule, RestrictedCourse
class CountryFactory(DjangoModelFactory):
class Meta(object):
model = Country
country = 'US'
class RestrictedCourseFactory(DjangoModelFactory):
class Meta(object):
model = RestrictedCourse
@factory.lazy_attribute
def course_key(self):
return CourseFactory().id
class CountryAccessRuleFactory(DjangoModelFactory):
class Meta(object):
model = CountryAccessRule
country = factory.SubFactory(CountryFactory)
restricted_course = factory.SubFactory(RestrictedCourseFactory)
rule_type = CountryAccessRule.BLACKLIST_RULE
......@@ -115,7 +115,7 @@ class EmbargoMiddlewareAccessTests(UrlResetMixin, ModuleStoreTestCase):
self.assertEqual(response.status_code, 200)
else:
redirect_url = reverse(
'embargo_blocked_message',
'embargo:blocked_message',
kwargs={
'access_point': 'courseware',
'message_key': 'embargo'
......@@ -139,7 +139,7 @@ class EmbargoMiddlewareAccessTests(UrlResetMixin, ModuleStoreTestCase):
)
url = reverse(
'embargo_blocked_message',
'embargo:blocked_message',
kwargs={
'access_point': access_point,
'message_key': msg_key
......
"""Tests for embargo app views. """
from mock import patch
import ddt
import json
import mock
import pygeoip
from django.core.urlresolvers import reverse
from django.conf import settings
import ddt
from mock import patch
from util.testing import UrlResetMixin
from .factories import CountryFactory, CountryAccessRuleFactory, RestrictedCourseFactory
from .. import messages
from lms.djangoapps.course_api.tests.mixins import CourseApiFactoryMixin
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme
from student.tests.factories import UserFactory
from util.testing import UrlResetMixin
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
@skip_unless_lms
......@@ -57,7 +66,7 @@ class CourseAccessMessageViewTest(CacheIsolationTestCase, UrlResetMixin):
# Custom override specified for the "embargo" message
# for backwards compatibility with previous versions
# of the embargo app.
url = reverse('embargo_blocked_message', kwargs={
url = reverse('embargo:blocked_message', kwargs={
'access_point': access_point,
'message_key': "embargo"
})
......@@ -69,7 +78,7 @@ class CourseAccessMessageViewTest(CacheIsolationTestCase, UrlResetMixin):
def _load_page(self, access_point, message_key, expected_status=200):
"""Load the message page and check the status code. """
url = reverse('embargo_blocked_message', kwargs={
url = reverse('embargo:blocked_message', kwargs={
'access_point': access_point,
'message_key': message_key
})
......@@ -85,3 +94,56 @@ class CourseAccessMessageViewTest(CacheIsolationTestCase, UrlResetMixin):
actual=response.status_code
)
)
@skip_unless_lms
class CheckCourseAccessViewTest(CourseApiFactoryMixin, ModuleStoreTestCase):
""" Tests the course access check endpoint. """
@patch.dict(settings.FEATURES, {'EMBARGO': True})
def setUp(self):
super(CheckCourseAccessViewTest, self).setUp()
self.url = reverse('api_embargo:v1_course_access')
user = UserFactory(is_staff=True)
self.client.login(username=user.username, password=UserFactory._DEFAULT_PASSWORD)
self.course_id = str(CourseFactory().id)
self.request_data = {
'course_ids': [self.course_id],
'ip_address': '0.0.0.0',
'user': self.user,
}
def test_course_access_endpoint_with_unrestricted_course(self):
response = self.client.get(self.url, data=self.request_data)
expected_response = {'access': True}
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, expected_response)
def test_course_access_endpoint_with_restricted_course(self):
CountryAccessRuleFactory(restricted_course=RestrictedCourseFactory(course_key=self.course_id))
self.user.is_staff = False
self.user.save()
# Appear to make a request from an IP in the blocked country
with mock.patch.object(pygeoip.GeoIP, 'country_code_by_addr') as mock_ip:
mock_ip.return_value = 'US'
response = self.client.get(self.url, data=self.request_data)
expected_response = {'access': False}
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, expected_response)
def test_course_access_endpoint_with_logged_out_user(self):
self.client.logout()
response = self.client.get(self.url, data=self.request_data)
self.assertEqual(response.status_code, 403)
def test_course_access_endpoint_with_non_staff_user(self):
user = UserFactory(is_staff=False)
self.client.login(username=user.username, password=UserFactory._DEFAULT_PASSWORD)
response = self.client.get(self.url, data=self.request_data)
self.assertEqual(response.status_code, 403)
def test_course_access_endpoint_with_invalid_data(self):
response = self.client.get(self.url, data=None)
self.assertEqual(response.status_code, 400)
......@@ -2,13 +2,14 @@
from django.conf.urls import patterns, url
from .views import CourseAccessMessageView
from .views import CheckCourseAccessView, CourseAccessMessageView
urlpatterns = patterns(
'openedx.core.djangoapps.embargo.views',
url(
r'^blocked-message/(?P<access_point>enrollment|courseware)/(?P<message_key>.+)/$',
CourseAccessMessageView.as_view(),
name='embargo_blocked_message',
name='blocked_message',
),
url(r'^v1/course_access/$', CheckCourseAccessView.as_view(), name='v1_course_access'),
)
"""Views served by the embargo app. """
from django.contrib.auth.models import User
from django.http import Http404
from django.views.generic.base import View
from edx_rest_framework_extensions.authentication import JwtAuthentication
from opaque_keys.edx.keys import CourseKey
from rest_framework import permissions, status
from rest_framework.response import Response
from rest_framework.views import APIView
from edxmako.shortcuts import render_to_response
from . import messages
from .api import check_course_access
class CheckCourseAccessView(APIView):
permission_classes = (permissions.IsAuthenticated, permissions.IsAdminUser)
def get(self, request):
"""
GET /api/embargo/v1/course_access/
Arguments:
request (HttpRequest)
Return:
Response: True or False depending on the check.
"""
course_ids = request.GET.getlist('course_ids', [])
username = request.GET.get('user')
user_ip_address = request.GET.get('ip_address')
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
user = None
response = {'access': True}
if course_ids and user and user_ip_address:
for course_id in course_ids:
if not check_course_access(CourseKey.from_string(course_id), user, user_ip_address):
response['access'] = False
break
else:
return Response(data=None, status=status.HTTP_400_BAD_REQUEST)
return Response(response)
class CourseAccessMessageView(View):
......
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