Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Anonymous Courseware access broken in Nutmeg #443

Open
ormsbee opened this issue Aug 23, 2022 · 5 comments
Open

Anonymous Courseware access broken in Nutmeg #443

ormsbee opened this issue Aug 23, 2022 · 5 comments
Assignees
Labels
bug Report of or fix for something that isn't working as intended

Comments

@ormsbee
Copy link

ormsbee commented Aug 23, 2022

We've gotten reports that Anonymous courseware access is broken in Nutmeg, likely due to this PR.

This ticket would include:

  1. Fix the anonymous user handling, for the courseware API view.
  2. Add new tests to make sure that this doesn't break again for anonymous users.
  3. Backport this fix to Nutmeg.
@ormsbee ormsbee added the bug Report of or fix for something that isn't working as intended label Aug 23, 2022
@ormsbee ormsbee moved this to To Do - Backlog in Axim Engineering Tasks Aug 23, 2022
@ormsbee
Copy link
Author

ormsbee commented Aug 23, 2022

FYI @jmakowski1123, @e0d, @kdmccormick

@ormsbee ormsbee moved this from To Do - Backlog to To Do - Prioritized for Current Sprint in Axim Engineering Tasks Aug 23, 2022
@ormsbee ormsbee self-assigned this Aug 23, 2022
@eirikhanssen
Copy link

Hello,

I am joining this conversation with and behalf of my colleague Gabi who contacted you on e-mail.

When trying to access a course anonymously, we're experiencing this issue with Nutmeg installed using tutor v 14.0.4:

The page will display: There was an error loading this course.

We had tried to add the suggested following waffle flags in django for the following course: course-v1:OsloMetX+SP22+01

Waffle flags added:
grades.assume_zero_grade_if_absent
seo.enable_anonymous_courseware_access

Here's a stacktrace from ~/.local/share/tutor/data/lms/logs/all.log when trying to access the course anonumously:

2022-10-04 11:51:51,054 INFO 9 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/", "context": {"user_id": null, "path": "/", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {}, "POST": {}}", "time": "2022-10-04T11:51:51.053848+00:00", "event_type": "/", "event_source": "server", "page": null}
2022-10-04 11:51:54,292 INFO 21 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/courses/course-v1:OsloMetX+SP22+01/about", "context": {"course_id": "course-v1:OsloMetX+SP22+01", "course_user_tags": {}, "user_id": null, "path": "/courses/course-v1:OsloMetX+SP22+01/about", "org_id": "OsloMetX", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {}, "POST": {}}", "time": "2022-10-04T11:51:54.292607+00:00", "event_type": "/courses/course-v1:OsloMetX+SP22+01/about", "event_source": "server", "page": null}
2022-10-04 11:51:54,296 INFO 21 [openedx.core.djangoapps.cors_csrf.helpers] [user None] [ip 158.36.145.87] helpers.py:64 - Origin 'https://devthemes.eu' was not in CORS_ORIGIN_WHITELIST; full referer was 'https://devthemes.eu/' and requested host was 'devthemes.eu'; CORS_ORIGIN_ALLOW_ALL=False
2022-10-04 11:51:57,013 INFO 9 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/theming/asset/images/favicon.ico", "context": {"user_id": null, "path": "/theming/asset/images/favicon.ico", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {}, "POST": {}}", "time": "2022-10-04T11:51:57.013016+00:00", "event_type": "/theming/asset/images/favicon.ico", "event_source": "server", "page": null}
2022-10-04 11:51:57,023 INFO 21 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/theming/asset/images/logo.png", "context": {"user_id": null, "path": "/theming/asset/images/logo.png", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {}, "POST": {}}", "time": "2022-10-04T11:51:57.022787+00:00", "event_type": "/theming/asset/images/logo.png", "event_source": "server", "page": null}
2022-10-04 11:51:57,084 INFO 21 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/api/course_home/outline/course-v1:OsloMetX+SP22+01", "context": {"user_id": null, "path": "/api/course_home/outline/course-v1:OsloMetX+SP22+01", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {}, "POST": {}}", "time": "2022-10-04T11:51:57.083933+00:00", "event_type": "/api/course_home/outline/course-v1:OsloMetX+SP22+01", "event_source": "server", "page": null}
2022-10-04 11:51:57,085 INFO 9 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/api/course_home/course_metadata/course-v1:OsloMetX+SP22+01", "context": {"user_id": null, "path": "/api/course_home/course_metadata/course-v1:OsloMetX+SP22+01", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {"browser_timezone": ["Europe/Oslo"]}, "POST": {}}", "time": "2022-10-04T11:51:57.084968+00:00", "event_type": "/api/course_home/course_metadata/course-v1:OsloMetX+SP22+01", "event_source": "server", "page": null}
2022-10-04 11:51:57,088 WARNING 21 [edx_rest_framework_extensions.auth.jwt.middleware] [user None] [ip 158.36.145.87] middleware.py:253 - Both JWT auth cookies missing. JWT auth cookies will not be reconstituted.
2022-10-04 11:51:57,088 WARNING 9 [edx_rest_framework_extensions.auth.jwt.middleware] [user None] [ip 158.36.145.87] middleware.py:253 - Both JWT auth cookies missing. JWT auth cookies will not be reconstituted.
2022-10-04 11:51:57,759 INFO 21 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/apps.devthemes.eu/src/course-home/outline-tab/LmsHtmlFragment.css", "context": {"user_id": null, "path": "/apps.devthemes.eu/src/course-home/outline-tab/LmsHtmlFragment.css", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {}, "POST": {}}", "time": "2022-10-04T11:51:57.758921+00:00", "event_type": "/apps.devthemes.eu/src/course-home/outline-tab/LmsHtmlFragment.css", "event_source": "server", "page": null}
2022-10-04 11:51:57,762 INFO 9 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/api/edx_proctoring/v1/user_onboarding/status", "context": {"user_id": null, "path": "/api/edx_proctoring/v1/user_onboarding/status", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {"is_learning_mfe": ["true"], "course_id": ["course-v1:OsloMetX+SP22+01"]}, "POST": {}}", "time": "2022-10-04T11:51:57.762506+00:00", "event_type": "/api/edx_proctoring/v1/user_onboarding/status", "event_source": "server", "page": null}
2022-10-04 11:51:57,766 WARNING 9 [edx_rest_framework_extensions.auth.jwt.middleware] [user None] [ip 158.36.145.87] middleware.py:253 - Both JWT auth cookies missing. JWT auth cookies will not be reconstituted.
2022-10-04 11:52:05,281 INFO 9 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/api/courseware/course/course-v1:OsloMetX+SP22+01", "context": {"course_id": "course-v1:OsloMetX+SP22+01", "course_user_tags": {}, "user_id": null, "path": "/api/courseware/course/course-v1:OsloMetX+SP22+01", "org_id": "OsloMetX", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {"browser_timezone": ["Europe/Oslo"]}, "POST": {}}", "time": "2022-10-04T11:52:05.281330+00:00", "event_type": "/api/courseware/course/course-v1:OsloMetX+SP22+01", "event_source": "server", "page": null}
2022-10-04 11:52:05,282 INFO 21 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/api/learning_sequences/v1/course_outline/course-v1:OsloMetX+SP22+01", "context": {"user_id": null, "path": "/api/learning_sequences/v1/course_outline/course-v1:OsloMetX+SP22+01", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {}, "POST": {}}", "time": "2022-10-04T11:52:05.282084+00:00", "event_type": "/api/learning_sequences/v1/course_outline/course-v1:OsloMetX+SP22+01", "event_source": "server", "page": null}
2022-10-04 11:52:05,285 WARNING 9 [edx_rest_framework_extensions.auth.jwt.middleware] [user None] [ip 158.36.145.87] middleware.py:253 - Both JWT auth cookies missing. JWT auth cookies will not be reconstituted.
2022-10-04 11:52:05,286 WARNING 21 [edx_rest_framework_extensions.auth.jwt.middleware] [user None] [ip 158.36.145.87] middleware.py:253 - Both JWT auth cookies missing. JWT auth cookies will not be reconstituted.
2022-10-04 11:52:05,419 INFO 21 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/api/course_home/course_metadata/course-v1:OsloMetX+SP22+01", "context": {"user_id": null, "path": "/api/course_home/course_metadata/course-v1:OsloMetX+SP22+01", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {"browser_timezone": ["Europe/Oslo"]}, "POST": {}}", "time": "2022-10-04T11:52:05.419495+00:00", "event_type": "/api/course_home/course_metadata/course-v1:OsloMetX+SP22+01", "event_source": "server", "page": null}
2022-10-04 11:52:05,422 WARNING 21 [edx_rest_framework_extensions.auth.jwt.middleware] [user None] [ip 158.36.145.87] middleware.py:253 - Both JWT auth cookies missing. JWT auth cookies will not be reconstituted.
2022-10-04 11:52:05,453 INFO 9 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "edx.course.grade.now_failed", "context": {"course_id": "course-v1:OsloMetX+SP22+01", "course_user_tags": {}, "user_id": null, "path": "/api/courseware/course/course-v1:OsloMetX+SP22+01", "org_id": "OsloMetX", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": {"user_id": "None", "course_id": "course-v1:OsloMetX+SP22+01", "event_transaction_id": "None", "event_transaction_type": "None"}, "time": "2022-10-04T11:52:05.453047+00:00", "event_type": "edx.course.grade.now_failed", "event_source": "server", "page": null}
2022-10-04 11:52:05,455 ERROR 9 [root] [user None] [ip None] signals.py:22 - Uncaught exception from None
Traceback (most recent call last):
File "/openedx/edx-platform/./lms/djangoapps/grades/models.py", line 620, in read
prefetched_grades = get_cache(cls._CACHE_NAMESPACE)[cls._cache_key(course_id)]
KeyError: 'grades_cache.course-v1:OsloMetX+SP22+01'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/openedx/edx-platform/./lms/djangoapps/grades/course_grade_factory.py", line 50, in read
return self._read(user, course_data)
File "/openedx/edx-platform/./lms/djangoapps/grades/course_grade_factory.py", line 152, in _read
persistent_grade = PersistentCourseGrade.read(user.id, course_data.course_key)
File "/openedx/edx-platform/./lms/djangoapps/grades/models.py", line 629, in read
return cls.objects.get(user_id=user_id, course_id=course_id)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 435, in get
raise self.model.DoesNotExist(
lms.djangoapps.grades.models.PersistentCourseGrade.DoesNotExist: PersistentCourseGrade matching query does not exist.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/fields/init.py", line 1823, in get_prep_value
return int(value)
File "/openedx/venv/lib/python3.8/site-packages/django/contrib/auth/models.py", line 420, in int
raise TypeError('Cannot cast AnonymousUser to int. Are you trying to use it in place of User?')
TypeError: Cannot cast AnonymousUser to int. Are you trying to use it in place of User?

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/opt/pyenv/versions/3.8.12/lib/python3.8/contextlib.py", line 75, in inner
return func(*args, **kwds)
File "/openedx/venv/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/generics.py", line 208, in get
return self.retrieve(request, *args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/mixins.py", line 56, in retrieve
return Response(serializer.data)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/serializers.py", line 548, in data
ret = super().data
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/serializers.py", line 246, in data
self._data = self.to_representation(self.instance)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/serializers.py", line 502, in to_representation
attribute = field.get_attribute(instance)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/fields.py", line 457, in get_attribute
return get_attribute(instance, self.source_attrs)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/fields.py", line 97, in get_attribute
instance = getattr(instance, attr)
File "/openedx/edx-platform/./openedx/core/djangoapps/courseware_api/views.py", line 221, in entrance_exam_data
self.course_grade, get_entrance_exam_usage_key(self.overview),
File "/openedx/venv/lib/python3.8/site-packages/django/utils/functional.py", line 48, in get
res = instance.dict[self.name] = self.func(instance)
File "/openedx/edx-platform/./openedx/core/djangoapps/courseware_api/views.py", line 187, in course_grade
return CourseGradeFactory().read(self.effective_user, self.course)
File "/openedx/edx-platform/./lms/djangoapps/grades/course_grade_factory.py", line 55, in read
return self._update(user, course_data, send_course_grade_signals=send_course_grade_signals)
File "/openedx/edx-platform/./lms/djangoapps/grades/course_grade_factory.py", line 215, in _update
COURSE_GRADE_NOW_FAILED.send(
File "/openedx/venv/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 180, in send
return [
File "/openedx/venv/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 181, in
(receiver, receiver(signal=self, sender=sender, **named))
File "/openedx/edx-platform/./lms/djangoapps/certificates/signals.py", line 92, in _listen_for_failing_grade
if is_on_certificate_allowlist(user, course_id):
File "/openedx/edx-platform/./lms/djangoapps/certificates/generation_handler.py", line 321, in is_on_certificate_allowlist
return CertificateAllowlist.objects.filter(user=user, course_id=course_key, allowlist=True).exists()
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 941, in filter
return self._filter_or_exclude(False, args, kwargs)
File "/openedx/edx-platform/./openedx/core/djangoapps/xmodule_django/models.py", line 47, in _filter_or_exclude
return super()._filter_or_exclude(*args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 961, in _filter_or_exclude
clone._filter_or_exclude_inplace(negate, args, kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 968, in _filter_or_exclude_inplace
self._query.add_q(Q(*args, **kwargs))
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1416, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1435, in _add_q
child_clause, needed_inner = self.build_filter(
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1370, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1216, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/lookups.py", line 25, in init
self.rhs = self.get_prep_lookup()
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/fields/related_lookups.py", line 117, in get_prep_lookup
self.rhs = target_field.get_prep_value(self.rhs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/fields/init.py", line 1825, in get_prep_value
raise e.class(
TypeError: Field 'id' expected a number but got <django.contrib.auth.models.AnonymousUser object at 0x7fbf1e873d90>.
2022-10-04 11:52:05,480 INFO 21 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/api/courseware/sequence/block-v1:OsloMetX+SP22+01+type@sequential+block@ca56593cbe234a899cd12aaadd168ec2", "context": {"user_id": null, "path": "/api/courseware/sequence/block-v1:OsloMetX+SP22+01+type@sequential+block@ca56593cbe234a899cd12aaadd168ec2", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "", "session": "", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {}, "POST": {}}", "time": "2022-10-04T11:52:05.479880+00:00", "event_type": "/api/courseware/sequence/block-v1:OsloMetX+SP22+01+type@sequential+block@ca56593cbe234a899cd12aaadd168ec2", "event_source": "server", "page": null}
2022-10-04 11:52:05,521 INFO 21 [tracking] [user None] [ip 158.36.145.87] logger.py:41 - {"name": "/api/courseware/sequence/block-v1:OsloMetX+SP22+01+type@sequential+block@ca56593cbe234a899cd12aaadd168ec2", "context": {"user_id": null, "path": "/api/courseware/sequence/block-v1:OsloMetX+SP22+01+type@sequential+block@ca56593cbe234a899cd12aaadd168ec2", "course_id": "", "org_id": "", "enterprise_uuid": ""}, "username": "", "session": "b0f086d89902f8a35bb863a100d218af", "ip": "158.36.145.87", "agent": "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0", "host": "devthemes.eu", "referer": "https://apps.devthemes.eu/", "accept_language": "en-US,en;q=0.5", "event": "{"GET": {}, "POST": {}}", "time": "2022-10-04T11:52:05.520786+00:00", "event_type": "/api/courseware/sequence/block-v1:OsloMetX+SP22+01+type@sequential+block@ca56593cbe234a899cd12aaadd168ec2", "event_source": "server", "page": null}
2022-10-04 11:52:05,524 WARNING 21 [edx_rest_framework_extensions.auth.jwt.middleware] [user None] [ip 158.36.145.87] middleware.py:253 - Both JWT auth cookies missing. JWT auth cookies will not be reconstituted.
2022-10-04 11:52:05,473 ERROR 9 [django.request] [user None] [ip 158.36.145.87] log.py:224 - Internal Server Error: /api/courseware/course/course-v1:OsloMetX+SP22+01
Traceback (most recent call last):
File "/openedx/edx-platform/./lms/djangoapps/grades/models.py", line 620, in read
prefetched_grades = get_cache(cls._CACHE_NAMESPACE)[cls._cache_key(course_id)]
KeyError: 'grades_cache.course-v1:OsloMetX+SP22+01'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/openedx/edx-platform/./lms/djangoapps/grades/course_grade_factory.py", line 50, in read
return self._read(user, course_data)
File "/openedx/edx-platform/./lms/djangoapps/grades/course_grade_factory.py", line 152, in _read
persistent_grade = PersistentCourseGrade.read(user.id, course_data.course_key)
File "/openedx/edx-platform/./lms/djangoapps/grades/models.py", line 629, in read
return cls.objects.get(user_id=user_id, course_id=course_id)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 435, in get
raise self.model.DoesNotExist(
lms.djangoapps.grades.models.PersistentCourseGrade.DoesNotExist: PersistentCourseGrade matching query does not exist.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/fields/init.py", line 1823, in get_prep_value
return int(value)
File "/openedx/venv/lib/python3.8/site-packages/django/contrib/auth/models.py", line 420, in int
raise TypeError('Cannot cast AnonymousUser to int. Are you trying to use it in place of User?')
TypeError: Cannot cast AnonymousUser to int. Are you trying to use it in place of User?

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/opt/pyenv/versions/3.8.12/lib/python3.8/contextlib.py", line 75, in inner
return func(*args, **kwds)
File "/openedx/venv/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/generics.py", line 208, in get
return self.retrieve(request, *args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/mixins.py", line 56, in retrieve
return Response(serializer.data)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/serializers.py", line 548, in data
ret = super().data
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/serializers.py", line 246, in data
self._data = self.to_representation(self.instance)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/serializers.py", line 502, in to_representation
attribute = field.get_attribute(instance)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/fields.py", line 457, in get_attribute
return get_attribute(instance, self.source_attrs)
File "/openedx/venv/lib/python3.8/site-packages/rest_framework/fields.py", line 97, in get_attribute
instance = getattr(instance, attr)
File "/openedx/edx-platform/./openedx/core/djangoapps/courseware_api/views.py", line 221, in entrance_exam_data
self.course_grade, get_entrance_exam_usage_key(self.overview),
File "/openedx/venv/lib/python3.8/site-packages/django/utils/functional.py", line 48, in get
res = instance.dict[self.name] = self.func(instance)
File "/openedx/edx-platform/./openedx/core/djangoapps/courseware_api/views.py", line 187, in course_grade
return CourseGradeFactory().read(self.effective_user, self.course)
File "/openedx/edx-platform/./lms/djangoapps/grades/course_grade_factory.py", line 55, in read
return self._update(user, course_data, send_course_grade_signals=send_course_grade_signals)
File "/openedx/edx-platform/./lms/djangoapps/grades/course_grade_factory.py", line 215, in _update
COURSE_GRADE_NOW_FAILED.send(
File "/openedx/venv/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 180, in send
return [
File "/openedx/venv/lib/python3.8/site-packages/django/dispatch/dispatcher.py", line 181, in
(receiver, receiver(signal=self, sender=sender, **named))
File "/openedx/edx-platform/./lms/djangoapps/certificates/signals.py", line 92, in _listen_for_failing_grade
if is_on_certificate_allowlist(user, course_id):
File "/openedx/edx-platform/./lms/djangoapps/certificates/generation_handler.py", line 321, in is_on_certificate_allowlist
return CertificateAllowlist.objects.filter(user=user, course_id=course_key, allowlist=True).exists()
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 941, in filter
return self._filter_or_exclude(False, args, kwargs)
File "/openedx/edx-platform/./openedx/core/djangoapps/xmodule_django/models.py", line 47, in _filter_or_exclude
return super()._filter_or_exclude(*args, **kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 961, in _filter_or_exclude
clone._filter_or_exclude_inplace(negate, args, kwargs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 968, in _filter_or_exclude_inplace
self._query.add_q(Q(*args, **kwargs))
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1416, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1435, in _add_q
child_clause, needed_inner = self.build_filter(
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1370, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1216, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/lookups.py", line 25, in init
self.rhs = self.get_prep_lookup()
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/fields/related_lookups.py", line 117, in get_prep_lookup
self.rhs = target_field.get_prep_value(self.rhs)
File "/openedx/venv/lib/python3.8/site-packages/django/db/models/fields/init.py", line 1825, in get_prep_value
raise e.class(
TypeError: Field 'id' expected a number but got <django.contrib.auth.models.AnonymousUser object at 0x7fbf1e873d90>.

@ormsbee ormsbee moved this from To Do - Prioritized for Current Sprint to In Progress in Axim Engineering Tasks Oct 28, 2022
@asadali145
Copy link

Hi, I was having a look into this issue and it seems like the above exception is actually fixed with the removal of the ASSUME_ZERO_IF_ABSENT waffle flag under openedx/edx-platform#30978. Now it assumes zero grade by default. As a result of this PR, the issue mentioned above is resolved for anonymous users.

Currently, the course home is still not loading when the MILESTONES_APP feature is set to True.

  • Course home is getting There was an error loading this course. for anonymous users as the backend raises an unhandled exception that results in 500.
  • MILESTONES_APP is required to enable the entrance exams for a course.
  • Exception is raised intentionally for anonymous users when the milestones app is enabled.
  • Exception message says Anonymous access is not allowed for course runs with milestones set..
  • Here is the link to the responsible code snippet.
  • This exception seems to be intentional when Milestones are enabled for a course.
  • Exception Traceback is added at the end of this message.

Possible Solutions:

  1. Log the exception and show a meaningful error message to the user.

TRACEBACK:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib/python3.8/contextlib.py", line 75, in inner
    return func(*args, **kwds)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/course_home_api/outline/views.py", line 286, in get
    user_course_outline = get_user_course_outline(
  File "/usr/lib/python3.8/contextlib.py", line 75, in inner
    return func(*args, **kwds)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/content/learning_sequences/api/outlines.py", line 268, in get_user_course_outline
    user_course_outline, _ = _get_user_course_outline_and_processors(course_key, user, at_time)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/content/learning_sequences/api/outlines.py", line 343, in _get_user_course_outline_and_processors
    processor.load_data(full_course_outline)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/content/learning_sequences/api/processors/content_gating.py", line 35, in load_data
    self.required_content = milestones_helpers.get_required_content(self.course_key, self.user)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/milestones_helpers.py", line 244, in get_required_content
    raise InvalidUserException('Anonymous access is not allowed for course runs with milestones set.')
milestones.exceptions.InvalidUserException: ['Anonymous access is not allowed for course runs with milestones set.']
Internal Server Error: /api/course_home/outline/course-v1:edX+DemoX+Demo_Course
Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib/python3.8/contextlib.py", line 75, in inner
    return func(*args, **kwds)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/course_home_api/outline/views.py", line 286, in get
    user_course_outline = get_user_course_outline(
  File "/usr/lib/python3.8/contextlib.py", line 75, in inner
    return func(*args, **kwds)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/content/learning_sequences/api/outlines.py", line 268, in get_user_course_outline
    user_course_outline, _ = _get_user_course_outline_and_processors(course_key, user, at_time)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/content/learning_sequences/api/outlines.py", line 343, in _get_user_course_outline_and_processors
    processor.load_data(full_course_outline)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/content/learning_sequences/api/processors/content_gating.py", line 35, in load_data
    self.required_content = milestones_helpers.get_required_content(self.course_key, self.user)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/milestones_helpers.py", line 244, in get_required_content
    raise InvalidUserException('Anonymous access is not allowed for course runs with milestones set.')
milestones.exceptions.InvalidUserException: ['Anonymous access is not allowed for course runs with milestones set.']
2022-10-31 11:57:04,052 ERROR 896 [django.request] [user None] [ip None] log.py:224 - Internal Server Error: /api/course_home/outline/course-v1:edX+DemoX+Demo_Course
Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib/python3.8/contextlib.py", line 75, in inner
    return func(*args, **kwds)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/course_home_api/outline/views.py", line 286, in get
    user_course_outline = get_user_course_outline(
  File "/usr/lib/python3.8/contextlib.py", line 75, in inner
    return func(*args, **kwds)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/content/learning_sequences/api/outlines.py", line 268, in get_user_course_outline
    user_course_outline, _ = _get_user_course_outline_and_processors(course_key, user, at_time)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/content/learning_sequences/api/outlines.py", line 343, in _get_user_course_outline_and_processors
    processor.load_data(full_course_outline)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/content/learning_sequences/api/processors/content_gating.py", line 35, in load_data
    self.required_content = milestones_helpers.get_required_content(self.course_key, self.user)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/milestones_helpers.py", line 244, in get_required_content
    raise InvalidUserException('Anonymous access is not allowed for course runs with milestones set.')
milestones.exceptions.InvalidUserException: ['Anonymous access is not allowed for course runs with milestones set.']
[31/Oct/2022 11:57:04] "GET /api/course_home/outline/course-v1:edX+DemoX+Demo_Course HTTP/1.1" 500 414410

@throwaway-a
Copy link

Just a FYI that I'm hoping to see this in the post-Olive release, as I used to have some public access courses, and I had to take them down when I upgraded to Nutmeg due to this bug.

@asadali145
Copy link

@throwaway-a Original issue is fixed and is released in Olive, You can see my comment above for more details.

@ormsbee ormsbee moved this from In Progress to Done in Axim Engineering Tasks Apr 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Report of or fix for something that isn't working as intended
Projects
Status: Done
Development

No branches or pull requests

4 participants