Skip to content

Commit

Permalink
feat: add openedx-filters hook to account settings before rendering i…
Browse files Browse the repository at this point in the history
…t context (#31295)
  • Loading branch information
Henrrypg authored and JuanDavidBuitrago committed Jul 21, 2023
1 parent 1611ec1 commit 2d4cbb0
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 4 deletions.
22 changes: 21 additions & 1 deletion openedx/core/djangoapps/user_api/accounts/settings_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.translation import gettext as _
from django.views.decorators.http import require_http_methods
from django_countries import countries

from openedx_filters.learning.filters import AccountSettingsRenderStarted
from common.djangoapps import third_party_auth
from common.djangoapps.edxmako.shortcuts import render_to_response
from common.djangoapps.student.models import UserProfile
Expand Down Expand Up @@ -72,7 +74,25 @@ def account_settings(request):
return redirect(url)

context = account_settings_context(request)
return render_to_response('student_account/account_settings.html', context)

account_settings_template = 'student_account/account_settings.html'

try:
# .. filter_implemented_name: AccountSettingsRenderStarted
# .. filter_type: org.openedx.learning.student.settings.render.started.v1
context, account_settings_template = AccountSettingsRenderStarted.run_filter(
context=context, template_name=account_settings_template,
)
except AccountSettingsRenderStarted.RenderInvalidAccountSettings as exc:
response = render_to_response(exc.account_settings_template, exc.template_context)
except AccountSettingsRenderStarted.RedirectToPage as exc:
response = HttpResponseRedirect(exc.redirect_to or reverse('dashboard'))
except AccountSettingsRenderStarted.RenderCustomResponse as exc:
response = exc.response
else:
response = render_to_response(account_settings_template, context)

return response


def account_settings_context(request):
Expand Down
241 changes: 241 additions & 0 deletions openedx/core/djangoapps/user_api/accounts/tests/test_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
"""
Test that various filters are fired for views in the certificates app.
"""
from django.http import HttpResponse
from django.test import override_settings
from django.urls import reverse
from openedx_filters import PipelineStep
from openedx_filters.learning.filters import AccountSettingsRenderStarted
from rest_framework import status
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase

from openedx.core.djangolib.testing.utils import skip_unless_lms
from common.djangoapps.student.tests.factories import UserFactory


class TestRenderInvalidAccountSettings(PipelineStep):
"""
Utility class used when getting steps for pipeline.
"""

def run_filter(self, context, template_name): # pylint: disable=arguments-differ
"""
Pipeline step that stops the course about render process.
"""
raise AccountSettingsRenderStarted.RenderInvalidAccountSettings(
"You can't access the account settings page.",
account_settings_template="static_templates/server-error.html",
)


class TestRedirectToPage(PipelineStep):
"""
Utility class used when getting steps for pipeline.
"""

def run_filter(self, context, template_name): # pylint: disable=arguments-differ
"""
Pipeline step that redirects to dashboard before rendering the account settings page.
When raising RedirectToPage, this filter uses a redirect_to field handled by
the course about view that redirects to that URL.
"""
raise AccountSettingsRenderStarted.RedirectToPage(
"You can't access this page, redirecting to dashboard.",
redirect_to="/courses",
)


class TestRedirectToDefaultPage(PipelineStep):
"""
Utility class used when getting steps for pipeline.
"""

def run_filter(self, context, template_name): # pylint: disable=arguments-differ
"""
Pipeline step that redirects to dashboard before rendering the account settings page.
When raising RedirectToPage, this filter uses a redirect_to field handled by
the course about view that redirects to that URL.
"""
raise AccountSettingsRenderStarted.RedirectToPage(
"You can't access this page, redirecting to dashboard."
)


class TestRenderCustomResponse(PipelineStep):
"""
Utility class used when getting steps for pipeline.
"""

def run_filter(self, context, template_name): # pylint: disable=arguments-differ
"""Pipeline step that returns a custom response when rendering the account settings page."""
response = HttpResponse("Here's the text of the web page.")
raise AccountSettingsRenderStarted.RenderCustomResponse(
"You can't access this page.",
response=response,
)


class TestAccountSettingsRender(PipelineStep):
"""
Utility class used when getting steps for pipeline.
"""

def run_filter(self, context, template_name): # pylint: disable=arguments-differ
"""Pipeline step that returns a custom response when rendering the account settings page."""
template_name = 'static_templates/about.html'
return {
"context": context, "template_name": template_name,
}


@skip_unless_lms
class TestAccountSettingsFilters(SharedModuleStoreTestCase):
"""
Tests for the Open edX Filters associated with the account settings proccess.
This class guarantees that the following filters are triggered during the user's account settings rendering:
- AccountSettingsRenderStarted
"""
def setUp(self): # pylint: disable=arguments-differ
super().setUp()
self.user = UserFactory.create(
username="somestudent",
first_name="Student",
last_name="Person",
email="robot@robot.org",
is_active=True,
password="password",
)
self.client.login(username=self.user.username, password="password")
self.account_settings_url = '/account/settings'

@override_settings(
OPEN_EDX_FILTERS_CONFIG={
"org.openedx.learning.student.settings.render.started.v1": {
"pipeline": [
"openedx.core.djangoapps.user_api.accounts.tests.test_filters.TestAccountSettingsRender",
],
"fail_silently": False,
},
},
)
def test_account_settings_render_filter_executed(self):
"""
Test whether the account settings filter is triggered before the user's
account settings page is rendered.
Expected result:
- AccountSettingsRenderStarted is triggered and executes TestAccountSettingsRender
"""
response = self.client.get(self.account_settings_url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertContains(response, "This page left intentionally blank. Feel free to add your own content.")

@override_settings(
OPEN_EDX_FILTERS_CONFIG={
"org.openedx.learning.student.settings.render.started.v1": {
"pipeline": [
"openedx.core.djangoapps.user_api.accounts.tests.test_filters.TestRenderInvalidAccountSettings", # pylint: disable=line-too-long
],
"fail_silently": False,
},
},
PLATFORM_NAME="My site",
)
def test_account_settings_render_alternative(self):
"""
Test whether the account settings filter is triggered before the user's
account settings page is rendered.
Expected result:
- AccountSettingsRenderStarted is triggered and executes TestRenderInvalidAccountSettings # pylint: disable=line-too-long
"""
response = self.client.get(self.account_settings_url)

self.assertContains(response, "There has been a 500 error on the <em>My site</em> servers")

@override_settings(
OPEN_EDX_FILTERS_CONFIG={
"org.openedx.learning.student.settings.render.started.v1": {
"pipeline": [
"openedx.core.djangoapps.user_api.accounts.tests.test_filters.TestRenderCustomResponse",
],
"fail_silently": False,
},
},
)
def test_account_settings_render_custom_response(self):
"""
Test whether the account settings filter is triggered before the user's
account settings page is rendered.
Expected result:
- AccountSettingsRenderStarted is triggered and executes TestRenderCustomResponse
"""
response = self.client.get(self.account_settings_url)

self.assertEqual(response.content, b"Here's the text of the web page.")

@override_settings(
OPEN_EDX_FILTERS_CONFIG={
"org.openedx.learning.student.settings.render.started.v1": {
"pipeline": [
"openedx.core.djangoapps.user_api.accounts.tests.test_filters.TestRedirectToPage",
],
"fail_silently": False,
},
},
)
def test_account_settings_redirect_to_page(self):
"""
Test whether the account settings filter is triggered before the user's
account settings page is rendered.
Expected result:
- AccountSettingsRenderStarted is triggered and executes TestRedirectToPage
"""
response = self.client.get(self.account_settings_url)

self.assertEqual(response.status_code, status.HTTP_302_FOUND)
self.assertEqual('/courses', response.url)

@override_settings(
OPEN_EDX_FILTERS_CONFIG={
"org.openedx.learning.student.settings.render.started.v1": {
"pipeline": [
"openedx.core.djangoapps.user_api.accounts.tests.test_filters.TestRedirectToDefaultPage",
],
"fail_silently": False,
},
},
)
def test_account_settings_redirect_default(self):
"""
Test whether the account settings filter is triggered before the user's
account settings page is rendered.
Expected result:
- AccountSettingsRenderStarted is triggered and executes TestRedirectToDefaultPage
"""
response = self.client.get(self.account_settings_url)

self.assertEqual(response.status_code, status.HTTP_302_FOUND)
self.assertEqual(f"{reverse('dashboard')}", response.url)

@override_settings(OPEN_EDX_FILTERS_CONFIG={})
def test_account_settings_render_without_filter_config(self):
"""
Test whether the course about filter is triggered before the course about
render without affecting its execution flow.
Expected result:
- AccountSettingsRenderStarted executes a noop (empty pipeline). Without any
modification comparing it with the effects of TestAccountSettingsRender.
- The view response is HTTP_200_OK.
"""
response = self.client.get(self.account_settings_url)

self.assertNotContains(response, "This page left intentionally blank. Feel free to add your own content.")
2 changes: 1 addition & 1 deletion requirements/edx/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ openedx-events==0.13.0
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.in
# edx-event-bus-kafka
openedx-filters==1.0.0
openedx-filters==1.2.0
# via
# -r requirements/edx/base.in
# lti-consumer-xblock
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/development.txt
Original file line number Diff line number Diff line change
Expand Up @@ -996,7 +996,7 @@ openedx-events==0.13.0
# -c requirements/edx/../constraints.txt
# -r requirements/edx/testing.txt
# edx-event-bus-kafka
openedx-filters==1.0.0
openedx-filters==1.2.0
# via
# -r requirements/edx/testing.txt
# lti-consumer-xblock
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,7 @@ openedx-events==0.13.0
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
# edx-event-bus-kafka
openedx-filters==1.0.0
openedx-filters==1.2.0
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
Expand Down

0 comments on commit 2d4cbb0

Please sign in to comment.