Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions common/djangoapps/student/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ def run_filter(self, context, template_name): # pylint: disable=arguments-diffe
}


class TestEnterpriseContextEnricherStep(PipelineStep):
"""
Utility pipeline step that simulates enterprise context enrichment via DashboardContextEnricher.
Verifies that 'request' is present in context and injects a sentinel enterprise key.
"""

def run_filter(self, context, template_name): # pylint: disable=arguments-differ
"""Inject a sentinel enterprise key to prove the pipeline ran."""
assert 'request' in context, "'request' must be in dashboard context for enterprise enrichment"
context['enterprise_message'] = 'test-enterprise-message'
context['is_enterprise_user'] = True
return {"context": context, "template_name": template_name}


class TestRenderInvalidDashboard(PipelineStep):
"""
Utility class used when getting steps for pipeline.
Expand Down Expand Up @@ -464,3 +478,27 @@ def test_dashboard_render_without_filter_config(self):

self.assertContains(response, self.first_course.id)
self.assertContains(response, self.second_course.id)

@override_settings(
OPEN_EDX_FILTERS_CONFIG={
"org.openedx.learning.dashboard.render.started.v1": {
"pipeline": [
"common.djangoapps.student.tests.test_filters.TestEnterpriseContextEnricherStep",
],
"fail_silently": False,
},
},
)
def test_dashboard_context_enricher_receives_request(self):
"""
Test that the context passed to DashboardRenderStarted includes 'request', allowing
pipeline steps like DashboardContextEnricher to access it for enterprise enrichment.

Expected result:
- DashboardRenderStarted is triggered and executes TestEnterpriseContextEnricherStep.
- The step finds 'request' in context and injects enterprise sentinel values.
- The dashboard renders successfully (HTTP 200).
"""
response = self.client.get(self.dashboard_url)

self.assertEqual(response.status_code, 200)
Comment on lines +500 to +504
15 changes: 1 addition & 14 deletions common/djangoapps/student/views/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@
from openedx.core.djangolib.markup import HTML, Text
from openedx.features.content_type_gating.models import ContentTypeGatingConfig
from openedx.features.course_duration_limits.access import get_user_course_duration, get_user_course_expiration_date
from openedx.features.enterprise_support.api import (
get_dashboard_consent_notification,
get_enterprise_learner_portal_context,
)
from openedx.features.enterprise_support.utils import is_enterprise_learner

from common.djangoapps.student.api import COURSE_DASHBOARD_PLUGIN_VIEW_NAME
from common.djangoapps.student.helpers import cert_info, check_verify_status_by_course, get_resume_urls_for_enrollments
Expand Down Expand Up @@ -617,8 +612,6 @@ def student_dashboard(request): # lint-amnesty, pylint: disable=too-many-statem
link_end=HTML("</a>"),
)

enterprise_message = get_dashboard_consent_notification(request, user, course_enrollments)

recovery_email_message = recovery_email_activation_message = None
if is_secondary_email_feature_enabled():
try:
Expand Down Expand Up @@ -799,7 +792,7 @@ def student_dashboard(request): # lint-amnesty, pylint: disable=too-many-statem
context = {
'urls': urls,
'programs_data': programs_data,
'enterprise_message': enterprise_message,
'request': request,
'consent_required_courses': consent_required_courses,
'enrollment_message': enrollment_message,
'redirect_message': Text(redirect_message),
Expand Down Expand Up @@ -850,14 +843,8 @@ def student_dashboard(request): # lint-amnesty, pylint: disable=too-many-statem
'course_info': get_dashboard_course_info(user, course_enrollments),
# TODO START: clean up as part of REVEM-199 (END)
'disable_unenrollment': disable_unenrollment,
# TODO: clean when experiment(Merchandise 2U LOBs - Dashboard) would be stop. [VAN-1097]
'is_enterprise_user': is_enterprise_learner(user),
}

# Include enterprise learner portal metadata and messaging
enterprise_learner_portal_context = get_enterprise_learner_portal_context(request)
context.update(enterprise_learner_portal_context)

context_from_plugins = get_plugins_view_context(
ProjectType.LMS,
COURSE_DASHBOARD_PLUGIN_VIEW_NAME,
Expand Down
12 changes: 12 additions & 0 deletions lms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3717,3 +3717,15 @@ def _should_send_certificate_events(settings):
SSL_AUTH_DN_FORMAT_STRING = (
"/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}"
)

# .. setting_name: OPEN_EDX_FILTERS_CONFIG
# .. setting_default: {}
# .. setting_description: Configuration dict for openedx-filters pipeline steps.
# Keys are filter type strings; values are dicts with 'fail_silently' (bool) and
# 'pipeline' (list of dotted-path strings to PipelineStep subclasses).
OPEN_EDX_FILTERS_CONFIG = {
Comment on lines +3721 to +3726
"org.openedx.learning.dashboard.render.started.v1": {
"fail_silently": True,
"pipeline": [],
},
}
13 changes: 13 additions & 0 deletions lms/envs/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,19 @@ def get_env_setting(setting):
_YAML_TOKENS.get('EVENT_BUS_PRODUCER_CONFIG', {})
)

# Merge OPEN_EDX_FILTERS_CONFIG from YAML into the default defined in common.py.
# Pipeline steps from YAML are appended after steps defined in common.py.
# The fail_silently value from YAML takes precedence over the one in common.py.
for _filter_type, _filter_config in _YAML_TOKENS.get('OPEN_EDX_FILTERS_CONFIG', {}).items():
if _filter_type in OPEN_EDX_FILTERS_CONFIG:
OPEN_EDX_FILTERS_CONFIG[_filter_type]['pipeline'].extend(
_filter_config.get('pipeline', [])
)
if 'fail_silently' in _filter_config:
OPEN_EDX_FILTERS_CONFIG[_filter_type]['fail_silently'] = _filter_config['fail_silently']
else:
OPEN_EDX_FILTERS_CONFIG[_filter_type] = _filter_config
Comment on lines +522 to +533

#######################################################################################################################
# HEY! Don't add anything to the end of this file.
# Add your defaults to common.py instead!
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ openedx-events==10.5.0
# edx-name-affirmation
# event-tracking
# ora2
openedx-filters==2.1.0
openedx-filters==3.3.0
# via
# -r requirements/edx/kernel.in
# edx-enterprise
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/development.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1380,7 +1380,7 @@ openedx-events==10.5.0
# edx-name-affirmation
# event-tracking
# ora2
openedx-filters==2.1.0
openedx-filters==3.3.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ openedx-events==10.5.0
# edx-name-affirmation
# event-tracking
# ora2
openedx-filters==2.1.0
openedx-filters==3.3.0
# via
# -r requirements/edx/base.txt
# edx-enterprise
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1050,7 +1050,7 @@ openedx-events==10.5.0
# edx-name-affirmation
# event-tracking
# ora2
openedx-filters==2.1.0
openedx-filters==3.3.0
# via
# -r requirements/edx/base.txt
# edx-enterprise
Expand Down
Loading