Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions openedx/core/djangoapps/course_live/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,38 @@ def test_post_error_messages(self):
self.assertEqual(content, expected_data) # noqa: PT009
self.assertEqual(response.status_code, 400) # noqa: PT009

def test_post_missing_provider_type_without_pii_flag(self):
"""
Test a missing provider_type is reported as a 400, with no PII sharing flag set.

Distinct from `test_post_error_messages`, which enables `CourseAllowPIISharingInLTIFlag`.
That flag makes `pii_sharing_allowed` true, which short-circuits the `and` in the view's
PII check before the unresolved (None) provider is dereferenced. Without the flag the
provider *is* dereferenced, and the view used to raise an AttributeError -- a 500 on the
documented 400 path.
"""
response = self._post({})

self.assertEqual(response.status_code, 400) # noqa: PT009
content = json.loads(response.content.decode('utf-8'))
self.assertEqual(content, {'provider_type': ['This field is required.']}) # noqa: PT009

def test_post_unknown_provider_type_without_pii_flag(self):
"""
Test a provider_type that names no enabled provider is reported as a 400.

Same unresolved-provider path as above, reached with a provider_type that is present but
does not match an enabled provider.
"""
response = self._post({
'enabled': True,
'provider_type': 'not_a_real_provider',
})

self.assertEqual(response.status_code, 400) # noqa: PT009
content = json.loads(response.content.decode('utf-8'))
self.assertIn('does not exist', str(content)) # noqa: PT009

def test_non_staff_user_access(self):
"""
Test non staff user has no access to API
Expand Down
5 changes: 4 additions & 1 deletion openedx/core/djangoapps/course_live/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ def post(self, request, course_id: str) -> Response:
"""
pii_sharing_allowed = get_lti_pii_sharing_state_for_course(course_id)
provider = ProviderManager().get_enabled_providers().get(request.data.get('provider_type', ''), None)
if not pii_sharing_allowed and provider.requires_pii_sharing():
# `provider` is None when `provider_type` is missing or names a provider that is not
# enabled. Let the serializer report that as a 400 rather than raising an AttributeError
# here -- the check below already treats `provider` as optional.
if not pii_sharing_allowed and provider and provider.requires_pii_sharing():
return Response({
"pii_sharing_allowed": pii_sharing_allowed,
"message": "PII sharing is not allowed on this course"
Expand Down
Loading