Ejemplo n.º 1
0
    def test_repeat_course(self):
        # Initially course shouldn't be authorized
        self.assertFalse(EmbargoedCourse.is_embargoed(self.course.id))
        # Test authorizing the course, which should totally work
        form = EmbargoedCourseForm(data=self.true_form_data)
        # Validation should work
        self.assertTrue(form.is_valid())
        form.save()
        # Check that this course is authorized
        self.assertTrue(EmbargoedCourse.is_embargoed(self.course.id))

        # Now make a new course authorization with the same course id that tries to turn email off
        form = EmbargoedCourseForm(data=self.false_form_data)
        # Validation should not work because course_id field is unique
        self.assertFalse(form.is_valid())
        self.assertEquals(
            "Embargoed course with this Course id already exists.",
            form._errors["course_id"][0],  # pylint: disable=protected-access
        )
        with self.assertRaisesRegexp(
            ValueError, "The EmbargoedCourse could not be created because the data didn't validate."
        ):
            form.save()

        # Course should still be authorized (invalid attempt had no effect)
        self.assertTrue(EmbargoedCourse.is_embargoed(self.course.id))
Ejemplo n.º 2
0
    def test_repeat_course(self):
        # Initially course shouldn't be authorized
        self.assertFalse(EmbargoedCourse.is_embargoed(self.course.id))
        # Test authorizing the course, which should totally work
        form = EmbargoedCourseForm(data=self.true_form_data)
        # Validation should work
        self.assertTrue(form.is_valid())
        form.save()
        # Check that this course is authorized
        self.assertTrue(EmbargoedCourse.is_embargoed(self.course.id))

        # Now make a new course authorization with the same course id that tries to turn email off
        form = EmbargoedCourseForm(data=self.false_form_data)
        # Validation should not work because course_id field is unique
        self.assertFalse(form.is_valid())
        self.assertEquals(
            "Embargoed course with this Course id already exists.",
            form._errors['course_id'][0]  # pylint: disable=protected-access
        )
        with self.assertRaisesRegexp(
                ValueError,
                "The EmbargoedCourse could not be created because the data didn't validate."
        ):
            form.save()

        # Course should still be authorized (invalid attempt had no effect)
        self.assertTrue(EmbargoedCourse.is_embargoed(self.course.id))
Ejemplo n.º 3
0
 def test_embargo_course(self):
     self.assertFalse(EmbargoedCourse.is_embargoed(self.course.id))
     # Test adding embargo to this course
     form = EmbargoedCourseForm(data=self.true_form_data)
     # Validation should work
     self.assertTrue(form.is_valid())
     form.save()
     # Check that this course is embargoed
     self.assertTrue(EmbargoedCourse.is_embargoed(self.course.id))
Ejemplo n.º 4
0
 def test_embargo_course(self):
     self.assertFalse(EmbargoedCourse.is_embargoed(self.course.id))
     # Test adding embargo to this course
     form = EmbargoedCourseForm(data=self.true_form_data)
     # Validation should work
     self.assertTrue(form.is_valid())
     form.save()
     # Check that this course is embargoed
     self.assertTrue(EmbargoedCourse.is_embargoed(self.course.id))
Ejemplo n.º 5
0
    def test_course_embargo(self):
        course_id = CourseLocator('abc', '123', 'doremi')
        # Test that course is not authorized by default
        self.assertFalse(EmbargoedCourse.is_embargoed(course_id))

        # Authorize
        cauth = EmbargoedCourse(course_id=course_id, embargoed=True)
        cauth.save()

        # Now, course should be embargoed
        self.assertTrue(EmbargoedCourse.is_embargoed(course_id))
        self.assertEquals(
            unicode(cauth),
            u"Course '{course_id}' is Embargoed".format(course_id=course_id)
        )

        # Unauthorize by explicitly setting email_enabled to False
        cauth.embargoed = False
        cauth.save()
        # Test that course is now unauthorized
        self.assertFalse(EmbargoedCourse.is_embargoed(course_id))
        self.assertEquals(
            unicode(cauth),
            u"Course '{course_id}' is Not Embargoed".format(course_id=course_id)
        )
Ejemplo n.º 6
0
    def process_request(self, request):
        """
        Processes embargo requests
        """
        url = request.path
        course_id = course_id_from_url(url)

        # If they're trying to access a course that cares about embargoes
        if EmbargoedCourse.is_embargoed(course_id):
            # If we're having performance issues, add caching here
            ip_addr = get_ip(request)

            # if blacklisted, immediately fail
            if ip_addr in IPFilter.current().blacklist_ips:
                log.info(
                    "Embargo: Restricting IP address %s to course %s because IP is blacklisted.",
                    ip_addr, course_id)
                return redirect('embargo')

            country_code_from_ip = pygeoip.GeoIP(
                settings.GEOIP_PATH).country_code_by_addr(ip_addr)
            is_embargoed = country_code_from_ip in EmbargoedState.current(
            ).embargoed_countries_list
            # Fail if country is embargoed and the ip address isn't explicitly whitelisted
            if is_embargoed and ip_addr not in IPFilter.current(
            ).whitelist_ips:
                log.info(
                    "Embargo: Restricting IP address %s to course %s because IP is from country %s.",
                    ip_addr, course_id, country_code_from_ip)
                return redirect('embargo')
Ejemplo n.º 7
0
    def process_request(self, request):
        """
        Processes embargo requests.
        """
        url = request.path
        course_id = course_id_from_url(url)
        course_is_embargoed = EmbargoedCourse.is_embargoed(course_id)

        # If they're trying to access a course that cares about embargoes
        if self.site_enabled or course_is_embargoed:

            # Construct the list of functions that check whether the user is embargoed.
            # We wrap each of these functions in a decorator that logs the reason the user
            # was blocked.
            # Each function should return `True` iff the user is blocked by an embargo.
            check_functions = [
                self._log_embargo_reason(check_func, course_id, course_is_embargoed)
                for check_func in [
                    partial(self._is_embargoed_by_ip, get_ip(request)),
                    partial(self._is_embargoed_by_profile_country, request.user)
                ]
            ]

            # Perform each of the checks
            # If the user fails any of the checks, immediately redirect them
            # and skip later checks.
            for check_func in check_functions:
                if check_func():
                    return self._embargo_redirect_response
Ejemplo n.º 8
0
    def process_request(self, request):
        """
        Processes embargo requests
        """
        url = request.path
        course_id = course_id_from_url(url)

        # If they're trying to access a course that cares about embargoes
        if EmbargoedCourse.is_embargoed(course_id):
            # If we're having performance issues, add caching here
            ip_addr = get_ip(request)

            # if blacklisted, immediately fail
            if ip_addr in IPFilter.current().blacklist_ips:
                log.info("Embargo: Restricting IP address %s to course %s because IP is blacklisted.", ip_addr, course_id)
                return redirect('embargo')

            country_code_from_ip = pygeoip.GeoIP(settings.GEOIP_PATH).country_code_by_addr(ip_addr)
            is_embargoed = country_code_from_ip in EmbargoedState.current().embargoed_countries_list
            # Fail if country is embargoed and the ip address isn't explicitly whitelisted
            if is_embargoed and ip_addr not in IPFilter.current().whitelist_ips:
                log.info(
                    "Embargo: Restricting IP address %s to course %s because IP is from country %s.",
                    ip_addr, course_id, country_code_from_ip
                )
                return redirect('embargo')
Ejemplo n.º 9
0
    def setUp(self):
        super(EmbargoMiddlewareTests, self).setUp()

        self.user = UserFactory(username='******', password='******')
        self.client.login(username='******', password='******')
        self.embargo_course = CourseFactory.create()
        self.embargo_course.save()
        self.regular_course = CourseFactory.create(org="Regular")
        self.regular_course.save()
        self.embargoed_page = '/courses/' + self.embargo_course.id.to_deprecated_string(
        ) + '/info'
        self.regular_page = '/courses/' + self.regular_course.id.to_deprecated_string(
        ) + '/info'
        EmbargoedCourse(course_id=self.embargo_course.id,
                        embargoed=True).save()
        EmbargoedState(embargoed_countries="cu, ir, Sy, SD",
                       changed_by=self.user,
                       enabled=True).save()
        CourseEnrollment.enroll(self.user, self.regular_course.id)
        CourseEnrollment.enroll(self.user, self.embargo_course.id)
        # Text from lms/templates/static_templates/embargo.html
        self.embargo_text = "Unfortunately, at this time edX must comply with export controls, and we cannot allow you to access this course."

        self.patcher = mock.patch.object(pygeoip.GeoIP, 'country_code_by_addr',
                                         self.mock_country_code_by_addr)
        self.patcher.start()
Ejemplo n.º 10
0
    def process_request(self, request):
        """
        Processes embargo requests.
        """
        url = request.path
        course_id = course_id_from_url(url)
        course_is_embargoed = EmbargoedCourse.is_embargoed(course_id)

        # If they're trying to access a course that cares about embargoes
        if self.site_enabled or course_is_embargoed:

            # Construct the list of functions that check whether the user is embargoed.
            # We wrap each of these functions in a decorator that logs the reason the user
            # was blocked.
            # Each function should return `True` iff the user is blocked by an embargo.
            check_functions = [
                self._log_embargo_reason(check_func, course_id, course_is_embargoed)
                for check_func in [
                    partial(self._is_embargoed_by_ip, get_ip(request)),
                    partial(self._is_embargoed_by_profile_country, request.user)
                ]
            ]

            # Perform each of the checks
            # If the user fails any of the checks, immediately redirect them
            # and skip later checks.
            for check_func in check_functions:
                if check_func():
                    return self._embargo_redirect_response
Ejemplo n.º 11
0
    def process_request(self, request):
        """
        Processes embargo requests
        """
        url = request.path
        course_id = course_id_from_url(url)
        course_is_embargoed = EmbargoedCourse.is_embargoed(course_id)

        # If they're trying to access a course that cares about embargoes
        if self.site_enabled or course_is_embargoed:
            response = redirect('embargo')
            # Set the proper response if site is enabled
            if self.site_enabled:
                redirect_url = getattr(settings, 'EMBARGO_SITE_REDIRECT_URL',
                                       None)
                response = HttpResponseRedirect(redirect_url) if redirect_url \
                           else HttpResponseForbidden('Access Denied')

            # If we're having performance issues, add caching here
            ip_addr = get_ip(request)

            # if blacklisted, immediately fail
            if ip_addr in IPFilter.current().blacklist_ips:
                if course_is_embargoed:
                    msg = "Embargo: Restricting IP address %s to course %s because IP is blacklisted." % \
                          (ip_addr, course_id)
                else:
                    msg = "Embargo: Restricting IP address %s because IP is blacklisted." % ip_addr
                log.info(msg)
                return response
            # ipv6 support
            if ip_addr.find(':') >= 0:
                country_code_from_ip = pygeoip.GeoIP(
                    settings.GEOIPV6_PATH).country_code_by_addr(ip_addr)
            else:
                country_code_from_ip = pygeoip.GeoIP(
                    settings.GEOIP_PATH).country_code_by_addr(ip_addr)

            is_embargoed = country_code_from_ip in EmbargoedState.current(
            ).embargoed_countries_list
            # Fail if country is embargoed and the ip address isn't explicitly
            # whitelisted
            if is_embargoed and ip_addr not in IPFilter.current(
            ).whitelist_ips:
                if course_is_embargoed:
                    msg = "Embargo: Restricting IP address %s to course %s because IP is from country %s." % \
                          (ip_addr, course_id, country_code_from_ip)
                else:
                    msg = "Embargo: Restricting IP address %s because IP is from country %s." % \
                          (ip_addr, country_code_from_ip)

                log.info(msg)
                return response
Ejemplo n.º 12
0
    def process_request(self, request):
        """
        Processes embargo requests
        """
        url = request.path
        course_id = course_id_from_url(url)
        course_is_embargoed = EmbargoedCourse.is_embargoed(course_id)

        # If they're trying to access a course that cares about embargoes
        if self.site_enabled or course_is_embargoed:
            response = redirect("embargo")
            # Set the proper response if site is enabled
            if self.site_enabled:
                redirect_url = getattr(settings, "EMBARGO_SITE_REDIRECT_URL", None)
                response = (
                    HttpResponseRedirect(redirect_url) if redirect_url else HttpResponseForbidden("Access Denied")
                )

            # If we're having performance issues, add caching here
            ip_addr = get_ip(request)

            # if blacklisted, immediately fail
            if ip_addr in IPFilter.current().blacklist_ips:
                if course_is_embargoed:
                    msg = "Embargo: Restricting IP address %s to course %s because IP is blacklisted." % (
                        ip_addr,
                        course_id,
                    )
                else:
                    msg = "Embargo: Restricting IP address %s because IP is blacklisted." % ip_addr

                log.info(msg)
                return response

            country_code_from_ip = pygeoip.GeoIP(settings.GEOIP_PATH).country_code_by_addr(ip_addr)
            is_embargoed = country_code_from_ip in EmbargoedState.current().embargoed_countries_list
            # Fail if country is embargoed and the ip address isn't explicitly whitelisted
            if is_embargoed and ip_addr not in IPFilter.current().whitelist_ips:
                if course_is_embargoed:
                    msg = "Embargo: Restricting IP address %s to course %s because IP is from country %s." % (
                        ip_addr,
                        course_id,
                        country_code_from_ip,
                    )
                else:
                    msg = "Embargo: Restricting IP address %s because IP is from country %s." % (
                        ip_addr,
                        country_code_from_ip,
                    )

                log.info(msg)
                return response
Ejemplo n.º 13
0
    def test_course_embargo(self):
        course_id = CourseLocator('abc', '123', 'doremi')
        # Test that course is not authorized by default
        self.assertFalse(EmbargoedCourse.is_embargoed(course_id))

        # Authorize
        cauth = EmbargoedCourse(course_id=course_id, embargoed=True)
        cauth.save()

        # Now, course should be embargoed
        self.assertTrue(EmbargoedCourse.is_embargoed(course_id))
        self.assertEquals(
            unicode(cauth),
            u"Course '{course_id}' is Embargoed".format(course_id=course_id))

        # Unauthorize by explicitly setting email_enabled to False
        cauth.embargoed = False
        cauth.save()
        # Test that course is now unauthorized
        self.assertFalse(EmbargoedCourse.is_embargoed(course_id))
        self.assertEquals(
            unicode(cauth), u"Course '{course_id}' is Not Embargoed".format(
                course_id=course_id))
Ejemplo n.º 14
0
    def process_request(self, request):
        """Block requests based on embargo rules.

        In the new ENABLE_COUNTRY_ACCESS implmentation,
        this will perform the following checks:

        1) If the user's IP address is blacklisted, block.
        2) If the user's IP address is whitelisted, allow.
        3) If the user's country (inferred from their IP address) is blocked for
            a courseware page, block.
        4) If the user's country (retrieved from the user's profile) is blocked
            for a courseware page, block.
        5) Allow access.

        """
        # If the feature flag is set, use the new "country access" implementation.
        # This is a more flexible implementation of the embargo feature that allows
        # per-course country access rules.
        if self.enable_country_access:

            # Never block certain patterns by IP address
            for pattern in self.ALLOW_URL_PATTERNS:
                if pattern.match(request.path) is not None:
                    return None

            ip_address = get_ip(request)
            ip_filter = IPFilter.current()

            if ip_filter.enabled and ip_address in ip_filter.blacklist_ips:
                log.info(
                    (
                        u"User %s was blocked from accessing %s "
                        u"because IP address %s is blacklisted."
                    ), request.user.id, request.path, ip_address
                )

                # If the IP is blacklisted, reject.
                # This applies to any request, not just courseware URLs.
                ip_blacklist_url = reverse(
                    'embargo_blocked_message',
                    kwargs={
                        'access_point': 'courseware',
                        'message_key': 'embargo'
                    }
                )
                return redirect(ip_blacklist_url)

            elif ip_filter.enabled and ip_address in ip_filter.whitelist_ips:
                log.info(
                    (
                        u"User %s was allowed access to %s because "
                        u"IP address %s is whitelisted."
                    ),
                    request.user.id, request.path, ip_address
                )

                # If the IP is whitelisted, then allow access,
                # skipping later checks.
                return None

            else:
                # Otherwise, perform the country access checks.
                # This applies only to courseware URLs.
                return self.country_access_rules(request.user, ip_address, request.path)

        url = request.path
        course_id = course_id_from_url(url)
        course_is_embargoed = EmbargoedCourse.is_embargoed(course_id)

        # If they're trying to access a course that cares about embargoes
        if self.site_enabled or course_is_embargoed:

            # Construct the list of functions that check whether the user is embargoed.
            # We wrap each of these functions in a decorator that logs the reason the user
            # was blocked.
            # Each function should return `True` iff the user is blocked by an embargo.
            check_functions = [
                self._log_embargo_reason(check_func, course_id, course_is_embargoed)
                for check_func in [
                    partial(self._is_embargoed_by_ip, get_ip(request)),
                    partial(self._is_embargoed_by_profile_country, request.user)
                ]
            ]

            # Perform each of the checks
            # If the user fails any of the checks, immediately redirect them
            # and skip later checks.
            for check_func in check_functions:
                if check_func():
                    return self._embargo_redirect_response
Ejemplo n.º 15
0
    def test_course_embargo(self):
        course_id = SlashSeparatedCourseKey('abc', '123', 'doremi')
        # Test that course is not authorized by default
        self.assertFalse(EmbargoedCourse.is_embargoed(course_id))

        # Authorize
        cauth = EmbargoedCourse(course_id=course_id, embargoed=True)
        cauth.save()

        # Now, course should be embargoed
        self.assertTrue(EmbargoedCourse.is_embargoed(course_id))
        self.assertEquals(cauth.__unicode__(),
                          "Course 'abc/123/doremi' is Embargoed")

        # Unauthorize by explicitly setting email_enabled to False
        cauth.embargoed = False
        cauth.save()
        # Test that course is now unauthorized
        self.assertFalse(EmbargoedCourse.is_embargoed(course_id))
        self.assertEquals(cauth.__unicode__(),
                          "Course 'abc/123/doremi' is Not Embargoed")
Ejemplo n.º 16
0
    def process_request(self, request):
        """Block requests based on embargo rules.

        In the new ENABLE_COUNTRY_ACCESS implmentation,
        this will perform the following checks:

        1) If the user's IP address is blacklisted, block.
        2) If the user's IP address is whitelisted, allow.
        3) If the user's country (inferred from their IP address) is blocked for
            a courseware page, block.
        4) If the user's country (retrieved from the user's profile) is blocked
            for a courseware page, block.
        5) Allow access.

        """
        # If the feature flag is set, use the new "country access" implementation.
        # This is a more flexible implementation of the embargo feature that allows
        # per-course country access rules.
        if self.enable_country_access:

            # Never block certain patterns by IP address
            for pattern in self.ALLOW_URL_PATTERNS:
                if pattern.match(request.path) is not None:
                    return None

            ip_address = get_ip(request)
            ip_filter = IPFilter.current()

            if ip_filter.enabled and ip_address in ip_filter.blacklist_ips:
                log.info((u"User %s was blocked from accessing %s "
                          u"because IP address %s is blacklisted."),
                         request.user.id, request.path, ip_address)

                # If the IP is blacklisted, reject.
                # This applies to any request, not just courseware URLs.
                ip_blacklist_url = reverse('embargo_blocked_message',
                                           kwargs={
                                               'access_point': 'courseware',
                                               'message_key': 'embargo'
                                           })
                return redirect(ip_blacklist_url)

            elif ip_filter.enabled and ip_address in ip_filter.whitelist_ips:
                log.info((u"User %s was allowed access to %s because "
                          u"IP address %s is whitelisted."), request.user.id,
                         request.path, ip_address)

                # If the IP is whitelisted, then allow access,
                # skipping later checks.
                return None

            else:
                # Otherwise, perform the country access checks.
                # This applies only to courseware URLs.
                return self.country_access_rules(request.user, ip_address,
                                                 request.path)

        url = request.path
        course_id = course_id_from_url(url)
        course_is_embargoed = EmbargoedCourse.is_embargoed(course_id)

        # If they're trying to access a course that cares about embargoes
        if self.site_enabled or course_is_embargoed:

            # Construct the list of functions that check whether the user is embargoed.
            # We wrap each of these functions in a decorator that logs the reason the user
            # was blocked.
            # Each function should return `True` iff the user is blocked by an embargo.
            check_functions = [
                self._log_embargo_reason(check_func, course_id,
                                         course_is_embargoed)
                for check_func in [
                    partial(self._is_embargoed_by_ip, get_ip(request)),
                    partial(self._is_embargoed_by_profile_country,
                            request.user)
                ]
            ]

            # Perform each of the checks
            # If the user fails any of the checks, immediately redirect them
            # and skip later checks.
            for check_func in check_functions:
                if check_func():
                    return self._embargo_redirect_response
Ejemplo n.º 17
0
    def test_course_embargo(self):
        course_id = 'abc/123/doremi'
        # Test that course is not authorized by default
        self.assertFalse(EmbargoedCourse.is_embargoed(course_id))

        # Authorize
        cauth = EmbargoedCourse(course_id=course_id, embargoed=True)
        cauth.save()

        # Now, course should be embargoed
        self.assertTrue(EmbargoedCourse.is_embargoed(course_id))
        self.assertEquals(
            cauth.__unicode__(),
            "Course 'abc/123/doremi' is Embargoed"
        )

        # Unauthorize by explicitly setting email_enabled to False
        cauth.embargoed = False
        cauth.save()
        # Test that course is now unauthorized
        self.assertFalse(EmbargoedCourse.is_embargoed(course_id))
        self.assertEquals(
            cauth.__unicode__(),
            "Course 'abc/123/doremi' is Not Embargoed"
        )