feat: add first batch of Open edX Filters

* Add PreEnrollmentFilter
* Add PreRegisterFilter
* Add PreLoginFilter
This commit is contained in:
Maria Grimaldi
2021-11-26 16:47:56 -04:00
parent 3eea5d9337
commit f29a4eef68
9 changed files with 417 additions and 0 deletions

View File

@@ -66,6 +66,7 @@ from openedx_events.learning.signals import (
COURSE_ENROLLMENT_CREATED,
COURSE_UNENROLLMENT_COMPLETED,
)
from openedx_filters.learning.filters import CourseEnrollmentStarted
import openedx.core.djangoapps.django_comment_common.comment_client as cc
from common.djangoapps.course_modes.models import CourseMode, get_cosmetic_verified_display_price
from common.djangoapps.student.emails import send_proctoring_requirements_email
@@ -1117,6 +1118,10 @@ class AlreadyEnrolledError(CourseEnrollmentException):
pass
class EnrollmentNotAllowed(CourseEnrollmentException):
pass
class CourseEnrollmentManager(models.Manager):
"""
Custom manager for CourseEnrollment with Table-level filter methods.
@@ -1627,6 +1632,13 @@ class CourseEnrollment(models.Model):
Also emits relevant events for analytics purposes.
"""
try:
user, course_key, mode = CourseEnrollmentStarted.run_filter(
user=user, course_key=course_key, mode=mode,
)
except CourseEnrollmentStarted.PreventEnrollment as exc:
raise EnrollmentNotAllowed(str(exc)) from exc
if mode is None:
mode = _default_course_mode(str(course_key))
# All the server-side checks for whether a user is allowed to enroll.

View File

@@ -0,0 +1,104 @@
"""
Test that various filters are fired for models in the student app.
"""
from django.test import override_settings
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from openedx_filters.learning.filters import CourseEnrollmentStarted
from openedx_filters import PipelineStep
from common.djangoapps.student.models import CourseEnrollment, EnrollmentNotAllowed
from common.djangoapps.student.tests.factories import UserFactory, UserProfileFactory
from openedx.core.djangolib.testing.utils import skip_unless_lms
class TestEnrollmentPipelineStep(PipelineStep):
"""
Utility function used when getting steps for pipeline.
"""
def run_filter(self, user, course_key, mode): # pylint: disable=arguments-differ
"""Pipeline steps that changes mode to honor."""
if mode == "no-id-professional":
raise CourseEnrollmentStarted.PreventEnrollment()
return {"mode": "honor"}
@skip_unless_lms
class EnrollmentFiltersTest(ModuleStoreTestCase):
"""
Tests for the Open edX Filters associated with the enrollment process through the enroll method.
This class guarantees that the following filters are triggered during the user's enrollment:
- CourseEnrollmentStarted
"""
def setUp(self): # pylint: disable=arguments-differ
super().setUp()
self.course = CourseFactory.create()
self.user = UserFactory.create(
username="test",
email="test@example.com",
password="password",
)
self.user_profile = UserProfileFactory.create(user=self.user, name="Test Example")
@override_settings(
OPEN_EDX_FILTERS_CONFIG={
"org.openedx.learning.course.enrollment.started.v1": {
"pipeline": [
"common.djangoapps.student.tests.test_filters.TestEnrollmentPipelineStep",
],
"fail_silently": False,
},
},
)
def test_enrollment_filter_executed(self):
"""
Test whether the student enrollment filter is triggered before the user's
enrollment process.
Expected result:
- CourseEnrollmentStarted is triggered and executes TestEnrollmentPipelineStep.
- The arguments that the receiver gets are the arguments used by the filter
with the enrollment mode changed.
"""
enrollment = CourseEnrollment.enroll(self.user, self.course.id, mode='audit')
self.assertEqual('honor', enrollment.mode)
@override_settings(
OPEN_EDX_FILTERS_CONFIG={
"org.openedx.learning.course.enrollment.started.v1": {
"pipeline": [
"common.djangoapps.student.tests.test_filters.TestEnrollmentPipelineStep",
],
"fail_silently": False,
},
},
)
def test_enrollment_filter_prevent_enroll(self):
"""
Test prevent the user's enrollment through a pipeline step.
Expected result:
- CourseEnrollmentStarted is triggered and executes TestEnrollmentPipelineStep.
- The user can't enroll.
"""
with self.assertRaises(EnrollmentNotAllowed):
CourseEnrollment.enroll(self.user, self.course.id, mode='no-id-professional')
@override_settings(OPEN_EDX_FILTERS_CONFIG={})
def test_enrollment_without_filter_configuration(self):
"""
Test usual enrollment process, without filter's intervention.
Expected result:
- CourseEnrollmentStarted does not have any effect on the enrollment process.
- The enrollment process ends successfully.
"""
enrollment = CourseEnrollment.enroll(self.user, self.course.id, mode='audit')
self.assertEqual('audit', enrollment.mode)
self.assertTrue(CourseEnrollment.is_enrolled(self.user, self.course.id))