Skip to content

Commit

Permalink
feat: add mfe_api v1
Browse files Browse the repository at this point in the history
This PR adds MFE API. This is part of the work that is being done to obtain the MFE Runtime Configurations and that has been discussed in the BTR WG.

Discussion: https://discuss.openedx.org/t/how-to-use-microfrontend-in-a-multitenant-instance/6936/14?u=mafermazu
MFE Runtime configuration - eduNEXT: https://docs.google.com/document/d/1-FHIQmyeQZu3311x8eYUNMru4JX7Yb3UlqjmJxvM8do/edit?usp=sharing

feat: add lms setting to set mfe config cache (#262)

Co-authored-by: María Fernanda Magallanes Z <[email protected]>

feat: make mfe config api disabled by default (#263)

* feat: make mfe config api disabled by default

* fix: simple is better than complex

test: add mfe config tests (#264)

* test: add mfe config tests

* test: fix it and simplify it

* test: correct pylint issues

fix: correct pep 8 violations

fix: add mfe api unit test in github workflow

fix: correct unit tests

refactor: move mfe api to lms

fix: try mfe api urls without regex

fix: add app_namespace in lms urls

fix: try url without conditional

Revert "fix: try url without conditional"

This reverts commit 694aab546134b4bd9ad2642e24927b42cac24459.

fix: set enable_mfe_config_api feature to true in the tests

test: try to add failed test case

Revert "test: try to add failed test case"

This reverts commit cee6bf656ab1b96492b0b6199ddff32a6d6a65bd.

docs: improve explanation and documentation

fix: ensure the response is a json object

refactor: be consistent with the variable names

fix: allow overriding mfe api config cache timeout in production

fix: handle 404 response in view

refactor: use a guard instead if-else

feat: add the possibility to show mfe specific config
  • Loading branch information
MaferMazu committed Jul 8, 2022
1 parent 915ddb9 commit 7f5eb29
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/pylint-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- module-name: lms-1
path: "lms/djangoapps/badges/ lms/djangoapps/branding/ lms/djangoapps/bulk_email/ lms/djangoapps/bulk_enroll/ lms/djangoapps/bulk_user_retirement/ lms/djangoapps/ccx/ lms/djangoapps/certificates/ lms/djangoapps/commerce/ lms/djangoapps/course_api/ lms/djangoapps/course_blocks/ lms/djangoapps/course_home_api/ lms/djangoapps/course_wiki/ lms/djangoapps/coursewarehistoryextended/ lms/djangoapps/debug/ lms/djangoapps/courseware/ lms/djangoapps/course_goals/ lms/djangoapps/rss_proxy/ lms/djangoapps/save_for_later/"
- module-name: lms-2
path: "lms/djangoapps/gating/ lms/djangoapps/grades/ lms/djangoapps/instructor/ lms/djangoapps/instructor_analytics/ lms/djangoapps/discussion/ lms/djangoapps/edxnotes/ lms/djangoapps/email_marketing/ lms/djangoapps/experiments/ lms/djangoapps/instructor_task/ lms/djangoapps/learner_dashboard/ lms/djangoapps/lms_initialization/ lms/djangoapps/lms_xblock/ lms/djangoapps/lti_provider/ lms/djangoapps/mailing/ lms/djangoapps/mobile_api/ lms/djangoapps/monitoring/ lms/djangoapps/ora_staff_grader/ lms/djangoapps/program_enrollments/ lms/djangoapps/rss_proxy lms/djangoapps/static_template_view/ lms/djangoapps/staticbook/ lms/djangoapps/support/ lms/djangoapps/survey/ lms/djangoapps/teams/ lms/djangoapps/tests/ lms/djangoapps/user_tours/ lms/djangoapps/verify_student/ lms/envs/ lms/lib/ lms/tests.py"
path: "lms/djangoapps/gating/ lms/djangoapps/grades/ lms/djangoapps/instructor/ lms/djangoapps/instructor_analytics/ lms/djangoapps/discussion/ lms/djangoapps/edxnotes/ lms/djangoapps/email_marketing/ lms/djangoapps/experiments/ lms/djangoapps/instructor_task/ lms/djangoapps/learner_dashboard/ lms/djangoapps/lms_initialization/ lms/djangoapps/lms_xblock/ lms/djangoapps/lti_provider/ lms/djangoapps/mailing/ lms/djangoapps/mobile_api/ lms/djangoapps/monitoring/ lms/djangoapps/ora_staff_grader/ lms/djangoapps/program_enrollments/ lms/djangoapps/rss_proxy lms/djangoapps/static_template_view/ lms/djangoapps/staticbook/ lms/djangoapps/support/ lms/djangoapps/survey/ lms/djangoapps/teams/ lms/djangoapps/tests/ lms/djangoapps/user_tours/ lms/djangoapps/verify_student/ lms/djangoapps/mfe_api/ lms/envs/ lms/lib/ lms/tests.py"
- module-name: openedx-1
path: "openedx/core/types/ openedx/core/djangoapps/ace_common/ openedx/core/djangoapps/agreements/ openedx/core/djangoapps/api_admin/ openedx/core/djangoapps/auth_exchange/ openedx/core/djangoapps/bookmarks/ openedx/core/djangoapps/cache_toolbox/ openedx/core/djangoapps/catalog/ openedx/core/djangoapps/ccxcon/ openedx/core/djangoapps/commerce/ openedx/core/djangoapps/common_initialization/ openedx/core/djangoapps/common_views/ openedx/core/djangoapps/config_model_utils/ openedx/core/djangoapps/content/ openedx/core/djangoapps/content_libraries/ openedx/core/djangoapps/contentserver/ openedx/core/djangoapps/cookie_metadata/ openedx/core/djangoapps/cors_csrf/ openedx/core/djangoapps/course_apps/ openedx/core/djangoapps/course_date_signals/ openedx/core/djangoapps/course_groups/ openedx/core/djangoapps/courseware_api/ openedx/core/djangoapps/crawlers/ openedx/core/djangoapps/credentials/ openedx/core/djangoapps/credit/ openedx/core/djangoapps/dark_lang/ openedx/core/djangoapps/debug/ openedx/core/djangoapps/demographics/ openedx/core/djangoapps/discussions/ openedx/core/djangoapps/django_comment_common/ openedx/core/djangoapps/embargo/ openedx/core/djangoapps/enrollments/ openedx/core/djangoapps/external_user_ids/ openedx/core/djangoapps/zendesk_proxy/ openedx/core/djangolib/ openedx/core/lib/ openedx/core/tests/ openedx/core/djangoapps/course_live/"
- module-name: openedx-2
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/unit-test-shards.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"lms/djangoapps/tests/",
"lms/djangoapps/user_tours/",
"lms/djangoapps/verify_student/",
"lms/djangoapps/mfe_api/",
"lms/envs/",
"lms/lib/",
"lms/tests.py"
Expand Down
Empty file.
Empty file.
43 changes: 43 additions & 0 deletions lms/djangoapps/mfe_api/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
Test the use cases of the views of the mfe api.
"""

from unittest.mock import patch

from django.conf import settings
from django.urls import reverse
from rest_framework import status

from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.lib.api.test_utils import ApiTestCase


class MFEConfigTestCase(ApiTestCase):
"""
Test the use case that exposes the site configuration with the mfe api.
"""
def setUp(self):
self.mfe_config_api_url = reverse('mfe_api:config')
return super().setUp()

def test_get_mfe_config(self):
"""Test the get mfe config from site configuration with the mfe api.
Expected result:
- Inside self.get_json pass the response is a json and the status is 200 asserts.
- The configuration obtained by the api is equal to its site configuration in the
MFE_CONFIG key.
"""
mfe_config = configuration_helpers.get_value('MFE_CONFIG', {})
response_json = self.get_json(self.mfe_config_api_url)
assert response_json == mfe_config

@patch.dict(settings.FEATURES, {'ENABLE_MFE_API': False})
def test_404_get_mfe_config(self):
"""Test the 404 not found response from get mfe config.
Expected result:
- Response status code equal to 404
"""
response = self.client.get(self.mfe_config_api_url)
assert response.status_code == status.HTTP_404_NOT_FOUND
10 changes: 10 additions & 0 deletions lms/djangoapps/mfe_api/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
""" URLs configuration for the mfe api."""

from django.urls import path

from lms.djangoapps.mfe_api.views import MFEConfigView

app_name = 'mfe_api'
urlpatterns = [
path('v1/config', MFEConfigView.as_view(), name='config'),
]
42 changes: 42 additions & 0 deletions lms/djangoapps/mfe_api/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
MFE API Views for useful information related to mfes.
"""

from django.conf import settings
from django.http import JsonResponse
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from rest_framework import status
from rest_framework.views import APIView

from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers


class MFEConfigView(APIView):
"""
Provides an API endpoint to get the MFE_CONFIG from site configuration.
"""

@method_decorator(cache_page(settings.MFE_API_CONFIG_CACHE_TIMEOUT))
def get(self, request):
"""
GET /api/mfe/v1/config
**GET Response Values**
```
{
"LOGO_URL": "https://example.com/logo.png",
}
```
"""

if not settings.FEATURES.get('ENABLE_MFE_API'):
msg = 'MFE API not found. Try setting FEATURES["ENABLE_MFE_API"] to true.'
return JsonResponse({'message': msg}, status=status.HTTP_404_NOT_FOUND)

mfe_config = {'MFE_CONFIG': configuration_helpers.get_value('MFE_CONFIG', {})}
if request.query_params.get('mfe'):
mfe = str(request.query_params.get('mfe')).upper()
mfe_config[f'MFE_CONFIG_{mfe}']= configuration_helpers.get_value(f'MFE_CONFIG_{mfe}',{})

return JsonResponse(mfe_config, status=status.HTTP_200_OK)
21 changes: 21 additions & 0 deletions lms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,18 @@
# .. toggle_target_removal_date: None
# .. toggle_tickets: 'https://openedx.atlassian.net/browse/MST-1458'
'ENABLE_CERTIFICATES_IDV_REQUIREMENT': False,

# .. toggle_name: FEATURES['ENABLE_MFE_API']
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: Set to True to enable MFE Config REST API. This is disabled by
# default.
# .. toggle_use_cases: open_edx
# .. toggle_creation_date: 2022-05-20
# .. toggle_target_removal_date: None
# .. toggle_warnings: None
# .. toggle_tickets: None
'ENABLE_MFE_API': False,
}

# Specifies extra XBlock fields that should available when requested via the Course Blocks API
Expand Down Expand Up @@ -3251,6 +3263,9 @@ def _make_locale_paths(settings): # pylint: disable=missing-function-docstring

# Blockstore
'blockstore.apps.bundles',

# MFE API
'lms.djangoapps.mfe_api',
]

######################### CSRF #########################################
Expand Down Expand Up @@ -4909,6 +4924,12 @@ def _make_locale_paths(settings): # pylint: disable=missing-function-docstring
# .. toggle_tickets: https://openedx.atlassian.net/browse/VAN-838
ENABLE_DYNAMIC_REGISTRATION_FIELDS = False

# .. setting_name: MFE_API_CONFIG_CACHE_TIMEOUT
# .. setting_default: 60*5
# .. setting_description: The MFE_CONFIG site configuration will be cached during the
# specified time
MFE_API_CONFIG_CACHE_TIMEOUT = 60 * 5

############### Settings for the ace_common plugin #################
# Note that all settings are actually defined by the plugin
# pylint: disable=wrong-import-position
Expand Down
3 changes: 3 additions & 0 deletions lms/envs/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -1078,3 +1078,6 @@ def get_env_setting(setting):
"SECRET": ENV_TOKENS.get('BIG_BLUE_BUTTON_GLOBAL_SECRET', None),
"URL": ENV_TOKENS.get('BIG_BLUE_BUTTON_GLOBAL_URL', None),
}

############################# MFE API CONFIG CACHE TIMEOUT############################
MFE_API_CONFIG_CACHE_TIMEOUT = ENV_TOKENS.get('MFE_API_CONFIG_CACHE_TIMEOUT', MFE_API_CONFIG_CACHE_TIMEOUT)
3 changes: 3 additions & 0 deletions lms/envs/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,3 +647,6 @@
"SECRET": "***",
"URL": "***",
}

################## MFE API ####################
FEATURES['ENABLE_MFE_API'] = True
5 changes: 5 additions & 0 deletions lms/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -1022,3 +1022,8 @@
urlpatterns += [
path('api/instructor_task/', include('lms.djangoapps.instructor_task.rest_api.urls')),
]

# MFE API urls
urlpatterns += [
path('api/mfe/', include(('lms.djangoapps.mfe_api.urls', 'lms.djangoapps.mfe_api'), namespace='mfe_api'))
]

0 comments on commit 7f5eb29

Please sign in to comment.