Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
6 changes: 6 additions & 0 deletions common/djangoapps/student/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from openedx_authz.api import users as authz_api
from openedx_authz.api.data import CourseOverviewData, OrgCourseOverviewGlobData, RoleAssignmentData
from openedx_authz.constants import roles as authz_roles
from organizations.api import get_organizations

from common.djangoapps.student.models import CourseAccessRole
from common.djangoapps.student.signals.signals import emit_course_access_role_added, emit_course_access_role_removed
Expand Down Expand Up @@ -632,6 +633,11 @@ def _authz_get_orgs_for_user(self, user) -> list[str]:
user_external_key=user.username,
role_external_key=role,
)
# A platform-wide grant (course-v1:*, lib:*) covers every org, not just the ones
# with a concrete assignment. Platform-glob scopes have no .org attribute at all
# (unlike org-glob/course/library scopes, where it's a real field that can be None).
if any(assignment.scope.IS_PLATFORM_GLOB for assignment in assignments):
return [org["short_name"] for org in get_organizations()]
Comment thread
efortish marked this conversation as resolved.
Resolved
orgs = {assignment.scope.org for assignment in assignments if assignment.scope.org is not None}
return list(orgs)

Expand Down
29 changes: 29 additions & 0 deletions common/djangoapps/student/tests/test_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
ContentLibraryData,
CourseOverviewData,
OrgCourseOverviewGlobData,
PlatformCourseOverviewGlobData,
RoleAssignmentData,
RoleData,
ScopeData,
UserData,
)
from openedx_authz.constants.roles import COURSE_ADMIN, COURSE_STAFF
from openedx_authz.engine.enforcer import AuthzEnforcer
from organizations.api import add_organization

from common.djangoapps.student.admin import CourseAccessRoleHistoryAdmin
from common.djangoapps.student.models import CourseAccessRoleHistory, User
Expand Down Expand Up @@ -313,6 +315,33 @@ def test_get_orgs_for_user_authz(self):
result = role.get_orgs_for_user(self.student)
self.assertCountEqual(result, [self.course_key.org, other_org]) # noqa: PT009

@override_waffle_flag(AUTHZ_COURSE_AUTHORING_FLAG, active=True)
def test_get_orgs_for_user_authz_platform_glob(self):
"""
A platform-wide glob assignment (course-v1:*) has no `.org` attribute, unlike
course/org-glob scopes. get_orgs_for_user must special-case it and return every
registered org instead of crashing with an AttributeError.
"""
role = CourseStaffRole(self.course_key)

for org in self.orgs:
add_organization({"name": org, "short_name": org, "description": ""})

staff_authz_role = RoleData(external_key=COURSE_STAFF)
assignments = [
RoleAssignmentData(
subject=UserData(external_key=self.student.username),
roles=[staff_authz_role],
scope=PlatformCourseOverviewGlobData(external_key="course-v1:*"),
Comment thread
efortish marked this conversation as resolved.
Resolved
),
]

with patch("openedx_authz.api.users.get_user_role_assignments_filtered", return_value=assignments):
result = role.get_orgs_for_user(self.student)
self.assertCountEqual(result, self.orgs) # noqa: PT009
assert role.has_org_for_user(self.student)
assert role.has_org_for_user(self.student, org=self.orgs[0])

def test_get_authz_compat_course_access_roles_for_user(self):
"""
Test that get_authz_compat_course_access_roles_for_user doesn't crash when the user
Expand Down
Loading