feat: add first batch of Open edX Filters
* Add PreEnrollmentFilter * Add PreRegisterFilter * Add PreLoginFilter
This commit is contained in:
@@ -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.
|
||||
|
||||
104
common/djangoapps/student/tests/test_filters.py
Normal file
104
common/djangoapps/student/tests/test_filters.py
Normal 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))
|
||||
Reference in New Issue
Block a user