Skip to content

feat: enforce AuthZ permissions in the Grading endpoints - #39366

Open
carlos-marquez-wgu wants to merge 1 commit into
openedx:masterfrom
WGU-Open-edX:carlos-marquez-wgu/issue-490-authz-instructor-dashboard-enforcement_grading-tab-2
Open

carlos-marquez-wgu wants to merge 1 commit into
openedx:masterfrom
WGU-Open-edX:carlos-marquez-wgu/issue-490-authz-instructor-dashboard-enforcement_grading-tab-2

Conversation

@carlos-marquez-wgu

@carlos-marquez-wgu carlos-marquez-wgu commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Description

Migrate the Grading tab endpoints of the Instructor Dashboard API v2 from InstructorPermission to InstructorAuthzPermission:

  • LearnerView (GET): courses.view_gradebook
  • ProblemView (GET): courses.view_gradebook
  • GradingConfigView (GET): courses.view_grading_settings
  • ResetAttemptsView (POST): courses.manage_learner_grading
  • DeleteStateView (DELETE): courses.manage_learner_grading
  • RescoreView (POST): courses.manage_learner_grading
  • ScoreOverrideView (PUT): courses.manage_learner_grading

The behavior follows the authz.enable_course_authoring waffle flag, as introduced in #39255:

  • Flag enabled for the course: only AuthZ is consulted, except for the legacy roles that openedx-authz maps without dashboard permissions (course_limited_staff, course_data_researcher, course_beta_tester). Those fall back to the legacy check when AuthZ denies, so they keep their legacy access. courses.manage_learner_grading covers both the Single Learner and the All Learners actions.
  • Flag disabled: each view keeps its legacy bridgekeeper permission, and the All Learners actions still require instructor access, so existing users keep their access.

Other changes:

  • GradingConfigView uses courses.view_grading_settings instead of courses.view_grading_configuration. openedx-authz does not define the latter, and it is no longer in the Instructor Dashboard Permissions catalog (see this discussion).
  • All Learners actions (bulk reset attempts and bulk rescore) check courses.manage_learner_grading with the flag enabled, and keep the legacy instructor check with it disabled.
  • ScoreOverrideView no longer runs its extra has_access(user, 'staff', block) check. The problem key is mapped into the URL's course, so it resolved to the same course-level staff check as the view's legacy permission (OVERRIDE_GRADES). With the flag disabled it was redundant; with it enabled, it made courses.manage_learner_grading insufficient to override scores.

Affected roles: Course Admin, Course Staff, legacy course instructors and legacy course staff. The AuthZ Course Limited Staff, Course Data Researcher and Course Beta Tester roles keep the access of their legacy role.

Supporting Information

Testing Instructions

Setup

  1. Pick a course, for example course-v1:OpenedX+DemoX+DemoCourse, and a problem in it (its usage key, for example block-v1:OpenedX+DemoX+DemoCourse+type@problem+block@<id>).
  2. Enroll a learner, learner, and submit at least one answer to that problem as the learner, so there is state to reset, rescore and delete.
  3. With the flag disabled, open Studio > Settings > Course Team and add:
    • legacy_admin as Admin (legacy instructor).
    • legacy_staff as Staff (legacy staff).
  4. Enable the flag:
    tutor dev exec lms ./manage.py lms waffle_flag authz.enable_course_authoring --create --everyone
  5. With the flag enabled, open Studio > Settings > Roles and Permissions (it replaces Course Team while the flag is on) and assign:
    • authz_admin the Course Admin role.
    • authz_staff the Course Staff role.

Open the Grading tab at http://apps.local.openedx.io:8080/instructor-dashboard/<course_id>/grading and use the Single Learner and All Learners actions. To check responses directly, use the browser's network tab or call the endpoints (<problem> is the problem's usage key):

Action Request Status on success
View learner GET /api/instructor/v2/courses/<course_id>/learners/<learner> 200
View problem GET /api/instructor/v2/courses/<course_id>/problems/<problem> 200
View grading configuration GET /api/instructor/v2/courses/<course_id>/grading-config 200
Reset attempts, Single Learner POST /api/instructor/v2/courses/<course_id>/<problem>/grading/attempts/reset?learner=<learner> 200
Delete state, Single Learner DELETE /api/instructor/v2/courses/<course_id>/<problem>/grading/state?learner=<learner> 200
Rescore, Single Learner POST /api/instructor/v2/courses/<course_id>/<problem>/grading/scores/rescore?learner=<learner> 202
Override score, Single Learner PUT /api/instructor/v2/courses/<course_id>/<problem>/grading/scores?learner=<learner> with {"score": 0.5} 202
Reset attempts, All Learners POST /api/instructor/v2/courses/<course_id>/<problem>/grading/attempts/reset 202
Rescore, All Learners POST /api/instructor/v2/courses/<course_id>/<problem>/grading/scores/rescore 202

With the flag enabled

User Grading tab Views Single Learner actions All Learners actions
authz_admin Shown 200 Success 202
authz_staff Shown 200 Success 202 (behavior change, see Concerns section)
legacy_admin Hidden (no access to the dashboard) 403 403 403

With the flag disabled

Disable the flag:

tutor dev exec lms ./manage.py lms waffle_flag authz.enable_course_authoring --deactivate
User Grading tab Views Single Learner actions All Learners actions
legacy_admin Shown 200 Success 202
legacy_staff Shown 200 Success 403 (Instructor access required for bulk operations)

Users with an AuthZ role keep access while the flag is disabled, because of the compatibility layer between AuthZ roles and legacy roles (see #39255). This is expected.

Automated tests

tutor dev exec lms pytest lms/djangoapps/instructor/tests/test_api_v2_authz.py -k GradingTab

Deadline

Willow

Concerns

Behavior changes and known gaps, let me know if the changes are acceptable or do we need a different approach:

  • Course Staff can run the All Learners actions (flag enabled only): courses.manage_learner_grading covers both the Single Learner and All Learners actions, so Course Staff can reset attempts and rescore for all learners. Before this change, the All Learners actions required instructor access, in both the v1 and v2 APIs. This follows the Instructor Dashboard Permissions catalog: Single Learner and All Learners share Manage Learner Grading, and the UI should tell individual and course-wide operations apart. With the flag disabled, the legacy rule is unchanged. Is this acceptable?
  • TaskStatusView: not migrated. Its permission is still to be defined, and it is shared with other tabs.

Note

Shared test helpers: this PR adds allowed_only and allowed_all_except to test_api_v2_authz.py. The Course Team PR (#489) adds the same helpers. Whichever merges second will drop the duplicate.

AI Usage Notice

Kiro and Claude were used to help write the code and tests. A person guided the work, reviewed and corrected every change, and checked that it meets the requirements of the linked issue.

Migrate the Grading tab endpoints of the Instructor Dashboard API v2
from InstructorPermission to InstructorAuthzPermission:

- LearnerView (GET): courses.view_gradebook
- ProblemView (GET): courses.view_gradebook
- GradingConfigView (GET): courses.view_grading_settings
- ResetAttemptsView (POST): courses.manage_learner_grading
- DeleteStateView (DELETE): courses.manage_learner_grading
- RescoreView (POST): courses.manage_learner_grading
- ScoreOverrideView (PUT): courses.manage_learner_grading
@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Nov 11, 2026
@openedx-webhooks

openedx-webhooks commented Nov 11, 2026 •

Copy link
Copy Markdown

Thanks for the pull request, @carlos-marquez-wgu!

This repository is currently maintained by @openedx/wg-maintenance-openedx-platform-oncall.

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 approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.
🔘 Provide context

To 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:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads
🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

Details
Where 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:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

@github-project-automation github-project-automation Bot moved this to Needs Triage in Contributions Nov 11, 2026
@carlos-marquez-wgu
carlos-marquez-wgu marked this pull request as ready for review November 12, 2026 16:10
@carlos-marquez-wgu

Copy link
Copy Markdown
Contributor Author

Hi @openedx/wg-maintenance-openedx-platform-oncall, this PR is ready for reviews, thanks!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

open-source-contribution PR author is not from Axim or 2U

Projects

Status: Needs Triage

Development

Successfully merging this pull request may close these issues.

Enforcement: Grading tab

2 participants