diff --git a/lms/envs/common.py b/lms/envs/common.py index 4231c32105..555999d284 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -3486,14 +3486,9 @@ USERNAME_REPLACEMENT_WORKER = "REPLACE WITH VALID USERNAME" # modify lms/envs/private.py to give it a non-null value WRITABLE_GRADEBOOK_URL = None -# TODO (DEPR-17) -# This URL value is needed to redirect the old profile page to a new -# micro-frontend based implementation. Once the old implementation is -# completely removed and this redirect is no longer needed, we can remove this. -PROFILE_MICROFRONTEND_URL = "http://some.profile.spa/u/" - -# URL configuration for new microfrontends. -ORDER_HISTORY_MICROFRONTEND_URL = "http://some.order_history.spa/" +PROFILE_MICROFRONTEND_URL = "http://profile-mfe/abc/" +ORDER_HISTORY_MICROFRONTEND_URL = "http://order-history-mfe/" +ACCOUNT_MICROFRONTEND_URL = "http://account-mfe/" ############### Settings for django-fernet-fields ################## FERNET_KEYS = [ diff --git a/lms/envs/production.py b/lms/envs/production.py index 771e411963..00919da01d 100644 --- a/lms/envs/production.py +++ b/lms/envs/production.py @@ -1104,6 +1104,7 @@ COURSE_ENROLLMENT_MODES = ENV_TOKENS.get('COURSE_ENROLLMENT_MODES', COURSE_ENROL WRITABLE_GRADEBOOK_URL = ENV_TOKENS.get('WRITABLE_GRADEBOOK_URL', WRITABLE_GRADEBOOK_URL) PROFILE_MICROFRONTEND_URL = ENV_TOKENS.get('PROFILE_MICROFRONTEND_URL', PROFILE_MICROFRONTEND_URL) ORDER_HISTORY_MICROFRONTEND_URL = ENV_TOKENS.get('ORDER_HISTORY_MICROFRONTEND_URL', ORDER_HISTORY_MICROFRONTEND_URL) +ACCOUNT_MICROFRONTEND_URL = ENV_TOKENS.get('ACCOUNT_MICROFRONTEND_URL', ACCOUNT_MICROFRONTEND_URL) ############### Settings for edx-rbac ############### SYSTEM_WIDE_ROLE_CLASSES = ENV_TOKENS.get('SYSTEM_WIDE_ROLE_CLASSES') or SYSTEM_WIDE_ROLE_CLASSES diff --git a/openedx/core/djangoapps/user_api/accounts/settings_views.py b/openedx/core/djangoapps/user_api/accounts/settings_views.py index 0dd8672572..6bfae46d69 100644 --- a/openedx/core/djangoapps/user_api/accounts/settings_views.py +++ b/openedx/core/djangoapps/user_api/accounts/settings_views.py @@ -5,6 +5,7 @@ import logging from django.conf import settings from django.contrib import messages from django.contrib.auth.decorators import login_required +from django.shortcuts import redirect from django.utils.translation import ugettext as _ from django.urls import reverse from django.views.decorators.http import require_http_methods @@ -19,7 +20,10 @@ from openedx.core.djangoapps.dark_lang.models import DarkLangConfig from openedx.core.djangoapps.lang_pref.api import all_languages, released_languages from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from openedx.core.djangoapps.user_api.accounts.toggles import should_redirect_to_order_history_microfrontend +from openedx.core.djangoapps.user_api.accounts.toggles import ( + should_redirect_to_order_history_microfrontend, + should_redirect_to_account_microfrontend, +) from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences from openedx.core.lib.edx_api_utils import get_edx_api_data from openedx.core.lib.time_zone_utils import TIME_ZONE_CHOICES @@ -52,6 +56,9 @@ def account_settings(request): GET /account/settings """ + if should_redirect_to_account_microfrontend(): + return redirect(settings.ACCOUNT_MICROFRONTEND_URL) + context = account_settings_context(request) return render_to_response('student_account/account_settings.html', context) diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_settings_views.py b/openedx/core/djangoapps/user_api/accounts/tests/test_settings_views.py index 52259087fe..ce10563a56 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_settings_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_settings_views.py @@ -13,19 +13,22 @@ from edx_rest_api_client import exceptions from lms.djangoapps.commerce.models import CommerceConfiguration from lms.djangoapps.commerce.tests import factories from lms.djangoapps.commerce.tests.mocks import mock_get_orders +from openedx.core.djangoapps.user_api.accounts.toggles import REDIRECT_TO_ACCOUNT_MICROFRONTEND from openedx.core.djangoapps.dark_lang.models import DarkLangConfig from openedx.core.djangoapps.lang_pref.tests.test_api import EN, LT_LT from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory +from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin from openedx.core.djangoapps.user_api.tests.factories import UserPreferenceFactory from openedx.core.djangolib.testing.utils import skip_unless_lms from openedx.core.djangoapps.user_api.accounts.settings_views import account_settings_context, get_user_orders +from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag from student.tests.factories import UserFactory from third_party_auth.tests.testutil import ThirdPartyAuthTestMixin @skip_unless_lms -class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConfigMixin): +class AccountSettingsViewTest(ThirdPartyAuthTestMixin, SiteMixin, ProgramsApiConfigMixin, TestCase): """ Tests for the account settings view. """ USERNAME = 'student' @@ -152,7 +155,7 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf def test_view(self): """ - Test that all fields are visible + Test that all fields are visible """ view_path = reverse('account_settings') response = self.client.get(path=view_path) @@ -243,3 +246,22 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf order_detail = get_user_orders(self.user) self.assertEqual(len(order_detail), 1) + + def test_redirect_view(self): + with override_waffle_flag(REDIRECT_TO_ACCOUNT_MICROFRONTEND, active=True): + old_url_path = reverse('account_settings') + + # Test with waffle flag active and site setting disabled, does not redirect + response = self.client.get(path=old_url_path) + for attribute in self.FIELDS: + self.assertIn(attribute, response.content) + + # Test with waffle flag active and site setting enabled, redirects to microfrontend + site_domain = 'othersite.example.com' + self.set_up_site(site_domain, { + 'SITE_NAME': site_domain, + 'ENABLE_ACCOUNT_MICROFRONTEND': True + }) + self.client.login(username=self.USERNAME, password=self.PASSWORD) + response = self.client.get(path=old_url_path) + self.assertRedirects(response, settings.ACCOUNT_MICROFRONTEND_URL, fetch_redirect_response=False) diff --git a/openedx/core/djangoapps/user_api/accounts/toggles.py b/openedx/core/djangoapps/user_api/accounts/toggles.py index 4bae68873a..32f7b453b5 100644 --- a/openedx/core/djangoapps/user_api/accounts/toggles.py +++ b/openedx/core/djangoapps/user_api/accounts/toggles.py @@ -13,12 +13,35 @@ from openedx.core.djangoapps.waffle_utils import WaffleFlag # .. toggle_use_cases: incremental_release, open_edx # .. toggle_creation_date: 2019-04-11 # .. toggle_expiration_date: 2020-12-31 -# .. toggle_warnings: Remember to also set ORDER_HISTORY_MICROFRONTEND_URL before this toggle is enabled. +# .. toggle_warnings: Also set settings.ORDER_HISTORY_MICROFRONTEND_URL and site's ENABLE_ORDER_HISTORY_MICROFRONTEND. # .. toggle_tickets: DEPR-17 # .. toggle_status: supported REDIRECT_TO_ORDER_HISTORY_MICROFRONTEND = WaffleFlag('order_history', 'redirect_to_microfrontend') def should_redirect_to_order_history_microfrontend(): - should_redirect_for_current_site = configuration_helpers.get_value('ENABLE_ORDER_HISTORY_MICROFRONTEND') - return REDIRECT_TO_ORDER_HISTORY_MICROFRONTEND.is_enabled() and should_redirect_for_current_site + return ( + configuration_helpers.get_value('ENABLE_ORDER_HISTORY_MICROFRONTEND') and + REDIRECT_TO_ORDER_HISTORY_MICROFRONTEND.is_enabled() + ) + + +# .. toggle_name: REDIRECT_TO_ACCOUNT_MICROFRONTEND +# .. toggle_type: waffle_flag +# .. toggle_default: False +# .. toggle_description: Supports staged rollout of a new micro-frontend-based implementation of the account page. +# .. toggle_category: micro-frontend +# .. toggle_use_cases: incremental_release, open_edx +# .. toggle_creation_date: 2019-04-30 +# .. toggle_expiration_date: 2020-12-31 +# .. toggle_warnings: Also set settings.ACCOUNT_MICROFRONTEND_URL and site's ENABLE_ACCOUNT_MICROFRONTEND. +# .. toggle_tickets: DEPR-17 +# .. toggle_status: supported +REDIRECT_TO_ACCOUNT_MICROFRONTEND = WaffleFlag('account', 'redirect_to_microfrontend') + + +def should_redirect_to_account_microfrontend(): + return ( + configuration_helpers.get_value('ENABLE_ACCOUNT_MICROFRONTEND') and + REDIRECT_TO_ACCOUNT_MICROFRONTEND.is_enabled() + ) diff --git a/openedx/features/learner_profile/__init__.py b/openedx/features/learner_profile/__init__.py index cfda421ce5..e69de29bb2 100644 --- a/openedx/features/learner_profile/__init__.py +++ b/openedx/features/learner_profile/__init__.py @@ -1,23 +0,0 @@ -""" -Learner profile settings and helper methods. -""" - -from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace - - -# Namespace for learner profile waffle flags. -WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='learner_profile') - -# Waffle flag to redirect to another learner profile experience. -# .. toggle_name: REDIRECT_TO_PROFILE_MICROFRONTEND -# .. toggle_type: waffle_flag -# .. toggle_default: False -# .. toggle_description: Supports staged rollout of a new micro-frontend-based implementation of the profile page. -# .. toggle_category: micro-frontend -# .. toggle_use_cases: incremental_release, open_edx -# .. toggle_creation_date: 2019-02-19 -# .. toggle_expiration_date: 2020-12-31 -# .. toggle_warnings: Remember to also set PROFILE_MICROFRONTEND_URL before this toggle is enabled. -# .. toggle_tickets: DEPR-17 -# .. toggle_status: supported -REDIRECT_TO_PROFILE_MICROFRONTEND = WaffleFlag(WAFFLE_FLAG_NAMESPACE, 'redirect_to_microfrontend') diff --git a/openedx/features/learner_profile/tests/views/test_learner_profile.py b/openedx/features/learner_profile/tests/views/test_learner_profile.py index 7f10ff2009..6be63b82e6 100644 --- a/openedx/features/learner_profile/tests/views/test_learner_profile.py +++ b/openedx/features/learner_profile/tests/views/test_learner_profile.py @@ -15,7 +15,7 @@ from django.conf import settings from django.urls import reverse from django.test.client import RequestFactory from opaque_keys.edx.locator import CourseLocator -from openedx.features.learner_profile import REDIRECT_TO_PROFILE_MICROFRONTEND +from openedx.features.learner_profile.toggles import REDIRECT_TO_PROFILE_MICROFRONTEND from openedx.features.learner_profile.views.learner_profile import learner_profile_context from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag @@ -117,25 +117,24 @@ class LearnerProfileViewTest(SiteMixin, UrlResetMixin, ModuleStoreTestCase): self.assertIn(attribute, response.content) def test_redirect_view(self): - profile_url = "http://profile-spa/abc/" - with override_settings(PROFILE_MICROFRONTEND_URL=profile_url): - with override_waffle_flag(REDIRECT_TO_PROFILE_MICROFRONTEND, active=True): - profile_path = reverse('learner_profile', kwargs={'username': self.USERNAME}) + with override_waffle_flag(REDIRECT_TO_PROFILE_MICROFRONTEND, active=True): + profile_path = reverse('learner_profile', kwargs={'username': self.USERNAME}) - # Test with waffle flag active, site setting disabled - response = self.client.get(path=profile_path) - for attribute in self.CONTEXT_DATA: - self.assertIn(attribute, response.content) + # Test with waffle flag active and site setting disabled, does not redirect + response = self.client.get(path=profile_path) + for attribute in self.CONTEXT_DATA: + self.assertIn(attribute, response.content) - # Test with waffle flag active, site setting enabled - site_domain = 'othersite.example.com' - self.set_up_site(site_domain, { - 'SITE_NAME': site_domain, - 'ENABLE_PROFILE_MICROFRONTEND': True - }) - self.client.login(username=self.USERNAME, password=self.PASSWORD) - response = self.client.get(path=profile_path) - self.assertRedirects(response, profile_url + self.USERNAME, target_status_code=404) + # Test with waffle flag active and site setting enabled, redirects to microfrontend + site_domain = 'othersite.example.com' + self.set_up_site(site_domain, { + 'SITE_NAME': site_domain, + 'ENABLE_PROFILE_MICROFRONTEND': True + }) + self.client.login(username=self.USERNAME, password=self.PASSWORD) + response = self.client.get(path=profile_path) + profile_url = settings.PROFILE_MICROFRONTEND_URL + self.assertRedirects(response, profile_url + self.USERNAME, fetch_redirect_response=False) def test_records_link(self): profile_path = reverse('learner_profile', kwargs={'username': self.USERNAME}) diff --git a/openedx/features/learner_profile/toggles.py b/openedx/features/learner_profile/toggles.py new file mode 100644 index 0000000000..b16e65bfb8 --- /dev/null +++ b/openedx/features/learner_profile/toggles.py @@ -0,0 +1,31 @@ +""" +Toggles for Learner Profile page. +""" + +from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers +from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace + + +# Namespace for learner profile waffle flags. +WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='learner_profile') + +# Waffle flag to redirect to another learner profile experience. +# .. toggle_name: REDIRECT_TO_PROFILE_MICROFRONTEND +# .. toggle_type: waffle_flag +# .. toggle_default: False +# .. toggle_description: Supports staged rollout of a new micro-frontend-based implementation of the profile page. +# .. toggle_category: micro-frontend +# .. toggle_use_cases: incremental_release, open_edx +# .. toggle_creation_date: 2019-02-19 +# .. toggle_expiration_date: 2020-12-31 +# .. toggle_warnings: Also set settings.PROFILE_MICROFRONTEND_URL and site's ENABLE_PROFILE_MICROFRONTEND. +# .. toggle_tickets: DEPR-17 +# .. toggle_status: supported +REDIRECT_TO_PROFILE_MICROFRONTEND = WaffleFlag(WAFFLE_FLAG_NAMESPACE, 'redirect_to_microfrontend') + + +def should_redirect_to_profile_microfrontend(): + return ( + configuration_helpers.get_value('ENABLE_PROFILE_MICROFRONTEND') and + REDIRECT_TO_PROFILE_MICROFRONTEND.is_enabled() + ) diff --git a/openedx/features/learner_profile/views/learner_profile.py b/openedx/features/learner_profile/views/learner_profile.py index 206583e940..d1f2d2c6bd 100644 --- a/openedx/features/learner_profile/views/learner_profile.py +++ b/openedx/features/learner_profile/views/learner_profile.py @@ -19,13 +19,11 @@ from openedx.core.djangoapps.user_api.accounts.api import get_account_settings from openedx.core.djangoapps.user_api.errors import UserNotAuthorized, UserNotFound from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences from openedx.core.djangolib.markup import HTML, Text +from openedx.features.learner_profile.toggles import should_redirect_to_profile_microfrontend +from openedx.features.learner_profile.views.learner_achievements import LearnerAchievementsFragmentView from openedx.features.journals.api import journals_enabled from student.models import User -from .. import REDIRECT_TO_PROFILE_MICROFRONTEND - -from learner_achievements import LearnerAchievementsFragmentView - @login_required @require_http_methods(['GET']) @@ -46,8 +44,7 @@ def learner_profile(request, username): Example usage: GET /account/profile """ - is_profile_mfe_enabled_for_site = configuration_helpers.get_value('ENABLE_PROFILE_MICROFRONTEND') - if is_profile_mfe_enabled_for_site and REDIRECT_TO_PROFILE_MICROFRONTEND.is_enabled(): + if should_redirect_to_profile_microfrontend(): profile_microfrontend_url = "{}{}".format(settings.PROFILE_MICROFRONTEND_URL, username) return redirect(profile_microfrontend_url)