feat: make it compatible with django settings

This commit is contained in:
Maria Fernanda Magallanes Zubillaga
2022-07-08 01:15:04 -04:00
parent d6a30882d1
commit f2488b10a6
5 changed files with 76 additions and 16 deletions

View File

@@ -15,9 +15,9 @@ Currently, MFE settings are set via command line environment variables or an .en
Decision
********
- A lightweight API will be created that returns the mfe configuration variables from the site configuration.
- A lightweight API will be created that returns the mfe configuration variables from the site configuration or django settings. `PR Discussion about django settings`_
- The API will be enabled or disabled using the setting ``ENABLE_MFE_CONFIG_API``.
- The API will take the mfe configuration in the ``MFE_CONFIG`` keyset in the site configuration (admin > site configuration > your domain).
- The API will take the mfe configuration in the ``MFE_CONFIG`` keyset in the site configuration (admin > site configuration > your domain) or in django settings.
- This API allows to consult the configurations by specific MFE. Making a request like ``api/v1/mfe_config?mfe=mymfe`` will return the configuration defined in ``MFE_CONFIG_MYMFE`` merged with the ``MFE_CONFIG`` configuration.
- The API will have a mechanism to cache the response with ``MFE_CONFIG_API_CACHE_TIMEOUT`` variable.
- The API will live in lms/djangoapps because this is not something Studio needs to serve and it is a lightweight API. `PR Discussion`_
@@ -48,10 +48,10 @@ Consequences
- We have to change all the mfes so that they take the information from the API. `Issue MFE runtime configuration in frontend-wg`_
- Initialize the MFE could have a delay due to the HTTP method.
- `Site configuration is going to be deprecated`_ so later we have to take the configuration from django settings.
- The operator is responsible for configuring the settings in site configuration.
- `Site configuration is going to be deprecated`_ so later we have to clean the code that uses site configuration.
- The operator is responsible for configuring the settings in site configuration or django settings.
- We can have duplicate keys in site configuration (example: we can have a logo definition for each mfe).
- If the request is made from a domain that does not have a site configuration, it returns an empty json.
- If the request is made from a domain that does not have a site configuration, it returns django settings.
Rejected Alternatives
**********************
@@ -68,3 +68,5 @@ References
.. _Site configuration is going to be deprecated: https://github.com/openedx/platform-roadmap/issues/21
.. _Issue MFE runtime configuration in frontend-wg: https://github.com/openedx/frontend-wg/issues/103
.. _PR Discussion about django settings: https://github.com/openedx/edx-platform/pull/30473#discussion_r916263245

View File

@@ -5,6 +5,7 @@ Test the use cases of the views of the mfe api.
from unittest.mock import call, patch
import ddt
from django.conf import settings
from django.test import override_settings
from django.urls import reverse
from rest_framework import status
@@ -26,14 +27,14 @@ class MFEConfigTestCase(APITestCase):
Expected result:
- The get_value method of the configuration_helpers in the views is called once with the
parameters ("MFE_CONFIG", {}).
parameters ("MFE_CONFIG", getattr(settings, "MFE_CONFIG", {})).
- The status of the response of the request is a HTTP_200_OK.
- The json of the response of the request is equal to the mocked configuration.
"""
configuration_helpers_mock.get_value.return_value = {"EXAMPLE_VAR": "value"}
response = self.client.get(self.mfe_config_api_url)
configuration_helpers_mock.get_value.assert_called_once_with("MFE_CONFIG", {})
configuration_helpers_mock.get_value.assert_called_once_with("MFE_CONFIG", getattr(settings, "MFE_CONFIG", {}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json(), {"EXAMPLE_VAR": "value"})
@@ -43,8 +44,9 @@ class MFEConfigTestCase(APITestCase):
Expected result:
- The get_value method of the configuration_helpers in the views is called twice, once with the
parameters ("MFE_CONFIG", {}) and once with the parameters ("MFE_CONFIG_MYMFE", {}).
and one for get_value("MFE_CONFIG_MYMFE", {}).
parameters ("MFE_CONFIG", getattr(settings, "MFE_CONFIG", {})) and once with the parameters
("MFE_CONFIG_MYMFE", getattr(settings, "MFE_CONFIG_MYMFE", {})).
and one for get_value("MFE_CONFIG_MYMFE", getattr(settings, "MFE_CONFIG_MYMFE", {})).
- The json of the response is the merge of both mocked configurations.
"""
configuration_helpers_mock.get_value.side_effect = [{"EXAMPLE_VAR": "value", "OTHER": "other"},
@@ -52,7 +54,8 @@ class MFEConfigTestCase(APITestCase):
response = self.client.get(f"{self.mfe_config_api_url}?mfe=mymfe")
self.assertEqual(response.status_code, status.HTTP_200_OK)
calls = [call("MFE_CONFIG", {}), call("MFE_CONFIG_MYMFE", {})]
calls = [call("MFE_CONFIG", getattr(settings, "MFE_CONFIG", {})),
call("MFE_CONFIG_MYMFE", getattr(settings, "MFE_CONFIG_MYMFE", {}))]
configuration_helpers_mock.get_value.assert_has_calls(calls)
self.assertEqual(response.json(), {"EXAMPLE_VAR": "mymfe_value", "OTHER": "other"})
@@ -82,17 +85,42 @@ class MFEConfigTestCase(APITestCase):
Expected result:
- The get_value method of the configuration_helpers in the views is called twice, once with the
parameters ("MFE_CONFIG", {}) and once with the parameters ("MFE_CONFIG_MYMFE", {}).
parameters ("MFE_CONFIG", getattr(settings, "MFE_CONFIG", {})) and once with the parameters
("MFE_CONFIG_MYMFE", getattr(settings, "MFE_CONFIG_MYMFE", {})).
- The json of the response is the expected_response passed by ddt.data.
"""
configuration_helpers_mock.get_value.side_effect = [mfe_config, mfe_config_mymfe]
response = self.client.get(f"{self.mfe_config_api_url}?mfe=mymfe")
self.assertEqual(response.status_code, status.HTTP_200_OK)
calls = [call("MFE_CONFIG", {}), call("MFE_CONFIG_MYMFE", {})]
calls = [call("MFE_CONFIG", getattr(settings, "MFE_CONFIG", {})),
call("MFE_CONFIG_MYMFE", getattr(settings, "MFE_CONFIG_MYMFE", {}))]
configuration_helpers_mock.get_value.assert_has_calls(calls)
self.assertEqual(response.json(), expected_response)
def test_get_mfe_config_from_django_settings(self):
"""Test that when there is no site configuration, the API takes the django settings.
Expected result:
- The status of the response of the request is a HTTP_200_OK.
- The json response is equal to MFE_CONFIG in lms/envs/test.py"""
response = self.client.get(self.mfe_config_api_url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json(), getattr(settings, "MFE_CONFIG", {}))
def test_get_mfe_config_with_queryparam_from_django_settings(self):
"""Test that when there is no site configuration, the API with queryparam takes the django settings.
Expected result:
- The status of the response of the request is a HTTP_200_OK.
- The json response is equal to MFE_CONFIG merged with MFE_CONFIG_MYMFE in lms/envs/test.py
"""
response = self.client.get(f"{self.mfe_config_api_url}?mfe=mymfe")
self.assertEqual(response.status_code, status.HTTP_200_OK)
expected_response = getattr(settings, "MFE_CONFIG", {})
expected_response.update(getattr(settings, "MFE_CONFIG_MYMFE", {}))
self.assertEqual(response.json(), expected_response)
@patch("lms.djangoapps.mfe_config_api.views.configuration_helpers")
@override_settings(ENABLE_MFE_CONFIG_API=False)
def test_404_get_mfe_config(self, configuration_helpers_mock):

View File

@@ -43,9 +43,10 @@ class MFEConfigView(APIView):
if not settings.ENABLE_MFE_CONFIG_API:
return HttpResponseNotFound()
mfe_config = configuration_helpers.get_value('MFE_CONFIG', {})
mfe_config = configuration_helpers.get_value('MFE_CONFIG', getattr(settings, 'MFE_CONFIG', {}))
if request.query_params.get('mfe'):
mfe = str(request.query_params.get('mfe')).upper()
mfe_config.update(configuration_helpers.get_value(f'MFE_CONFIG_{mfe}', {}))
mfe_config.update(configuration_helpers.get_value(
f'MFE_CONFIG_{mfe}', getattr(settings, f'MFE_CONFIG_{mfe}', {})))
return JsonResponse(mfe_config, status=status.HTTP_200_OK)

View File

@@ -5146,7 +5146,7 @@ PERSONALIZED_RECOMMENDATION_COOKIE_NAME = 'edx-user-personalized-recommendation'
# .. toggle_name: ENABLE_MFE_CONFIG_API
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: Set to True to enable MFE Config REST API. This is disabled by
# .. toggle_description: Set to True to enable MFE Config API. This is disabled by
# default.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2022-05-20
@@ -5155,8 +5155,27 @@ PERSONALIZED_RECOMMENDATION_COOKIE_NAME = 'edx-user-personalized-recommendation'
# .. toggle_tickets: None
ENABLE_MFE_CONFIG_API = False
# .. setting_name: MFE_CONFIG
# .. setting_implementation: DjangoSetting
# .. setting_default: {}
# .. setting_description: Is a configuration that will be exposed by the MFE Config API to be consumed by the mfes
# Example: {
# "BASE_URL": "https://name_of_mfe.example.com",
# "LANGUAGE_PREFERENCE_COOKIE_NAME": "example-language-preference",
# "CREDENTIALS_BASE_URL": "https://credentials.example.com",
# "DISCOVERY_API_BASE_URL": "https://discovery.example.com",
# "LMS_BASE_URL": "https://courses.example.com",
# "LOGIN_URL": "https://courses.example.com/login",
# "LOGOUT_URL": "https://courses.example.com/logout",
# "STUDIO_BASE_URL": "https://studio.example.com",
# "LOGO_URL": "https://courses.example.com/logo.png"
# }
# .. setting_use_cases: open_edx
# .. setting_creation_date: 2022-07-08
MFE_CONFIG = {}
# .. setting_name: MFE_CONFIG_API_CACHE_TIMEOUT
# .. setting_default: 60*5
# .. setting_description: The MFE_CONFIG site configuration will be cached during the
# .. setting_description: The MFE Config API response will be cached during the
# specified time
MFE_CONFIG_API_CACHE_TIMEOUT = 60 * 5

View File

@@ -650,3 +650,13 @@ COURSE_LIVE_GLOBAL_CREDENTIALS["BIG_BLUE_BUTTON"] = {
################## MFE API ####################
ENABLE_MFE_CONFIG_API = True
MFE_CONFIG = {
"BASE_URL": "https://name_of_mfe.example.com",
"LANGUAGE_PREFERENCE_COOKIE_NAME": "example-language-preference",
"LOGO_URL": "https://courses.example.com/logo.png"
}
MFE_CONFIG_MYMFE = {
"LANGUAGE_PREFERENCE_COOKIE_NAME": "mymfe-language-preference",
"LOGO_URL": "https://courses.example.com/mymfe-logo.png"
}