Commit 7510e57
authored
fix: Course Auditor gets 403 navigating to a course unit (#38986)
* fix: Course Auditor gets 403 navigating to a course unit
xblock_outline_handler (the course outline tree) was already migrated to
the AuthZ-aware user_has_course_permission(..., COURSES_VIEW_COURSE, ...,
LegacyAuthoringPermission.READ) check, so it correctly recognizes AuthZ-
native roles that have no legacy equivalent, like course_auditor and
course_editor.
xblock_container_handler (the unit/container page — what's hit when
navigating to a unit) and xblock_view_handler (renders each child block's
preview fragment on that page), plus xblock_edit_view, were never migrated
the same way: they still called the legacy-only has_studio_read_access
directly, which only recognizes roles with a legacy equivalent
(staff/instructor/limited_staff). A Course Auditor has none, so
get_user_permissions() returned no permissions and these handlers raised
PermissionDenied, even though the outline (using the correct pattern) let
the same user in.
Migrate the three remaining read checks in block.py to the same
user_has_course_permission pattern xblock_outline_handler already uses.
The xblock_handler/handle_xblock CRUD endpoint was already correctly
AuthZ-aware (via _check_xblock_permission) and needed no change.
Fixes openedx/openedx-authz#384
* fix: also fix the REST API v1 container view that the Authoring MFE actually uses
Manual testing against a real devstack found that the block.py fix alone
wasn't enough: the modern Authoring MFE calls the REST API v1
ContainerHandlerView (/api/contentstore/v1/container_handler/...), which
still 403'd for course_auditor.
That view (and container_handler/container_embed_handler/xblock_edit_view
in the legacy views) all route through the shared _get_item_in_course()
helper in component.py, which gated on has_course_author_access — a
legacy-only *write* check — even though all four callers only need read
access to render a view. course_auditor has no legacy role equivalent, so
it never had write access and always got PermissionDenied here, regardless
of the block.py fix.
Migrate _get_item_in_course() to the same user_has_course_permission read
check, fixing all four callers (including the REST API v1 view) at their
single shared choke point instead of patching each call site.
Verified locally end-to-end: mounted this branch into a real devstack,
assigned course_auditor to a test user, confirmed the unit page 403'd
before this commit and loads correctly after it. Also ran the full
test_block.py + test_vertical_block.py suites against the same devstack
(186 passed).
* fix: sort imports (ruff I001)
* refactor: use plain assert instead of self.assertEqual in new tests
Per review feedback from @BryanttV on #38986 (same feedback given
earlier on #38984/#38980) — new test code in this repo should use
plain assert, not unittest-style assertions with # noqa: PT009.1 parent b13ef66 commit 7510e57
4 files changed
Lines changed: 164 additions & 5 deletions
File tree
- cms/djangoapps/contentstore
- rest_api/v1/views/tests
- views
- tests
Lines changed: 37 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
| 10 | + | |
9 | 11 | | |
10 | 12 | | |
11 | 13 | | |
12 | 14 | | |
13 | 15 | | |
14 | 16 | | |
| 17 | + | |
| 18 | + | |
15 | 19 | | |
16 | 20 | | |
17 | 21 | | |
| |||
275 | 279 | | |
276 | 280 | | |
277 | 281 | | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
278 | 315 | | |
279 | 316 | | |
280 | 317 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
142 | 142 | | |
143 | 143 | | |
144 | 144 | | |
145 | | - | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
146 | 151 | | |
147 | 152 | | |
148 | 153 | | |
| |||
299 | 304 | | |
300 | 305 | | |
301 | 306 | | |
302 | | - | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
303 | 313 | | |
304 | 314 | | |
305 | 315 | | |
| |||
371 | 381 | | |
372 | 382 | | |
373 | 383 | | |
374 | | - | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
375 | 390 | | |
376 | 391 | | |
377 | 392 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
| |||
28 | 29 | | |
29 | 30 | | |
30 | 31 | | |
| 32 | + | |
| 33 | + | |
31 | 34 | | |
32 | 35 | | |
33 | 36 | | |
| |||
491 | 494 | | |
492 | 495 | | |
493 | 496 | | |
494 | | - | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
495 | 502 | | |
496 | 503 | | |
497 | 504 | | |
| |||
501 | 508 | | |
502 | 509 | | |
503 | 510 | | |
504 | | - | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
505 | 517 | | |
506 | 518 | | |
507 | 519 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3627 | 3627 | | |
3628 | 3628 | | |
3629 | 3629 | | |
| 3630 | + | |
| 3631 | + | |
| 3632 | + | |
| 3633 | + | |
| 3634 | + | |
| 3635 | + | |
| 3636 | + | |
| 3637 | + | |
| 3638 | + | |
| 3639 | + | |
| 3640 | + | |
| 3641 | + | |
| 3642 | + | |
| 3643 | + | |
| 3644 | + | |
| 3645 | + | |
| 3646 | + | |
| 3647 | + | |
| 3648 | + | |
| 3649 | + | |
| 3650 | + | |
| 3651 | + | |
| 3652 | + | |
| 3653 | + | |
| 3654 | + | |
| 3655 | + | |
| 3656 | + | |
| 3657 | + | |
| 3658 | + | |
| 3659 | + | |
| 3660 | + | |
| 3661 | + | |
| 3662 | + | |
| 3663 | + | |
| 3664 | + | |
| 3665 | + | |
| 3666 | + | |
| 3667 | + | |
| 3668 | + | |
| 3669 | + | |
| 3670 | + | |
| 3671 | + | |
| 3672 | + | |
| 3673 | + | |
| 3674 | + | |
| 3675 | + | |
| 3676 | + | |
| 3677 | + | |
| 3678 | + | |
| 3679 | + | |
| 3680 | + | |
| 3681 | + | |
| 3682 | + | |
| 3683 | + | |
| 3684 | + | |
| 3685 | + | |
| 3686 | + | |
| 3687 | + | |
| 3688 | + | |
| 3689 | + | |
| 3690 | + | |
| 3691 | + | |
| 3692 | + | |
| 3693 | + | |
| 3694 | + | |
| 3695 | + | |
| 3696 | + | |
| 3697 | + | |
| 3698 | + | |
| 3699 | + | |
| 3700 | + | |
| 3701 | + | |
| 3702 | + | |
| 3703 | + | |
| 3704 | + | |
| 3705 | + | |
| 3706 | + | |
| 3707 | + | |
| 3708 | + | |
| 3709 | + | |
| 3710 | + | |
| 3711 | + | |
| 3712 | + | |
| 3713 | + | |
| 3714 | + | |
| 3715 | + | |
| 3716 | + | |
| 3717 | + | |
| 3718 | + | |
| 3719 | + | |
| 3720 | + | |
| 3721 | + | |
| 3722 | + | |
| 3723 | + | |
| 3724 | + | |
3630 | 3725 | | |
3631 | 3726 | | |
3632 | 3727 | | |
| |||
0 commit comments