Skip to content

Commit ba6026f

Browse files
xitij2000farhaanbukhsh
authored andcommitted
feat: Allow adding custom LTI parameters via LTI_CUSTOM_PARAMS django setting
Adds a new Django setting called `LTI_CUSTOM_PARAMS` that allows extending the list of optional LTI parameters processed by the platform. These parameters can be used by plugins for deeper platform integration.
1 parent c5f0f09 commit ba6026f

3 files changed

Lines changed: 46 additions & 2 deletions

File tree

lms/djangoapps/lti_provider/tests/test_views.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
"""
22
Tests for the LTI provider views
33
"""
4-
5-
64
from unittest.mock import MagicMock, patch
75

86
from django.contrib.auth.models import AnonymousUser
97
from django.test import TestCase
108
from django.test.client import RequestFactory
9+
from django.test.utils import override_settings
1110
from django.urls import reverse
1211
from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator
1312
from openedx_events.learning.data import UserData, UserPersonalData, LtiProviderLaunchData, LtiProviderLaunchParamsData
@@ -143,6 +142,23 @@ def test_valid_launch_with_optional_params(self, _authenticate, store_params, _r
143142
self.consumer
144143
)
145144

145+
@patch('lms.djangoapps.lti_provider.views.render_courseware')
146+
@patch('lms.djangoapps.lti_provider.views.store_outcome_parameters')
147+
@patch('lms.djangoapps.lti_provider.views.authenticate_lti_user')
148+
@override_settings(LTI_CUSTOM_PARAMS=["extra_param1", "extra_param2"])
149+
def test_valid_launch_with_extra_params(self, _authenticate, store_params, _render):
150+
"""
151+
Verifies that the LTI launch succeeds when passed a valid request.
152+
"""
153+
extra_params = {'extra_param1': 'extra_value1', 'extra_param2': "extra_value2"}
154+
request = build_launch_request(extra_post_data=LTI_OPTIONAL_PARAMS | extra_params)
155+
views.lti_launch(request, str(COURSE_KEY), str(USAGE_KEY))
156+
store_params.assert_called_with(
157+
dict(list(ALL_PARAMS.items()) + list(LTI_OPTIONAL_PARAMS.items()) + list(extra_params.items())),
158+
request.user,
159+
self.consumer
160+
)
161+
146162
@patch('lms.djangoapps.courseware.views.views.render_xblock')
147163
@patch('lms.djangoapps.lti_provider.views.authenticate_lti_user')
148164
def test_render_xblock_params(self, _authenticate, render):

lms/djangoapps/lti_provider/views.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from lms.djangoapps.lti_provider.outcomes import store_outcome_parameters
2121
from lms.djangoapps.lti_provider.signature_validator import SignatureValidator
2222
from lms.djangoapps.lti_provider.users import authenticate_lti_user
23+
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
2324
from openedx.core.lib.url_utils import unquote_slashes
2425

2526
log = logging.getLogger("edx.lti_provider")
@@ -61,6 +62,7 @@ def lti_launch(request, course_id, usage_id):
6162
if not params:
6263
return HttpResponseBadRequest()
6364
params.update(get_optional_parameters(request.POST))
65+
params.update(get_custom_parameters(request.POST))
6466

6567
# Get the consumer information from either the instance GUID or the consumer
6668
# key
@@ -175,6 +177,22 @@ def get_optional_parameters(dictionary):
175177
return {key: dictionary[key] for key in OPTIONAL_PARAMETERS if key in dictionary}
176178

177179

180+
def get_custom_parameters(params: dict[str]) -> dict[str]:
181+
"""
182+
Extract all optional LTI parameters from a dictionary. This method does not
183+
fail if any parameters are missing.
184+
185+
:param params: A dictionary containing zero or more parameters.
186+
:return: A new dictionary containing all optional parameters from the
187+
original dictionary, or an empty dictionary if no optional parameters
188+
were present.
189+
"""
190+
custom_params = configuration_helpers.get_value("LTI_CUSTOM_PARAMS", settings.LTI_CUSTOM_PARAMS)
191+
if not custom_params:
192+
return {}
193+
return {key: params[key] for key in custom_params if key in params}
194+
195+
178196
def render_courseware(request, usage_key):
179197
"""
180198
Render the content requested for the LTI launch.

lms/envs/common.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3984,6 +3984,16 @@
39843984
# The time value is in seconds.
39853985
LTI_AGGREGATE_SCORE_PASSBACK_DELAY = 15 * 60
39863986

3987+
3988+
# .. setting_name: LTI_CUSTOM_PARAMS
3989+
# .. setting_default: []
3990+
# .. setting_description: This expands the list of optional LTI parameters that the
3991+
# platform accepts. These parameters are not used by the platform, but can then
3992+
# be used by other plugins.
3993+
# .. setting_creation_date: 2025-08-22
3994+
# .. setting_tickets:
3995+
LTI_CUSTOM_PARAMS = []
3996+
39873997
# Credit notifications settings
39883998
NOTIFICATION_EMAIL_CSS = "templates/credit_notifications/credit_notification.css"
39893999
NOTIFICATION_EMAIL_EDX_LOGO = "templates/credit_notifications/edx-logo-header.png"

0 commit comments

Comments
 (0)