feat: AuthZ for course authoring compatibility layer - #38013
Conversation
|
Thanks for the pull request, @rodmgwgu! This repository is currently maintained by Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review. 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. DetailsWhere can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources: When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
b2b2bee to
6d842f9
Compare
c915425 to
5dc65a2
Compare
d28972c to
9477f62
Compare
|
I finally got my environment working on main again and was able to successfully test this going in both directions, it works great. I'll finish reviewing the actual code tomorrow |
bmtcril
left a comment
There was a problem hiding this comment.
This is looking good, just a few comments
dwong2708
left a comment
There was a problem hiding this comment.
This looks good overall! just a couple of suggestions and questions.
0bd07e0 to
7638824
Compare
bmtcril
left a comment
There was a problem hiding this comment.
I think once the other feedback is addressed this is good to go 👍
be3398d to
50c8a13
Compare
|
@rodmgwgu Thanks for the PR! After it was merged, we started seeing the following exception on the master branch. Reverting the PR reverting the issue. Steps to reproduce: 2026-03-10 04:32:36,306 INFO 166 [tracking] [user 4] [ip 172.18.0.1] logger.py:41 - {"name": "/api/learner_home/init", "context": {"user_id": 4, "path": "/api/learner_home/init", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "edx", "session": "036fc95ce131136bd8ee0a3a2a73af56", "ip": "172.18.0.1", "agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36", "host": "local.openedx.io:8000", "referer": "http://apps.local.openedx.io:1996/", "accept_language": "en-US,en;q=0.9", "event": "{\"GET\": {}, \"POST\": {}}", "time": "2026-03-10T04:32:36.306663+00:00", "event_type": "/api/learner_home/init", "event_source": "server", "page": null}
[10/Mar/2026 04:32:36] "GET /theming/asset/images/logo.png HTTP/1.1" 302 0
2026-03-10 04:32:36,346 ERROR 166 [root] [user None] [ip None] signals.py:22 - Uncaught exception from None
Traceback (most recent call last):
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 234, in __init__
self._roles_by_course_id = BulkRoleCache.get_user_roles(user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 215, in get_user_roles
return get_cache(cls.CACHE_NAMESPACE)[cls.CACHE_KEY][user.id]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
KeyError: 'roles_by_user'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 238, in get_namespace_plugin
return drivers[namespace].plugin
~~~~~~~^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/stevedore/extension.py", line 452, in __getitem__
return self._extensions_by_name[name]
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
KeyError: 'lib'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 190, in from_string
key_class = cls.get_namespace_plugin(namespace)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 243, in get_namespace_plugin
raise InvalidKeyError(cls, f'{namespace}:*') from error
opaque_keys.InvalidKeyError: <class 'opaque_keys.edx.keys.CourseKey'>: lib:*
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/openedx/venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/pyenv/versions/3.12.12/lib/python3.12/contextlib.py", line 81, in inner
return func(*args, **kwds)
^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
return view_func(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view
return self.dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 515, in dispatch
response = self.handle_exception(exc)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 475, in handle_exception
self.raise_uncaught_exception(exc)
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 486, in raise_uncaught_exception
raise exc
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 512, in dispatch
response = handler(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/lms/djangoapps/learner_home/views.py", line 475, in get
return self._initialize(request.user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/lms/djangoapps/learner_home/views.py", line 513, in _initialize
audit_access_deadlines = get_audit_access_deadlines(user, course_enrollments)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/pyenv/versions/3.12.12/lib/python3.12/contextlib.py", line 81, in inner
return func(*args, **kwds)
^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/lms/djangoapps/learner_home/views.py", line 419, in get_audit_access_deadlines
course_enrollment.course_id: get_user_course_expiration_date(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/course_duration_limits/access.py", line 80, in get_user_course_expiration_date
access_duration = get_user_course_duration(user, course)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/course_duration_limits/access.py", line 57, in get_user_course_duration
if not CourseDurationLimitConfig.enabled_for_enrollment(user, course):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/course_duration_limits/models.py", line 59, in enabled_for_enrollment
target_datetime = enrollment_date_for_fbe(user, course=course)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/content_type_gating/helpers.py", line 117, in enrollment_date_for_fbe
if user and user.id and has_staff_roles(user, course_key):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/core/lib/cache_utils.py", line 74, in decorator
result = wrapped(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/role_helpers.py", line 39, in has_staff_roles
is_staff = CourseStaffRole(course_key).has_user(user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 385, in has_user
user._roles = RoleCache(user)
^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 239, in __init__
compat_roles = get_authz_compat_course_access_roles_for_user(user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 144, in get_authz_compat_course_access_roles_for_user
parsed_key = CourseKey.from_string(course_key)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 198, in from_string
return cls.deprecated_fallback._from_deprecated_string(serialized) # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/edx/locator.py", line 403, in _from_deprecated_string
raise InvalidKeyError(cls, serialized)
opaque_keys.InvalidKeyError: <class 'opaque_keys.edx.locator.CourseLocator'>: lib:axim:1
Internal Server Error: /api/learner_home/init
Traceback (most recent call last):
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 234, in __init__
self._roles_by_course_id = BulkRoleCache.get_user_roles(user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 215, in get_user_roles
return get_cache(cls.CACHE_NAMESPACE)[cls.CACHE_KEY][user.id]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
KeyError: 'roles_by_user'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 238, in get_namespace_plugin
return drivers[namespace].plugin
~~~~~~~^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/stevedore/extension.py", line 452, in __getitem__
return self._extensions_by_name[name]
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
KeyError: 'lib'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 190, in from_string
key_class = cls.get_namespace_plugin(namespace)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 243, in get_namespace_plugin
raise InvalidKeyError(cls, f'{namespace}:*') from error
opaque_keys.InvalidKeyError: <class 'opaque_keys.edx.keys.CourseKey'>: lib:*
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/openedx/venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/pyenv/versions/3.12.12/lib/python3.12/contextlib.py", line 81, in inner
return func(*args, **kwds)
^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
return view_func(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view
return self.dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 515, in dispatch
response = self.handle_exception(exc)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 475, in handle_exception
self.raise_uncaught_exception(exc)
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 486, in raise_uncaught_exception
raise exc
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 512, in dispatch
response = handler(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/lms/djangoapps/learner_home/views.py", line 475, in get
return self._initialize(request.user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/lms/djangoapps/learner_home/views.py", line 513, in _initialize
audit_access_deadlines = get_audit_access_deadlines(user, course_enrollments)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/pyenv/versions/3.12.12/lib/python3.12/contextlib.py", line 81, in inner
return func(*args, **kwds)
^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/lms/djangoapps/learner_home/views.py", line 419, in get_audit_access_deadlines
course_enrollment.course_id: get_user_course_expiration_date(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/course_duration_limits/access.py", line 80, in get_user_course_expiration_date
access_duration = get_user_course_duration(user, course)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/course_duration_limits/access.py", line 57, in get_user_course_duration
if not CourseDurationLimitConfig.enabled_for_enrollment(user, course):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/course_duration_limits/models.py", line 59, in enabled_for_enrollment
target_datetime = enrollment_date_for_fbe(user, course=course)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/content_type_gating/helpers.py", line 117, in enrollment_date_for_fbe
if user and user.id and has_staff_roles(user, course_key):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/core/lib/cache_utils.py", line 74, in decorator
result = wrapped(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/role_helpers.py", line 39, in has_staff_roles
is_staff = CourseStaffRole(course_key).has_user(user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 385, in has_user
user._roles = RoleCache(user)
^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 239, in __init__
compat_roles = get_authz_compat_course_access_roles_for_user(user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 144, in get_authz_compat_course_access_roles_for_user
parsed_key = CourseKey.from_string(course_key)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 198, in from_string
return cls.deprecated_fallback._from_deprecated_string(serialized) # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/edx/locator.py", line 403, in _from_deprecated_string
raise InvalidKeyError(cls, serialized)
opaque_keys.InvalidKeyError: <class 'opaque_keys.edx.locator.CourseLocator'>: lib:axim:1
2026-03-10 04:32:36,448 ERROR 166 [django.request] [user None] [ip None] log.py:253 - Internal Server Error: /api/learner_home/init
Traceback (most recent call last):
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 234, in __init__
self._roles_by_course_id = BulkRoleCache.get_user_roles(user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 215, in get_user_roles
return get_cache(cls.CACHE_NAMESPACE)[cls.CACHE_KEY][user.id]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
KeyError: 'roles_by_user'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 238, in get_namespace_plugin
return drivers[namespace].plugin
~~~~~~~^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/stevedore/extension.py", line 452, in __getitem__
return self._extensions_by_name[name]
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
KeyError: 'lib'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 190, in from_string
key_class = cls.get_namespace_plugin(namespace)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 243, in get_namespace_plugin
raise InvalidKeyError(cls, f'{namespace}:*') from error
opaque_keys.InvalidKeyError: <class 'opaque_keys.edx.keys.CourseKey'>: lib:*
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/openedx/venv/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/pyenv/versions/3.12.12/lib/python3.12/contextlib.py", line 81, in inner
return func(*args, **kwds)
^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
return view_func(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view
return self.dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 515, in dispatch
response = self.handle_exception(exc)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 475, in handle_exception
self.raise_uncaught_exception(exc)
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 486, in raise_uncaught_exception
raise exc
File "/openedx/venv/lib/python3.12/site-packages/rest_framework/views.py", line 512, in dispatch
response = handler(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/lms/djangoapps/learner_home/views.py", line 475, in get
return self._initialize(request.user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/lms/djangoapps/learner_home/views.py", line 513, in _initialize
audit_access_deadlines = get_audit_access_deadlines(user, course_enrollments)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/pyenv/versions/3.12.12/lib/python3.12/contextlib.py", line 81, in inner
return func(*args, **kwds)
^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/lms/djangoapps/learner_home/views.py", line 419, in get_audit_access_deadlines
course_enrollment.course_id: get_user_course_expiration_date(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/course_duration_limits/access.py", line 80, in get_user_course_expiration_date
access_duration = get_user_course_duration(user, course)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/course_duration_limits/access.py", line 57, in get_user_course_duration
if not CourseDurationLimitConfig.enabled_for_enrollment(user, course):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/course_duration_limits/models.py", line 59, in enabled_for_enrollment
target_datetime = enrollment_date_for_fbe(user, course=course)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/features/content_type_gating/helpers.py", line 117, in enrollment_date_for_fbe
if user and user.id and has_staff_roles(user, course_key):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/openedx/core/lib/cache_utils.py", line 74, in decorator
result = wrapped(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/role_helpers.py", line 39, in has_staff_roles
is_staff = CourseStaffRole(course_key).has_user(user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 385, in has_user
user._roles = RoleCache(user)
^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 239, in __init__
compat_roles = get_authz_compat_course_access_roles_for_user(user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/edx-platform/common/djangoapps/student/roles.py", line 144, in get_authz_compat_course_access_roles_for_user
parsed_key = CourseKey.from_string(course_key)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/__init__.py", line 198, in from_string
return cls.deprecated_fallback._from_deprecated_string(serialized) # type: ignore
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/openedx/venv/lib/python3.12/site-packages/opaque_keys/edx/locator.py", line 403, in _from_deprecated_string
raise InvalidKeyError(cls, serialized)
opaque_keys.InvalidKeyError: <class 'opaque_keys.edx.locator.CourseLocator'>: lib:axim:1
[10/Mar/2026 04:32:36] "GET /api/learner_home/init HTTP/1.1" 500 459267 |
Description
Part of the AuthZ for Course Authoring project.
Implemented a compatibility layer on legacy permission role checking for Course Authoring in studio.
This also covers legacy endpoints that are used for configuring course authoring permissions, so legacy views (like the one in instructor-dashboard) continue to work.
The objective of this task is to keep compatibility with existing codepaths that use the existing endpoints to manage roles related with course authoring.
Implementation details:
Supporting information
Closes: #37909
Related technical discovery documents:
Testing instructions
Running relevant unit tests manually
Inside a cms container (
tutor dev run lms bash):Deadline
Verawood release.
Other information
Depends on: openedx/openedx-authz#217
Performance: I'm seeing that in average the change adds 2 database queries on related codepaths that read course data related to roles, this is mainly because of some api calls that previously returned a CourseAccessRole QuerySet now return AuthzCompatCourseAccessRole which is a data object, so we cannot optimize queries on code like this: https://github.com/WGU-Open-edX/edx-platform/blob/d28972c1f0ac26f94fcbd055ef95c899e5d9e837/cms/djangoapps/contentstore/views/course.py#L540-L541