From 3d088dee1a80bf2ec5494ec03b1d42f8980c2a08 Mon Sep 17 00:00:00 2001 From: Deimer M Date: Tue, 13 Jan 2026 15:01:36 -0500 Subject: [PATCH 1/2] fix: reapply entermittent "utils attribute not found" issue in webpack_loader (#37306)" (#314) This reverts commit 37a438c335f130ad5f4e4c60362a8ffe23d3b0d6. --- xmodule/util/builtin_assets.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/xmodule/util/builtin_assets.py b/xmodule/util/builtin_assets.py index cb1fca721414..6b8eb86ecf34 100644 --- a/xmodule/util/builtin_assets.py +++ b/xmodule/util/builtin_assets.py @@ -5,7 +5,6 @@ """ from pathlib import Path -import webpack_loader from django.conf import settings from django.core.exceptions import ImproperlyConfigured @@ -44,6 +43,11 @@ def add_webpack_js_to_fragment(fragment, bundle_name): """ Add all JS webpack chunks to the supplied fragment. """ - for chunk in webpack_loader.utils.get_files(bundle_name, None, 'DEFAULT'): + # Importing webpack_loader.utils at the top of the module causes an exception: + # OSError: Error reading webpack-stats.json. + # Are you sure webpack has generated the file and the path is correct? + # We are not quite sure why. + from webpack_loader.utils import get_files + for chunk in get_files(bundle_name, None, 'DEFAULT'): if chunk['name'].endswith(('.js', '.js.gz')): fragment.add_javascript_url(chunk['url']) From 9e178e286a2ebfce9c14d916c3bd7a17e9dd92bc Mon Sep 17 00:00:00 2001 From: Deimer M Date: Mon, 19 Jan 2026 11:24:19 -0500 Subject: [PATCH 2/2] fix: revert CourseLimitedStaffRole should not be able to access studio. (#311)" This reverts commit 2e2704e68c596cf7be5866e7c1c6d4cb7246ff5a. --- .../contentstore/tests/test_course_listing.py | 44 ------------------- cms/djangoapps/contentstore/views/course.py | 5 +-- common/djangoapps/student/auth.py | 6 +-- common/djangoapps/student/tests/test_authz.py | 18 -------- 4 files changed, 3 insertions(+), 70 deletions(-) diff --git a/cms/djangoapps/contentstore/tests/test_course_listing.py b/cms/djangoapps/contentstore/tests/test_course_listing.py index a2b6f07d15ef..e46b493b7b39 100644 --- a/cms/djangoapps/contentstore/tests/test_course_listing.py +++ b/cms/djangoapps/contentstore/tests/test_course_listing.py @@ -24,10 +24,8 @@ get_courses_accessible_to_user ) from common.djangoapps.course_action_state.models import CourseRerunState -from common.djangoapps.student.models.user import CourseAccessRole from common.djangoapps.student.roles import ( CourseInstructorRole, - CourseLimitedStaffRole, CourseStaffRole, GlobalStaff, OrgInstructorRole, @@ -190,48 +188,6 @@ def test_staff_course_listing(self): with self.assertNumQueries(2): list(_accessible_courses_summary_iter(self.request)) - def test_course_limited_staff_course_listing(self): - # Setup a new course - course_location = self.store.make_course_key('Org', 'CreatedCourse', 'Run') - CourseFactory.create( - org=course_location.org, - number=course_location.course, - run=course_location.run - ) - course = CourseOverviewFactory.create(id=course_location, org=course_location.org) - - # Add the user as a course_limited_staff on the course - CourseLimitedStaffRole(course.id).add_users(self.user) - self.assertTrue(CourseLimitedStaffRole(course.id).has_user(self.user)) - - # Fetch accessible courses list & verify their count - courses_list_by_staff, __ = get_courses_accessible_to_user(self.request) - - # Limited Course Staff should not be able to list courses in Studio - assert len(list(courses_list_by_staff)) == 0 - - def test_org_limited_staff_course_listing(self): - - # Setup a new course - course_location = self.store.make_course_key('Org', 'CreatedCourse', 'Run') - CourseFactory.create( - org=course_location.org, - number=course_location.course, - run=course_location.run - ) - course = CourseOverviewFactory.create(id=course_location, org=course_location.org) - - # Add a user as course_limited_staff on the org - # This is not possible using the course roles classes but is possible via Django admin so we - # insert a row into the model directly to test that scenario. - CourseAccessRole.objects.create(user=self.user, org=course_location.org, role=CourseLimitedStaffRole.ROLE) - - # Fetch accessible courses list & verify their count - courses_list_by_staff, __ = get_courses_accessible_to_user(self.request) - - # Limited Course Staff should not be able to list courses in Studio - assert len(list(courses_list_by_staff)) == 0 - def test_get_course_list_with_invalid_course_location(self): """ Test getting courses with invalid course location (course deleted from modulestore). diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index deeb4a4ee2fe..81ad1eb6ddde 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -53,7 +53,6 @@ GlobalStaff, UserBasedRole, OrgStaffRole, - strict_role_checking, ) from common.djangoapps.util.json_request import JsonResponse, JsonResponseBadRequest, expect_json from common.djangoapps.util.string_utils import _has_non_ascii_characters @@ -534,9 +533,7 @@ def filter_ccx(course_access): return not isinstance(course_access.course_id, CCXLocator) instructor_courses = UserBasedRole(request.user, CourseInstructorRole.ROLE).courses_with_role() - with strict_role_checking(): - staff_courses = UserBasedRole(request.user, CourseStaffRole.ROLE).courses_with_role() - + staff_courses = UserBasedRole(request.user, CourseStaffRole.ROLE).courses_with_role() all_courses = list(filter(filter_ccx, instructor_courses | staff_courses)) courses_list = [] course_keys = {} diff --git a/common/djangoapps/student/auth.py b/common/djangoapps/student/auth.py index 047f0174a062..e199142fe377 100644 --- a/common/djangoapps/student/auth.py +++ b/common/djangoapps/student/auth.py @@ -24,7 +24,6 @@ OrgInstructorRole, OrgLibraryUserRole, OrgStaffRole, - strict_role_checking, ) # Studio permissions: @@ -116,9 +115,8 @@ def get_user_permissions(user, course_key, org=None, service_variant=None): return STUDIO_NO_PERMISSIONS # Staff have all permissions except EDIT_ROLES: - with strict_role_checking(): - if OrgStaffRole(org=org).has_user(user) or (course_key and user_has_role(user, CourseStaffRole(course_key))): - return STUDIO_VIEW_USERS | STUDIO_EDIT_CONTENT | STUDIO_VIEW_CONTENT + if OrgStaffRole(org=org).has_user(user) or (course_key and user_has_role(user, CourseStaffRole(course_key))): + return STUDIO_VIEW_USERS | STUDIO_EDIT_CONTENT | STUDIO_VIEW_CONTENT # Otherwise, for libraries, users can view only: if course_key and isinstance(course_key, LibraryLocator): diff --git a/common/djangoapps/student/tests/test_authz.py b/common/djangoapps/student/tests/test_authz.py index 70636e04b68a..c0b88e6318b5 100644 --- a/common/djangoapps/student/tests/test_authz.py +++ b/common/djangoapps/student/tests/test_authz.py @@ -11,7 +11,6 @@ from django.test import TestCase, override_settings from opaque_keys.edx.locator import CourseLocator -from common.djangoapps.student.models.user import CourseAccessRole from common.djangoapps.student.auth import ( add_users, has_studio_read_access, @@ -306,23 +305,6 @@ def test_limited_staff_no_studio_access_cms(self): assert not has_studio_read_access(self.limited_staff, self.course_key) assert not has_studio_write_access(self.limited_staff, self.course_key) - @override_settings(SERVICE_VARIANT='cms') - def test_limited_org_staff_no_studio_access_cms(self): - """ - Verifies that course limited staff have no read and no write access when SERVICE_VARIANT is not 'lms'. - """ - # Add a user as course_limited_staff on the org - # This is not possible using the course roles classes but is possible via Django admin so we - # insert a row into the model directly to test that scenario. - CourseAccessRole.objects.create( - user=self.limited_staff, - org=self.course_key.org, - role=CourseLimitedStaffRole.ROLE, - ) - - assert not has_studio_read_access(self.limited_staff, self.course_key) - assert not has_studio_write_access(self.limited_staff, self.course_key) - class CourseOrgGroupTest(TestCase): """