Skip to content

fix: avoid anonymous completion lookup in navigation#38024

Merged
navinkarkera merged 4 commits into
openedx:masterfrom
Abstract-Tech:meet/fix_course-outline
Jun 18, 2026
Merged

fix: avoid anonymous completion lookup in navigation#38024
navinkarkera merged 4 commits into
openedx:masterfrom
Abstract-Tech:meet/fix_course-outline

Conversation

@meet0208

Copy link
Copy Markdown
Contributor

Description

This PR fixes course outline loading for anonymous users in the Learning MFE by preventing a server error in the course navigation API.

Previously, anonymous requests to GET /api/course_home/v1/navigation/{course_key} could raise a 500 when completion data was queried with AnonymousUser. This caused the course outline sidebar to fail to render for logged-out users, even when course visibility and waffle settings allowed public access.

This change adds an anonymous-user guard in CourseNavigationBlocksView.completions_dict:

  • If request.user is anonymous, return an empty completion map ({}).
  • Keep existing outline access filtering logic (filter_inaccessible_blocks) unchanged to preserve access control.

Implications

  • Anonymous users now receive a valid navigation payload instead of a 500.
  • Visibility/access restrictions continue to be enforced by existing processors and filtering.
  • No behavior change for authenticated learners/staff.

Supporting information

Relevant code / endpoint

  • File: lms/djangoapps/course_home_api/outline/views.py
  • Endpoint: GET /api/course_home/v1/navigation/{course_key}
  • Root cause: completion lookup attempted for AnonymousUser

Configuration context (unchanged)

  • seo.enable_anonymous_courseware_access enabled
  • Course visibility set to public or public_outline

Testing instructions

  1. Ensure the course is configured with:

    • visibility set to public (or public_outline)
    • waffle flag seo.enable_anonymous_courseware_access enabled
  2. Open the courseware URL in an incognito / logged-out browser session.

  3. Confirm GET /api/course_home/v1/navigation/{course_key} returns 200 (not 500).

  4. Verify the outline sidebar renders in the Learning MFE.

  5. Log in as a learner and as staff/admin and confirm outline behavior is unchanged.

  6. Optional regression checks:

    • Confirm hidden/inaccessible content remains filtered as before.
    • Confirm no new traceback appears in LMS logs for anonymous navigation requests.

Deadline

None.

Other information

User roles impacted

  • Learner: Yes (logged-out / public access flow)
  • Course Author: No direct impact
  • Developer: Yes (API behavior and debugging flow)
  • Operator: Yes (reduced 500s in logs for anonymous navigation requests)

UI changes

  • UI impact: course outline now renders for anonymous users on eligible public / public_outline courses.

  • Suggested screenshots to attach:

    1. Before: anonymous courseware page with missing/empty outline + API 500
    2. After: anonymous courseware page with outline visible + API 200
    3. Network tab response for /api/course_home/v1/navigation/{course_key} (before vs after)

Configuration changes

  • None.

Dependencies / special concerns

  • No dependency on other PRs.
  • No deprecations or migrations.
  • Security/access control is unchanged (no relaxation of access restrictions); this only prevents anonymous completion lookup failures.
  • No API contract changes.

@openedx-webhooks

openedx-webhooks commented Feb 19, 2026

Copy link
Copy Markdown

Thanks for the pull request, @meet0208!

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

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.

@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Feb 19, 2026
@github-project-automation github-project-automation Bot moved this to Needs Triage in Contributions Feb 19, 2026
@mphilbrick211 mphilbrick211 added the needs test run Author's first PR to this repository, awaiting test authorization from Axim label Feb 24, 2026
@mphilbrick211 mphilbrick211 moved this from Needs Triage to Needs Tests Run or CLA Signed in Contributions Feb 24, 2026
@mphilbrick211

Copy link
Copy Markdown

Hi @meet0208! Thank you for this contribution!

It looks like you're contributing on behalf of an organization. If so, could you please have your manager reach out to oscm@axim.org to have you added to our existing entity agreement? That way, we can get your CLA check to turn green.

@e0d

e0d commented Feb 25, 2026

Copy link
Copy Markdown
Contributor

@meet0208 you've been added to the entity CLA and that should be reflected in GitHub this evening.

@e0d e0d removed the needs test run Author's first PR to this repository, awaiting test authorization from Axim label Feb 25, 2026
@meet0208

meet0208 commented Feb 26, 2026

Copy link
Copy Markdown
Contributor Author

@e0d or @mphilbrick211 Hey can you approve a re run for this PR.

@mphilbrick211 mphilbrick211 moved this from Needs Tests Run or CLA Signed to Ready for Review in Contributions Mar 11, 2026
@mphilbrick211 mphilbrick211 added the needs reviewer assigned PR needs to be (re-)assigned a new reviewer label Mar 11, 2026
@ChrisChV

Copy link
Copy Markdown
Contributor

Hi @meet0208, I can't reproduce the bug:

Previously, anonymous requests to GET /api/course_home/v1/navigation/{course_key} could raise a 500 when completion data was queried with AnonymousUser

I tested it with the current master branch and got a 200 with an empty response. Can you verify it?

@mphilbrick211 mphilbrick211 removed the needs reviewer assigned PR needs to be (re-)assigned a new reviewer label Jun 1, 2026
@mphilbrick211 mphilbrick211 moved this from Ready for Review to In Eng Review in Contributions Jun 1, 2026
@navinkarkera

Copy link
Copy Markdown
Contributor

@meet0208 Thank you for your contribution. I was able to reproduce this issue in master.

@ChrisChV Here are the steps:

  1. Enable anonymous courseware waffle flag seo.enable_anonymous_courseware_access
  2. Set course visibility to public in course advanced settings
  3. Hit navigation API:
  curl -i "http://localhost:18000/api/course_home/v1/navigation/course-v1:edX+DemoX+Demo_Course"
  1. OR you can open the course outline (lms) in a private browsing window, then check the LMS logs, you'll see below error:
lms-1  |   File "/openedx/edx-platform/lms/djangoapps/course_home_api/outline/views.py", line 618, in completions_dict
lms-1  |     completions = BlockCompletion.objects.filter(user=self.request.user, context_key=course_key).values_list(
lms-1  |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/django/db/models/manager.py", line 87, in manager_method
lms-1  |     return getattr(self.get_queryset(), name)(*args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/django/db/models/query.py", line 1495, in filter
lms-1  |     return self._filter_or_exclude(False, args, kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/django/db/models/query.py", line 1513, in _filter_or_exclude
lms-1  |     clone._filter_or_exclude_inplace(negate, args, kwargs)
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/django/db/models/query.py", line 1523, in _filter_or_exclude_inplace
lms-1  |     self._query.add_q(Q(*args, **kwargs))
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/django/db/models/sql/query.py", line 1648, in add_q
lms-1  |     clause, _ = self._add_q(q_object, can_reuse)
lms-1  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/django/db/models/sql/query.py", line 1680, in _add_q
lms-1  |     child_clause, needed_inner = self.build_filter(
lms-1  |                                  ^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/django/db/models/sql/query.py", line 1590, in build_filter
lms-1  |     condition = self.build_lookup(lookups, col, value)
lms-1  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/django/db/models/sql/query.py", line 1417, in build_lookup
lms-1  |     lookup = lookup_class(lhs, rhs)
lms-1  |              ^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/django/db/models/lookups.py", line 38, in __init__
lms-1  |     self.rhs = self.get_prep_lookup()
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/django/db/models/fields/related_lookups.py", line 112, in get_prep_lookup
lms-1  |     self.rhs = target_field.get_prep_value(self.rhs)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.12/site-packages/django/db/models/fields/__init__.py", line 2130, in get_prep_value
lms-1  |     raise e.__class__(
lms-1  | TypeError: Field 'id' expected a number but got <django.contrib.auth.models.AnonymousUser object at 0x7fb35bd1fc50>.

@meet0208 Could you please add a test in lms/djangoapps/course_home_api/outline/tests/test_view.py for this change.

@navinkarkera navinkarkera self-requested a review June 9, 2026 05:22
@navinkarkera navinkarkera moved this from In Eng Review to Waiting on Author in Contributions Jun 16, 2026
@navinkarkera

Copy link
Copy Markdown
Contributor

@meet0208 Could you please add a test in lms/djangoapps/course_home_api/outline/tests/test_view.py for this change.

@meet0208 Gentle reminder

@meet0208

Copy link
Copy Markdown
Contributor Author

@navinkarkera Hey, I added a test case can you review and let me know.

@navinkarkera

Copy link
Copy Markdown
Contributor

@meet0208 Thanks! Can you please rebase with master.

@meet0208 meet0208 force-pushed the meet/fix_course-outline branch from 1979db2 to ebbb97c Compare June 18, 2026 13:00
@meet0208

Copy link
Copy Markdown
Contributor Author

@navinkarkera I did can you check now.

@meet0208

Copy link
Copy Markdown
Contributor Author

@navinkarkera Why the tests are failing to install "No matching distribution found for django-autocomplete-light==4.0.1" ? Even I rebased my branch with master.

@navinkarkera

Copy link
Copy Markdown
Contributor

@meet0208 It is an issue with the master branch. Once #38779 is merged, we can rebase here and see if the CI passes.

meet0208 added 3 commits June 18, 2026 09:44
… outline.

Return empty completions_dict for AnonymousUser in CourseNavigationBlocksView to prevent 500 on /api/course_home/v1/navigation/{course_key} for public anonymous access. Keeps existing outline access filtering unchanged.
@meet0208 meet0208 force-pushed the meet/fix_course-outline branch from ebbb97c to 3b135ce Compare June 18, 2026 13:44
@meet0208

Copy link
Copy Markdown
Contributor Author

@navinkarkera #38779 this is merged can you run pipeline now.

@meet0208

Copy link
Copy Markdown
Contributor Author

@navinkarkera One test case failed as my test was mocked BlockCompletion.objects.filter around the full API request. In other words, the test was exercising more than the specific guard. So, can you rerun the CI now.

@meet0208

Copy link
Copy Markdown
Contributor Author

@navinkarkera All the test cases are passed.

@navinkarkera navinkarkera left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@meet0208 Thanks for you work!

@navinkarkera navinkarkera merged commit 47c5078 into openedx:master Jun 18, 2026
41 checks passed
@github-project-automation github-project-automation Bot moved this from Waiting on Author to Done in Contributions Jun 18, 2026
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: Done

Development

Successfully merging this pull request may close these issues.

6 participants