Skip to content

Commit 9640095

Browse files
committed
feat: support organization-level scopes for course list
1 parent eeb95b8 commit 9640095

File tree

2 files changed

+77
-7
lines changed

2 files changed

+77
-7
lines changed

cms/djangoapps/contentstore/tests/test_course_listing.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +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
1314
from openedx_authz.api.users import assign_role_to_user_in_scope
1415
from openedx_authz.constants.roles import COURSE_DATA_RESEARCHER, COURSE_EDITOR, COURSE_STAFF
1516

@@ -20,6 +21,7 @@
2021
_accessible_courses_iter_for_tests,
2122
_accessible_courses_list_from_groups,
2223
_accessible_courses_summary_iter,
24+
_get_authz_accessible_courses_list,
2325
get_courses_accessible_to_user,
2426
)
2527
from common.djangoapps.course_action_state.models import CourseRerunState
@@ -715,3 +717,58 @@ def test_superuser_gets_all_courses(self):
715717
}
716718

717719
self.assertEqual(result_ids, expected_ids)
720+
721+
def test_get_authz_accessible_courses_list_with_org_scope(self):
722+
"""
723+
When the scope is an OrgCourseOverviewGlobData, all course keys
724+
returned by `_get_course_keys_for_org_scope` should be included in
725+
the resulting authz keys when the authz toggle is enabled.
726+
"""
727+
authz_keys, _, authz_courses, _ = self._create_courses()
728+
org_scope = OrgCourseOverviewGlobData(external_key='course-v1:Org1+*')
729+
730+
request = self._make_request(self.authorized_user)
731+
732+
with patch(
733+
"cms.djangoapps.contentstore.views.course.get_scopes_for_user_and_permission",
734+
return_value=[org_scope],
735+
), patch(
736+
"cms.djangoapps.contentstore.views.course._get_course_keys_for_org_scope",
737+
return_value=authz_keys,
738+
) as mock_get_keys, patch.object(
739+
core_toggles.AUTHZ_COURSE_AUTHORING_FLAG,
740+
"is_enabled",
741+
return_value=True,
742+
):
743+
result = _get_authz_accessible_courses_list(request)
744+
745+
mock_get_keys.assert_called_once_with(org_scope)
746+
self.assertEqual(result, set(authz_keys))
747+
748+
def test_get_authz_accessible_courses_list_org_scope_respects_toggle(self):
749+
"""
750+
If the authz toggle is enabled only for a subset of org courses, only
751+
those course keys should appear in the resulting authz keys.
752+
"""
753+
authz_keys, _, authz_courses, _ = self._create_courses()
754+
# enable only the first and third course keys
755+
enabled_keys = {str(authz_keys[0]), str(authz_keys[2])}
756+
org_scope = OrgCourseOverviewGlobData(external_key='course-v1:Org1+*')
757+
758+
request = self._make_request(self.authorized_user)
759+
760+
with patch(
761+
"cms.djangoapps.contentstore.views.course.get_scopes_for_user_and_permission",
762+
return_value=[org_scope],
763+
), patch(
764+
"cms.djangoapps.contentstore.views.course._get_course_keys_for_org_scope",
765+
return_value=authz_keys,
766+
), patch.object(
767+
core_toggles.AUTHZ_COURSE_AUTHORING_FLAG,
768+
"is_enabled",
769+
side_effect=self._mock_authz_toggle(enabled_keys),
770+
):
771+
result = _get_authz_accessible_courses_list(request)
772+
773+
expected = {authz_keys[0], authz_keys[2]}
774+
self.assertEqual(result, expected)

cms/djangoapps/contentstore/views/course.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from opaque_keys.edx.keys import CourseKey
3030
from opaque_keys.edx.locator import BlockUsageLocator
3131
from openedx_authz.api import get_scopes_for_user_and_permission
32-
from openedx_authz.api.data import CourseOverviewData
32+
from openedx_authz.api.data import CourseOverviewData, OrgCourseOverviewGlobData
3333
from openedx_authz.constants.permissions import (
3434
COURSES_MANAGE_COURSE_UPDATES,
3535
COURSES_MANAGE_GROUP_CONFIGURATIONS,
@@ -817,6 +817,14 @@ def filter_course(course):
817817
return filter(filter_course, filtered_courses)
818818

819819

820+
def _get_course_keys_for_org_scope(access):
821+
"""
822+
Function to convert an OrgCourseOverviewGlobData scope
823+
into specific course keys.
824+
"""
825+
return CourseOverview.get_all_courses(orgs=[access.org]).values_list('id', flat=True)
826+
827+
820828
def _get_authz_accessible_courses_list(request):
821829
"""
822830
List all courses available to the logged in user by
@@ -828,12 +836,17 @@ def _get_authz_accessible_courses_list(request):
828836
COURSES_VIEW_COURSE.identifier
829837
)
830838

831-
authz_keys = {
832-
access.course_key
833-
for access in authz_scopes
834-
if isinstance(access, CourseOverviewData) and access.course_key
835-
and core_toggles.enable_authz_course_authoring(access.course_key)
836-
}
839+
authz_keys = set()
840+
for access in authz_scopes:
841+
if isinstance(access, CourseOverviewData) and access.course_key:
842+
if core_toggles.enable_authz_course_authoring(access.course_key):
843+
authz_keys.add(access.course_key)
844+
elif isinstance(access, OrgCourseOverviewGlobData) and access.org:
845+
authz_keys.update(
846+
key for key in _get_course_keys_for_org_scope(access)
847+
if core_toggles.enable_authz_course_authoring(key)
848+
)
849+
837850
return authz_keys
838851

839852

0 commit comments

Comments
 (0)