From 903da3fbd2eaaf90812549729d7c3d721d10a839 Mon Sep 17 00:00:00 2001 From: Shadi Naif Date: Thu, 21 Nov 2024 09:36:53 +0300 Subject: [PATCH] feat: allow oauth2 on all views --- futurex_openedx_extensions/__init__.py | 2 +- futurex_openedx_extensions/dashboard/views.py | 21 ++++++++++++++++--- .../helpers/constants.py | 5 +++++ .../edx_platform_mocks/fake_models/classes.py | 7 +++++++ .../openedx/core/lib/api/authentication.py | 2 ++ 5 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 test_utils/edx_platform_mocks/openedx/core/lib/api/authentication.py diff --git a/futurex_openedx_extensions/__init__.py b/futurex_openedx_extensions/__init__.py index 6378bdfb..0caf951e 100644 --- a/futurex_openedx_extensions/__init__.py +++ b/futurex_openedx_extensions/__init__.py @@ -1,3 +1,3 @@ """One-line description for README and other doc files.""" -__version__ = '0.9.14' +__version__ = '0.9.15' diff --git a/futurex_openedx_extensions/dashboard/views.py b/futurex_openedx_extensions/dashboard/views.py index eb5c6f15..c5d69599 100644 --- a/futurex_openedx_extensions/dashboard/views.py +++ b/futurex_openedx_extensions/dashboard/views.py @@ -43,6 +43,7 @@ COURSE_ACCESS_ROLES_SUPPORTED_READ, COURSE_STATUS_SELF_PREFIX, COURSE_STATUSES, + FX_VIEW_DEFAULT_AUTH_CLASSES, ) from futurex_openedx_extensions.helpers.converters import error_details_to_dictionary from futurex_openedx_extensions.helpers.exceptions import FXCodedException, FXExceptionCodes @@ -69,6 +70,8 @@ from futurex_openedx_extensions.helpers.tenants import get_tenants_info from futurex_openedx_extensions.helpers.users import get_user_by_key +default_auth_classes = FX_VIEW_DEFAULT_AUTH_CLASSES.copy() + class TotalCountsView(APIView, FXViewRoleInfoMixin): """ @@ -91,6 +94,7 @@ class TotalCountsView(APIView, FXViewRoleInfoMixin): STAT_LEARNERS: 'learners_count', } + authentication_classes = default_auth_classes permission_classes = [FXHasTenantCourseAccess] fx_view_name = 'total_counts_statistics' fx_default_read_only_roles = ['staff', 'instructor', 'data_researcher', 'org_course_creator_group'] @@ -182,8 +186,9 @@ def get(self, request: Any, *args: Any, **kwargs: Any) -> Response | JsonRespons class LearnersView(ListAPIView, FXViewRoleInfoMixin): """View to get the list of learners""" - serializer_class = serializers.LearnerDetailsSerializer + authentication_classes = default_auth_classes permission_classes = [FXHasTenantCourseAccess] + serializer_class = serializers.LearnerDetailsSerializer pagination_class = DefaultPagination fx_view_name = 'learners_list' fx_default_read_only_roles = ['staff', 'instructor', 'data_researcher', 'org_course_creator_group'] @@ -203,8 +208,9 @@ def get_queryset(self) -> QuerySet: class CoursesView(ListAPIView, FXViewRoleInfoMixin): """View to get the list of courses""" - serializer_class = serializers.CourseDetailsSerializer + authentication_classes = default_auth_classes permission_classes = [FXHasTenantCourseAccess] + serializer_class = serializers.CourseDetailsSerializer pagination_class = DefaultPagination filter_backends = [DefaultOrderingFilter] ordering_fields = [ @@ -231,6 +237,7 @@ def get_queryset(self) -> QuerySet: class CourseStatusesView(APIView, FXViewRoleInfoMixin): """View to get the course statuses""" + authentication_classes = default_auth_classes permission_classes = [FXHasTenantCourseAccess] fx_view_name = 'course_statuses' fx_default_read_only_roles = ['staff', 'instructor', 'data_researcher', 'org_course_creator_group'] @@ -264,6 +271,7 @@ def get(self, request: Any, *args: Any, **kwargs: Any) -> JsonResponse: class LearnerInfoView(APIView, FXViewRoleInfoMixin): """View to get the information of a learner""" + authentication_classes = default_auth_classes permission_classes = [FXHasTenantCourseAccess] fx_view_name = 'learner_detailed_info' fx_default_read_only_roles = ['staff', 'instructor', 'data_researcher', 'org_course_creator_group'] @@ -298,8 +306,9 @@ def get(self, request: Any, username: str, *args: Any, **kwargs: Any) -> JsonRes class DataExportManagementView(viewsets.ModelViewSet, FXViewRoleInfoMixin): # pylint: disable=too-many-ancestors """View to list and retrieve data export tasks.""" - serializer_class = serializers.DataExportTaskSerializer + authentication_classes = default_auth_classes permission_classes = [FXHasTenantCourseAccess] + serializer_class = serializers.DataExportTaskSerializer pagination_class = DefaultPagination fx_view_name = 'exported_files_data' fx_default_read_only_roles = ['staff', 'instructor', 'data_researcher', 'org_course_creator_group'] @@ -328,6 +337,7 @@ def get_object(self) -> DataExportTask: class LearnerCoursesView(APIView, FXViewRoleInfoMixin): """View to get the list of courses for a learner""" + authentication_classes = default_auth_classes permission_classes = [FXHasTenantCourseAccess] pagination_class = DefaultPagination fx_view_name = 'learner_courses' @@ -399,6 +409,7 @@ def get(self, request: Any, *args: Any, **kwargs: Any) -> JsonResponse: # pylin class LearnersDetailsForCourseView(ExportCSVMixin, ListAPIView, FXViewRoleInfoMixin): """View to get the list of learners for a course""" + authentication_classes = default_auth_classes serializer_class = serializers.LearnerDetailsForCourseSerializer permission_classes = [FXHasTenantCourseAccess] pagination_class = DefaultPagination @@ -467,6 +478,7 @@ def get_serializer_context(self) -> Dict[str, Any]: class GlobalRatingView(APIView, FXViewRoleInfoMixin): """View to get the global rating""" + authentication_classes = default_auth_classes permission_classes = [FXHasTenantCourseAccess] fx_view_name = 'global_rating' fx_default_read_only_roles = ['staff', 'instructor', 'data_researcher', 'org_course_creator_group'] @@ -494,6 +506,7 @@ def get(self, request: Any, *args: Any, **kwargs: Any) -> JsonResponse: class UserRolesManagementView(viewsets.ModelViewSet, FXViewRoleInfoMixin): # pylint: disable=too-many-ancestors """View to get the user roles""" + authentication_classes = default_auth_classes permission_classes = [FXHasTenantAllCoursesAccess] fx_view_name = 'user_roles' fx_default_read_only_roles = ['org_course_creator_group'] @@ -656,6 +669,7 @@ def destroy(self, request: Any, *args: Any, **kwargs: Any) -> Response: class MyRolesView(APIView, FXViewRoleInfoMixin): """View to get the user roles of the caller""" + authentication_classes = default_auth_classes permission_classes = [FXHasTenantCourseAccess] fx_view_name = 'my_roles' fx_default_read_only_roles = COURSE_ACCESS_ROLES_SUPPORTED_READ.copy() @@ -672,6 +686,7 @@ def get(self, request: Any, *args: Any, **kwargs: Any) -> JsonResponse: class ClickhouseQueryView(APIView, FXViewRoleInfoMixin): """View to get the Clickhouse query""" + authentication_classes = default_auth_classes permission_classes = [FXHasTenantCourseAccess] fx_view_name = 'clickhouse_query_fetcher' fx_default_read_only_roles = ['staff', 'instructor', 'data_researcher', 'org_course_creator_group'] diff --git a/futurex_openedx_extensions/helpers/constants.py b/futurex_openedx_extensions/helpers/constants.py index f211b952..453b0606 100644 --- a/futurex_openedx_extensions/helpers/constants.py +++ b/futurex_openedx_extensions/helpers/constants.py @@ -1,4 +1,7 @@ """Constants for the FutureX Open edX Extensions app.""" +from openedx.core.lib.api.authentication import BearerAuthentication +from rest_framework.authentication import SessionAuthentication + CACHE_NAME_ALL_COURSE_ORG_FILTER_LIST = 'fx_course_org_filter_list' CACHE_NAME_ALL_TENANTS_INFO = 'fx_tenants_info' CACHE_NAME_ALL_VIEW_ROLES = 'fx_view_roles' @@ -112,3 +115,5 @@ USER_KEY_TYPE_NOT_ID = 'username/email' CSV_TASK_LIMIT_PER_USER = 3 + +FX_VIEW_DEFAULT_AUTH_CLASSES = [SessionAuthentication, BearerAuthentication] diff --git a/test_utils/edx_platform_mocks/fake_models/classes.py b/test_utils/edx_platform_mocks/fake_models/classes.py index 97b5f4c5..11aff24c 100644 --- a/test_utils/edx_platform_mocks/fake_models/classes.py +++ b/test_utils/edx_platform_mocks/fake_models/classes.py @@ -16,3 +16,10 @@ class OrgRole(RoleBase): # pylint: disable=too-few-public-methods REGISTERED_ACCESS_ROLES = {} + + +class BearerAuthentication: # pylint: disable=too-few-public-methods + """Mock""" + def authenticate(self, request): # pylint: disable=no-self-use + """Mock""" + return None diff --git a/test_utils/edx_platform_mocks/openedx/core/lib/api/authentication.py b/test_utils/edx_platform_mocks/openedx/core/lib/api/authentication.py new file mode 100644 index 00000000..24abc20e --- /dev/null +++ b/test_utils/edx_platform_mocks/openedx/core/lib/api/authentication.py @@ -0,0 +1,2 @@ +"""edx-platform Mocks""" +from fake_models.classes import BearerAuthentication # pylint: disable=unused-import