diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/xblock.py b/cms/djangoapps/contentstore/rest_api/v1/views/xblock.py index 025f2c4c4ca9..d00b37c10a2d 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/xblock.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/xblock.py @@ -8,6 +8,13 @@ * ADR 0026 - explicit authentication_classes + permission_classes * ADR 0028 - consolidated into XblockViewSet via DefaultRouter * ADR 0029 - standardized error envelope via StandardizedErrorMixin + * ADR 0034 - already compliant. ``authentication_classes`` is + ``(JwtAuthentication, SessionAuthenticationAllowInactiveUser)`` — no + ``BearerAuthentication`` / ``OAuth2Authentication`` to remove. This view + is set explicitly (rather than relying on platform defaults) because it + needs ``SessionAuthenticationAllowInactiveUser`` instead of the default + ``SessionAuthentication`` so inactive Studio authors can still hit the + endpoint while their session is being verified. * ADR 0036 - minimal/flattened views. ``retrieve`` accepts a ``?view=minimal`` query parameter that strips the (tree-shaped) xblock response to a small set of structural fields. The full xblock response is kept as the default diff --git a/cms/djangoapps/contentstore/rest_api/v3/views/authoring_grading.py b/cms/djangoapps/contentstore/rest_api/v3/views/authoring_grading.py index 72a4039c9ff3..e92272e6f8bd 100644 --- a/cms/djangoapps/contentstore/rest_api/v3/views/authoring_grading.py +++ b/cms/djangoapps/contentstore/rest_api/v3/views/authoring_grading.py @@ -30,6 +30,13 @@ real-world payload is always small. A hard cap is enforced upstream of this endpoint by :func:`CourseGradingModel.update_from_json`; we surface that as a documentation note rather than re-implement the bound here. + * ADR 0034 – auth standardization (OEP-0042). + ``authentication_classes`` is ``(JwtAuthentication, SessionAuthenticationAllowInactiveUser)``; + ``BearerAuthenticationAllowInactiveUser`` has been removed per the + deprecation policy. ``SessionAuthenticationAllowInactiveUser`` is + retained (rather than relying on the platform-default + ``SessionAuthentication``) so Studio authors whose accounts are + temporarily inactive can still update grading. Permission model note: PR #38363 proposed a class-level ``HasStudioReadAccess`` permission. The @@ -63,7 +70,6 @@ from openedx.core.djangoapps.authz.constants import LegacyAuthoringPermission from openedx.core.djangoapps.authz.decorators import user_has_course_permission from openedx.core.djangoapps.credit.tasks import update_credit_course_requirements -from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser from openedx.core.lib.api.mixins import StandardizedErrorMixin _COURSE_KEY_PARAMETER = OpenApiParameter( @@ -87,9 +93,12 @@ class AuthoringGradingViewSet(StandardizedErrorMixin, viewsets.ViewSet): Supersedes ``AuthoringGradingView`` at ``POST /api/contentstore/v0/grading/{course_id}``. """ + # ADR 0034 — JWT + session-with-inactive-user (BearerAuthenticationAllowInactiveUser + # removed per OEP-0042). SessionAuthenticationAllowInactiveUser is retained + # (instead of relying on the platform-default SessionAuthentication) so Studio + # authors whose accounts are temporarily inactive can still update grading. authentication_classes = ( JwtAuthentication, - BearerAuthenticationAllowInactiveUser, SessionAuthenticationAllowInactiveUser, ) permission_classes = (IsAuthenticated,) diff --git a/cms/djangoapps/contentstore/rest_api/v3/views/course_details.py b/cms/djangoapps/contentstore/rest_api/v3/views/course_details.py index 79a1f0ed1cba..ae31a1f7d0e1 100644 --- a/cms/djangoapps/contentstore/rest_api/v3/views/course_details.py +++ b/cms/djangoapps/contentstore/rest_api/v3/views/course_details.py @@ -12,6 +12,12 @@ * ADR 0029 – standardized error envelope via :class:`StandardizedErrorMixin` (v3-scoped — does not change the project-wide DRF ``EXCEPTION_HANDLER`` setting) + * ADR 0034 – already compliant. ``authentication_classes`` is + ``(JwtAuthentication, SessionAuthenticationAllowInactiveUser)`` — no + ``BearerAuthentication`` / ``OAuth2Authentication`` to remove. + Explicit declaration kept (rather than relying on platform defaults) + so that ``SessionAuthenticationAllowInactiveUser`` is used instead of + the default ``SessionAuthentication``. Permission model note: PR #38365 proposed a class-level ``HasStudioReadAccess`` permission. The diff --git a/cms/djangoapps/contentstore/rest_api/v3/views/home.py b/cms/djangoapps/contentstore/rest_api/v3/views/home.py index de5158c17e58..fcf09a0e617f 100644 --- a/cms/djangoapps/contentstore/rest_api/v3/views/home.py +++ b/cms/djangoapps/contentstore/rest_api/v3/views/home.py @@ -18,6 +18,12 @@ explicitly. The flat-list ``courses`` and ``libraries`` actions are out of scope (single-key dict around a list) and do not honour ``?fields=``. + * ADR 0034 – already compliant. ``authentication_classes`` is + ``(JwtAuthentication, SessionAuthenticationAllowInactiveUser)`` — + no ``BearerAuthentication`` / ``OAuth2Authentication`` to remove. + The explicit declaration is kept (rather than relying on platform + defaults) so that ``SessionAuthenticationAllowInactiveUser`` is used + instead of the default ``SessionAuthentication``. """ import edx_api_doc_tools as apidocs diff --git a/cms/djangoapps/contentstore/rest_api/v4/views/home.py b/cms/djangoapps/contentstore/rest_api/v4/views/home.py index 28fab47b55c0..7617cd6bd850 100644 --- a/cms/djangoapps/contentstore/rest_api/v4/views/home.py +++ b/cms/djangoapps/contentstore/rest_api/v4/views/home.py @@ -128,6 +128,11 @@ class HomeCoursesViewSet(StandardizedErrorMixin, viewsets.ViewSet): a dynamic-fields serializer mixin and per-field schema documentation) but is intentionally NOT added here to keep the v4 contract stable for the existing Studio frontend. + - 0034: already compliant. ``authentication_classes`` is + ``(JwtAuthentication, SessionAuthenticationAllowInactiveUser)`` — no + ``BearerAuthentication`` / ``OAuth2Authentication`` to remove. + Explicit declaration kept so ``SessionAuthenticationAllowInactiveUser`` + is used instead of the default ``SessionAuthentication``. """ authentication_classes = (JwtAuthentication, SessionAuthenticationAllowInactiveUser) diff --git a/openedx/core/djangoapps/enrollments/v2/views.py b/openedx/core/djangoapps/enrollments/v2/views.py index 905452f1d32c..67af3006a025 100644 --- a/openedx/core/djangoapps/enrollments/v2/views.py +++ b/openedx/core/djangoapps/enrollments/v2/views.py @@ -6,6 +6,13 @@ * ADR 0025 – ``serializer_class`` on every viewset/view * ADR 0026 – explicit ``authentication_classes`` + ``permission_classes`` + * ADR 0034 – auth standardization (OEP-0042). All four v2 viewsets/views use + ``(JwtAuthentication, EnrollmentCrossDomainSessionAuth)``; + ``BearerAuthenticationAllowInactiveUser`` has been removed per the + deprecation policy. ``EnrollmentCrossDomainSessionAuth`` is retained + (rather than relying on the platform-default ``SessionAuthentication``) + because these endpoints must accept cross-domain Studio/LMS CSRF-validated + session cookies. * ADR 0027 – ``drf_spectacular`` for OpenAPI schema generation * ADR 0028 – consolidated into ``ViewSet`` classes registered via ``DefaultRouter`` where the URL shape allows it @@ -70,7 +77,6 @@ EnrollmentUserThrottle, ) from openedx.core.djangoapps.user_api.accounts.permissions import CanRetireUser -from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser from openedx.core.lib.api.mixins import StandardizedErrorMixin from openedx.core.lib.api.permissions import ApiKeyHeaderPermissionIsAuthenticated @@ -209,9 +215,12 @@ class EnrollmentViewSet(StandardizedErrorMixin, viewsets.ViewSet, ApiKeyPermissi DELETE /api/enrollment/v2/enrollment/enrollment_allowed/ → allowed (DELETE) """ + # ADR 0034 — JWT + cross-domain session (BearerAuthenticationAllowInactiveUser + # removed per OEP-0042). EnrollmentCrossDomainSessionAuth retained because the + # endpoint must accept cross-domain Studio/LMS CSRF-validated session cookies; + # the platform-default SessionAuthentication would reject those. authentication_classes = ( JwtAuthentication, - BearerAuthenticationAllowInactiveUser, EnrollmentCrossDomainSessionAuth, ) permission_classes = (ApiKeyHeaderPermissionIsAuthenticated,) @@ -417,9 +426,12 @@ def allowed(self, request): class EnrollmentRetrieveView(StandardizedErrorMixin, ApiKeyPermissionMixIn, APIView): """GET enrollment for a course (and optionally a named user).""" + # ADR 0034 — JWT + cross-domain session (BearerAuthenticationAllowInactiveUser + # removed per OEP-0042). EnrollmentCrossDomainSessionAuth retained because the + # endpoint must accept cross-domain Studio/LMS CSRF-validated session cookies; + # the platform-default SessionAuthentication would reject those. authentication_classes = ( JwtAuthentication, - BearerAuthenticationAllowInactiveUser, EnrollmentCrossDomainSessionAuth, ) permission_classes = (ApiKeyHeaderPermissionIsAuthenticated,) @@ -492,9 +504,12 @@ def get(self, request, course_id=None, username=None): class UserRolesView(StandardizedErrorMixin, APIView): """List the current user's course-level roles.""" + # ADR 0034 — JWT + cross-domain session (BearerAuthenticationAllowInactiveUser + # removed per OEP-0042). EnrollmentCrossDomainSessionAuth retained because the + # endpoint must accept cross-domain Studio/LMS CSRF-validated session cookies; + # the platform-default SessionAuthentication would reject those. authentication_classes = ( JwtAuthentication, - BearerAuthenticationAllowInactiveUser, EnrollmentCrossDomainSessionAuth, ) permission_classes = (ApiKeyHeaderPermissionIsAuthenticated,) @@ -644,9 +659,12 @@ def get(self, request, course_id=None): class EnrollmentsAdminListView(StandardizedErrorMixin, ListAPIView): """Admin-only paginated enrollment list with OEP-68 filter aliases.""" + # ADR 0034 — JWT + cross-domain session (BearerAuthenticationAllowInactiveUser + # removed per OEP-0042). EnrollmentCrossDomainSessionAuth retained because the + # endpoint must accept cross-domain Studio/LMS CSRF-validated session cookies; + # the platform-default SessionAuthentication would reject those. authentication_classes = ( JwtAuthentication, - BearerAuthenticationAllowInactiveUser, EnrollmentCrossDomainSessionAuth, ) permission_classes = (permissions.IsAdminUser,)