Merge pull request #20368 from edx/arch/account-settings-toggle
Account Settings: Toggle for Micro-frontend Redirect
This commit is contained in:
@@ -3486,14 +3486,9 @@ USERNAME_REPLACEMENT_WORKER = "REPLACE WITH VALID USERNAME"
|
|||||||
# modify lms/envs/private.py to give it a non-null value
|
# modify lms/envs/private.py to give it a non-null value
|
||||||
WRITABLE_GRADEBOOK_URL = None
|
WRITABLE_GRADEBOOK_URL = None
|
||||||
|
|
||||||
# TODO (DEPR-17)
|
PROFILE_MICROFRONTEND_URL = "http://profile-mfe/abc/"
|
||||||
# This URL value is needed to redirect the old profile page to a new
|
ORDER_HISTORY_MICROFRONTEND_URL = "http://order-history-mfe/"
|
||||||
# micro-frontend based implementation. Once the old implementation is
|
ACCOUNT_MICROFRONTEND_URL = "http://account-mfe/"
|
||||||
# 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/"
|
|
||||||
|
|
||||||
############### Settings for django-fernet-fields ##################
|
############### Settings for django-fernet-fields ##################
|
||||||
FERNET_KEYS = [
|
FERNET_KEYS = [
|
||||||
|
|||||||
@@ -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)
|
WRITABLE_GRADEBOOK_URL = ENV_TOKENS.get('WRITABLE_GRADEBOOK_URL', WRITABLE_GRADEBOOK_URL)
|
||||||
PROFILE_MICROFRONTEND_URL = ENV_TOKENS.get('PROFILE_MICROFRONTEND_URL', PROFILE_MICROFRONTEND_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)
|
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 ###############
|
############### Settings for edx-rbac ###############
|
||||||
SYSTEM_WIDE_ROLE_CLASSES = ENV_TOKENS.get('SYSTEM_WIDE_ROLE_CLASSES') or SYSTEM_WIDE_ROLE_CLASSES
|
SYSTEM_WIDE_ROLE_CLASSES = ENV_TOKENS.get('SYSTEM_WIDE_ROLE_CLASSES') or SYSTEM_WIDE_ROLE_CLASSES
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import logging
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.shortcuts import redirect
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.views.decorators.http import require_http_methods
|
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.lang_pref.api import all_languages, released_languages
|
||||||
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
|
from openedx.core.djangoapps.programs.models import ProgramsApiConfig
|
||||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
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.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.edx_api_utils import get_edx_api_data
|
||||||
from openedx.core.lib.time_zone_utils import TIME_ZONE_CHOICES
|
from openedx.core.lib.time_zone_utils import TIME_ZONE_CHOICES
|
||||||
@@ -52,6 +56,9 @@ def account_settings(request):
|
|||||||
GET /account/settings
|
GET /account/settings
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if should_redirect_to_account_microfrontend():
|
||||||
|
return redirect(settings.ACCOUNT_MICROFRONTEND_URL)
|
||||||
|
|
||||||
context = account_settings_context(request)
|
context = account_settings_context(request)
|
||||||
return render_to_response('student_account/account_settings.html', context)
|
return render_to_response('student_account/account_settings.html', context)
|
||||||
|
|
||||||
|
|||||||
@@ -13,19 +13,22 @@ from edx_rest_api_client import exceptions
|
|||||||
from lms.djangoapps.commerce.models import CommerceConfiguration
|
from lms.djangoapps.commerce.models import CommerceConfiguration
|
||||||
from lms.djangoapps.commerce.tests import factories
|
from lms.djangoapps.commerce.tests import factories
|
||||||
from lms.djangoapps.commerce.tests.mocks import mock_get_orders
|
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.dark_lang.models import DarkLangConfig
|
||||||
from openedx.core.djangoapps.lang_pref.tests.test_api import EN, LT_LT
|
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.programs.tests.mixins import ProgramsApiConfigMixin
|
||||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
|
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.djangoapps.user_api.tests.factories import UserPreferenceFactory
|
||||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
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.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 student.tests.factories import UserFactory
|
||||||
from third_party_auth.tests.testutil import ThirdPartyAuthTestMixin
|
from third_party_auth.tests.testutil import ThirdPartyAuthTestMixin
|
||||||
|
|
||||||
|
|
||||||
@skip_unless_lms
|
@skip_unless_lms
|
||||||
class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConfigMixin):
|
class AccountSettingsViewTest(ThirdPartyAuthTestMixin, SiteMixin, ProgramsApiConfigMixin, TestCase):
|
||||||
""" Tests for the account settings view. """
|
""" Tests for the account settings view. """
|
||||||
|
|
||||||
USERNAME = 'student'
|
USERNAME = 'student'
|
||||||
@@ -152,7 +155,7 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf
|
|||||||
|
|
||||||
def test_view(self):
|
def test_view(self):
|
||||||
"""
|
"""
|
||||||
Test that all fields are visible
|
Test that all fields are visible
|
||||||
"""
|
"""
|
||||||
view_path = reverse('account_settings')
|
view_path = reverse('account_settings')
|
||||||
response = self.client.get(path=view_path)
|
response = self.client.get(path=view_path)
|
||||||
@@ -243,3 +246,22 @@ class AccountSettingsViewTest(ThirdPartyAuthTestMixin, TestCase, ProgramsApiConf
|
|||||||
order_detail = get_user_orders(self.user)
|
order_detail = get_user_orders(self.user)
|
||||||
|
|
||||||
self.assertEqual(len(order_detail), 1)
|
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)
|
||||||
|
|||||||
@@ -13,12 +13,35 @@ from openedx.core.djangoapps.waffle_utils import WaffleFlag
|
|||||||
# .. toggle_use_cases: incremental_release, open_edx
|
# .. toggle_use_cases: incremental_release, open_edx
|
||||||
# .. toggle_creation_date: 2019-04-11
|
# .. toggle_creation_date: 2019-04-11
|
||||||
# .. toggle_expiration_date: 2020-12-31
|
# .. 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_tickets: DEPR-17
|
||||||
# .. toggle_status: supported
|
# .. toggle_status: supported
|
||||||
REDIRECT_TO_ORDER_HISTORY_MICROFRONTEND = WaffleFlag('order_history', 'redirect_to_microfrontend')
|
REDIRECT_TO_ORDER_HISTORY_MICROFRONTEND = WaffleFlag('order_history', 'redirect_to_microfrontend')
|
||||||
|
|
||||||
|
|
||||||
def should_redirect_to_order_history_microfrontend():
|
def should_redirect_to_order_history_microfrontend():
|
||||||
should_redirect_for_current_site = configuration_helpers.get_value('ENABLE_ORDER_HISTORY_MICROFRONTEND')
|
return (
|
||||||
return REDIRECT_TO_ORDER_HISTORY_MICROFRONTEND.is_enabled() and should_redirect_for_current_site
|
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()
|
||||||
|
)
|
||||||
|
|||||||
@@ -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')
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from django.conf import settings
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory
|
||||||
from opaque_keys.edx.locator import CourseLocator
|
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.features.learner_profile.views.learner_profile import learner_profile_context
|
||||||
from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
|
from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
|
||||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
|
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)
|
self.assertIn(attribute, response.content)
|
||||||
|
|
||||||
def test_redirect_view(self):
|
def test_redirect_view(self):
|
||||||
profile_url = "http://profile-spa/abc/"
|
with override_waffle_flag(REDIRECT_TO_PROFILE_MICROFRONTEND, active=True):
|
||||||
with override_settings(PROFILE_MICROFRONTEND_URL=profile_url):
|
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
|
# Test with waffle flag active and site setting disabled, does not redirect
|
||||||
response = self.client.get(path=profile_path)
|
response = self.client.get(path=profile_path)
|
||||||
for attribute in self.CONTEXT_DATA:
|
for attribute in self.CONTEXT_DATA:
|
||||||
self.assertIn(attribute, response.content)
|
self.assertIn(attribute, response.content)
|
||||||
|
|
||||||
# Test with waffle flag active, site setting enabled
|
# Test with waffle flag active and site setting enabled, redirects to microfrontend
|
||||||
site_domain = 'othersite.example.com'
|
site_domain = 'othersite.example.com'
|
||||||
self.set_up_site(site_domain, {
|
self.set_up_site(site_domain, {
|
||||||
'SITE_NAME': site_domain,
|
'SITE_NAME': site_domain,
|
||||||
'ENABLE_PROFILE_MICROFRONTEND': True
|
'ENABLE_PROFILE_MICROFRONTEND': True
|
||||||
})
|
})
|
||||||
self.client.login(username=self.USERNAME, password=self.PASSWORD)
|
self.client.login(username=self.USERNAME, password=self.PASSWORD)
|
||||||
response = self.client.get(path=profile_path)
|
response = self.client.get(path=profile_path)
|
||||||
self.assertRedirects(response, profile_url + self.USERNAME, target_status_code=404)
|
profile_url = settings.PROFILE_MICROFRONTEND_URL
|
||||||
|
self.assertRedirects(response, profile_url + self.USERNAME, fetch_redirect_response=False)
|
||||||
|
|
||||||
def test_records_link(self):
|
def test_records_link(self):
|
||||||
profile_path = reverse('learner_profile', kwargs={'username': self.USERNAME})
|
profile_path = reverse('learner_profile', kwargs={'username': self.USERNAME})
|
||||||
|
|||||||
31
openedx/features/learner_profile/toggles.py
Normal file
31
openedx/features/learner_profile/toggles.py
Normal file
@@ -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()
|
||||||
|
)
|
||||||
@@ -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.errors import UserNotAuthorized, UserNotFound
|
||||||
from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences
|
from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences
|
||||||
from openedx.core.djangolib.markup import HTML, Text
|
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 openedx.features.journals.api import journals_enabled
|
||||||
from student.models import User
|
from student.models import User
|
||||||
|
|
||||||
from .. import REDIRECT_TO_PROFILE_MICROFRONTEND
|
|
||||||
|
|
||||||
from learner_achievements import LearnerAchievementsFragmentView
|
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@require_http_methods(['GET'])
|
@require_http_methods(['GET'])
|
||||||
@@ -46,8 +44,7 @@ def learner_profile(request, username):
|
|||||||
Example usage:
|
Example usage:
|
||||||
GET /account/profile
|
GET /account/profile
|
||||||
"""
|
"""
|
||||||
is_profile_mfe_enabled_for_site = configuration_helpers.get_value('ENABLE_PROFILE_MICROFRONTEND')
|
if should_redirect_to_profile_microfrontend():
|
||||||
if is_profile_mfe_enabled_for_site and REDIRECT_TO_PROFILE_MICROFRONTEND.is_enabled():
|
|
||||||
profile_microfrontend_url = "{}{}".format(settings.PROFILE_MICROFRONTEND_URL, username)
|
profile_microfrontend_url = "{}{}".format(settings.PROFILE_MICROFRONTEND_URL, username)
|
||||||
return redirect(profile_microfrontend_url)
|
return redirect(profile_microfrontend_url)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user