Skip to content

Commit 696991e

Browse files
committed
feat: add tests for platform-wide scope handling in course listing authorization
1 parent 4f07614 commit 696991e

1 file changed

Lines changed: 93 additions & 1 deletion

File tree

cms/djangoapps/contentstore/tests/test_course_listing.py

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from ccx_keys.locator import CCXLocator
1111
from django.test import RequestFactory
1212
from opaque_keys.edx.locations import CourseLocator
13-
from openedx_authz.api.data import OrgCourseOverviewGlobData
13+
from openedx_authz.api.data import OrgCourseOverviewGlobData, PlatformCourseOverviewGlobData
1414
from openedx_authz.api.users import assign_role_to_user_in_scope
1515
from openedx_authz.constants.roles import COURSE_DATA_RESEARCHER, COURSE_EDITOR, COURSE_STAFF
1616

@@ -21,6 +21,7 @@
2121
_accessible_courses_iter_for_tests,
2222
_accessible_courses_list_from_groups,
2323
_accessible_courses_summary_iter,
24+
_get_course_keys_from_scopes,
2425
get_courses_accessible_to_user,
2526
)
2627
from common.djangoapps.course_action_state.models import CourseRerunState
@@ -832,3 +833,94 @@ def test_course_listing_with_org_scope_fetched_once(self):
832833
courses, _ = get_courses_accessible_to_user(request)
833834

834835
mock_get_all_courses.assert_called_once_with(orgs={"Org1", "Org2"})
836+
837+
def test_course_listing_with_platform_scope(self):
838+
"""
839+
Verify that a platform-wide scope (`course-v1:*`) grants access to all
840+
courses across orgs when the AuthZ course authoring toggle is enabled.
841+
"""
842+
_, _, authz_courses, _ = self._create_courses()
843+
org2_course_key = CourseLocator("Org2", "Course1", "AuthzRun")
844+
org2_course = self._create_course(org2_course_key)
845+
assign_role_to_user_in_scope(
846+
self.authorized_user.username,
847+
COURSE_STAFF.external_key,
848+
PlatformCourseOverviewGlobData.build_external_key(),
849+
)
850+
851+
request = self._make_request(self.authorized_user)
852+
853+
with self._authz_waffle_context(active=True):
854+
courses, _ = get_courses_accessible_to_user(request)
855+
856+
result_ids = {c.id for c in courses}
857+
expected_ids = {*(c.id for c in authz_courses), org2_course.id}
858+
859+
self.assertEqual(result_ids, expected_ids) # noqa: PT009
860+
861+
def test_course_listing_with_platform_scope_with_toggle(self):
862+
"""
863+
If the authz toggle is enabled only for a subset of courses, only those
864+
course keys should appear when resolving a platform-wide scope.
865+
"""
866+
authz_keys, _, _, _ = self._create_courses()
867+
org2_course_key = CourseLocator("Org2", "Course1", "AuthzRun")
868+
self._create_course(org2_course_key)
869+
enabled_keys = {str(authz_keys[0]), str(authz_keys[2])}
870+
assign_role_to_user_in_scope(
871+
self.authorized_user.username,
872+
COURSE_STAFF.external_key,
873+
PlatformCourseOverviewGlobData.build_external_key(),
874+
)
875+
876+
request = self._make_request(self.authorized_user)
877+
878+
with patch.object(
879+
core_toggles.AUTHZ_COURSE_AUTHORING_FLAG,
880+
"is_enabled",
881+
side_effect=self._mock_authz_toggle(enabled_keys),
882+
):
883+
courses, _ = get_courses_accessible_to_user(request)
884+
885+
result_ids = {c.id for c in courses}
886+
expected = {authz_keys[0], authz_keys[2]}
887+
self.assertEqual(result_ids, expected) # noqa: PT009
888+
889+
def test_get_course_keys_from_scopes_with_platform_scope(self):
890+
"""
891+
Platform-wide scopes should resolve to all courses with AuthZ enabled.
892+
"""
893+
authz_keys, _, _, _ = self._create_courses()
894+
org2_course_key = CourseLocator("Org2", "Course1", "AuthzRun")
895+
self._create_course(org2_course_key)
896+
enabled_keys = {str(key) for key in authz_keys}
897+
898+
with patch.object(
899+
core_toggles.AUTHZ_COURSE_AUTHORING_FLAG,
900+
"is_enabled",
901+
side_effect=self._mock_authz_toggle(enabled_keys),
902+
):
903+
course_keys = _get_course_keys_from_scopes([PlatformCourseOverviewGlobData.build_external_key()])
904+
905+
self.assertEqual(course_keys, set(authz_keys)) # noqa: PT009
906+
907+
def test_get_course_keys_from_scopes_platform_scope_short_circuits(self):
908+
"""
909+
When a platform-wide scope is present, org and course scopes should be ignored.
910+
"""
911+
authz_keys, _, _, _ = self._create_courses()
912+
enabled_keys = {str(authz_keys[0])}
913+
914+
with patch.object(
915+
core_toggles.AUTHZ_COURSE_AUTHORING_FLAG,
916+
"is_enabled",
917+
side_effect=self._mock_authz_toggle(enabled_keys),
918+
):
919+
course_keys = _get_course_keys_from_scopes(
920+
[
921+
OrgCourseOverviewGlobData.build_external_key("Org1"),
922+
PlatformCourseOverviewGlobData.build_external_key(),
923+
]
924+
)
925+
926+
self.assertEqual(course_keys, {authz_keys[0]}) # noqa: PT009

0 commit comments

Comments
 (0)