From 0530332b4e076d5a6bc477569662b1dbc2800740 Mon Sep 17 00:00:00 2001 From: mohsentaba Date: Sun, 4 Jan 2026 15:37:55 +0330 Subject: [PATCH] TokenAuthentication added to sensitive views. --- apps/account/views/location_history.py | 2 + apps/account/views/notification.py | 3 ++ apps/account/views/user.py | 7 ++- apps/article/views.py | 5 +++ apps/bookmark/views/bookmark.py | 6 ++- apps/bookmark/views/rate.py | 4 ++ apps/certificate/views.py | 3 ++ apps/course/views/course.py | 6 ++- apps/course/views/lesson.py | 3 ++ apps/course/views/live_session.py | 4 ++ apps/podcast/views.py | 7 +++ apps/quiz/views/participant.py | 2 + apps/quiz/views/quiz.py | 2 + apps/transaction/views.py | 6 +++ apps/video/views.py | 6 +++ utils/admin.py | 59 -------------------------- 16 files changed, 62 insertions(+), 63 deletions(-) diff --git a/apps/account/views/location_history.py b/apps/account/views/location_history.py index e997649..d9db9aa 100644 --- a/apps/account/views/location_history.py +++ b/apps/account/views/location_history.py @@ -4,6 +4,7 @@ import re from pathlib import Path from rest_framework.mixins import CreateModelMixin from rest_framework.permissions import IsAuthenticated +from rest_framework.authentication import TokenAuthentication from rest_framework.generics import GenericAPIView from rest_framework.response import Response from rest_framework.views import APIView @@ -18,6 +19,7 @@ from drf_yasg import openapi class LocationHistoryView(GenericAPIView, CreateModelMixin): permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] serializer_class = LocationHistorySerializer def post(self, request, *args, **kwargs): diff --git a/apps/account/views/notification.py b/apps/account/views/notification.py index ab3c27f..632177b 100644 --- a/apps/account/views/notification.py +++ b/apps/account/views/notification.py @@ -1,5 +1,6 @@ from rest_framework import generics, status from rest_framework.response import Response +from rest_framework.authentication import TokenAuthentication from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi from rest_framework.permissions import IsAuthenticated @@ -14,6 +15,7 @@ class NotificationListView(generics.ListAPIView): queryset = Notification.objects.all() serializer_class = NotificationSerializer permission_classes = [IsAuthenticated,] + authentication_classes = [TokenAuthentication] pagination_class = StandardResultsSetPagination @swagger_auto_schema( @@ -58,6 +60,7 @@ class NotificationListView(generics.ListAPIView): class NotificationReadAllView(generics.GenericAPIView): permission_classes = [IsAuthenticated,] + authentication_classes = [TokenAuthentication] queryset = Notification.objects.all() diff --git a/apps/account/views/user.py b/apps/account/views/user.py index 8a03ec3..62ff007 100644 --- a/apps/account/views/user.py +++ b/apps/account/views/user.py @@ -424,6 +424,7 @@ class UserLoginView(CreateAPIView): class UserProfileView(RetrieveAPIView): serializer_class = UserProfileSerializer permission_classes = [IsAuthenticated, IsActiveUser] + authentication_classes = [TokenAuthentication] queryset = User.objects.all() def get(self, request, *args, **kwargs): @@ -436,6 +437,7 @@ class UserProfileView(RetrieveAPIView): class UserUpdateView(UpdateAPIView): permission_classes = [IsAuthenticated, IsActiveUser] + authentication_classes = [TokenAuthentication] serializer_class = UserProfileSerializer def put(self, request, *args, **kwargs): @@ -480,9 +482,10 @@ class UserRecoverPassword(CreateAPIView): ) -class UserResetPassword(CreateAPIView): +class UserResetPassword(CreateAPIView): serializer_class = UserResetPasswordSerializer permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_description=doc_reset(), @@ -508,6 +511,7 @@ class UserResetPassword(CreateAPIView): class UserDeleteView(APIView): permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] def delete(self, request, *args, **kwargs): try: @@ -528,6 +532,7 @@ class UserDeleteView(APIView): class UpdateFCMView(GenericAPIView): permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] serializer_class = UserFCMSerializer def post(self, request, *args, **kwargs): diff --git a/apps/article/views.py b/apps/article/views.py index bc8bc05..835107c 100755 --- a/apps/article/views.py +++ b/apps/article/views.py @@ -1,5 +1,6 @@ from rest_framework import generics, status from rest_framework.response import Response +from rest_framework.authentication import TokenAuthentication from drf_yasg import openapi from drf_yasg.utils import swagger_auto_schema from apps.library.pagination import NoPagination @@ -35,6 +36,7 @@ class ArticleCategoryListAPIView(generics.ListAPIView): class PinnedArticleCollectionListView(generics.ListAPIView): serializer_class = PinnedArticleCollectionSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] pagination_class = NoPagination @@ -82,6 +84,7 @@ class PinnedArticleCollectionListView(generics.ListAPIView): class MiddleArticleCollectionListView(generics.ListAPIView): serializer_class = MiddleArticleCollectionSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] pagination_class = NoPagination @swagger_auto_schema( @@ -108,6 +111,7 @@ class MiddleArticleCollectionListView(generics.ListAPIView): class ArticleListAPIView(generics.ListAPIView): serializer_class = ArticleListSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] pagination_class = StandardResultsSetPagination @swagger_auto_schema( @@ -215,6 +219,7 @@ class ArticleListAPIView(generics.ListAPIView): class ArticleDetailAPIView(generics.RetrieveAPIView): serializer_class = ArticleDetailSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] lookup_field = 'slug' @swagger_auto_schema( diff --git a/apps/bookmark/views/bookmark.py b/apps/bookmark/views/bookmark.py index 592793c..8181f23 100644 --- a/apps/bookmark/views/bookmark.py +++ b/apps/bookmark/views/bookmark.py @@ -2,6 +2,7 @@ from rest_framework import status from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated +from rest_framework.authentication import TokenAuthentication from rest_framework.generics import CreateAPIView, DestroyAPIView from rest_framework.exceptions import ValidationError from drf_yasg.utils import swagger_auto_schema @@ -17,6 +18,7 @@ class AddBookmarkView(CreateAPIView): If the bookmark already exists but is inactive, it will be reactivated. """ permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] serializer_class = BookmarkSerializer @swagger_auto_schema( @@ -73,10 +75,11 @@ class AddBookmarkView(CreateAPIView): class RemoveBookmarkView(DestroyAPIView): """ Deactivate a bookmark by setting its status to False using content_id and user. - + The request should specify the content_id of the bookmark to be deactivated. """ permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] serializer_class = BookmarkSerializer @swagger_auto_schema( @@ -129,6 +132,7 @@ class BookmarkStatusView(APIView): Return the count of bookmarks for each service for the current user. """ permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_description="Return the count of bookmarks for each service for the current user.", diff --git a/apps/bookmark/views/rate.py b/apps/bookmark/views/rate.py index 2e691b2..281d446 100644 --- a/apps/bookmark/views/rate.py +++ b/apps/bookmark/views/rate.py @@ -2,6 +2,7 @@ from rest_framework import status from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated +from rest_framework.authentication import TokenAuthentication from apps.bookmark.models import Rate from apps.bookmark.serializers import RateSerializer, RateStatusSerializer, AverageRateSerializer from drf_yasg import openapi @@ -12,6 +13,7 @@ class AddRateView(APIView): API view for adding or updating a rate. """ permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_description="Add or update a rate for a content.", @@ -37,6 +39,7 @@ class RemoveRateView(APIView): API view for removing a rate. """ permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_description="Remove a rate by setting its status to False.", @@ -76,6 +79,7 @@ class RateStatusView(APIView): API view for checking if a user has rated a content and getting the rate value. """ permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_description="Check if a user has rated a content and get the rate value.", diff --git a/apps/certificate/views.py b/apps/certificate/views.py index 35f0cb9..589c6ef 100644 --- a/apps/certificate/views.py +++ b/apps/certificate/views.py @@ -1,4 +1,5 @@ from rest_framework import generics, permissions +from rest_framework.authentication import TokenAuthentication from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi @@ -12,6 +13,7 @@ class CertificateRequestView(generics.CreateAPIView): queryset = Certificate.objects.all() serializer_class = CertificateRequestSerializer permission_classes = [permissions.IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_description="Request a certificate for completed course", @@ -33,6 +35,7 @@ class CertificateRequestView(generics.CreateAPIView): class UserCertificatesListView(generics.ListAPIView): serializer_class = CertificateSerializer permission_classes = [permissions.IsAuthenticated] + authentication_classes = [TokenAuthentication] pagination_class = StandardResultsSetPagination @swagger_auto_schema( diff --git a/apps/course/views/course.py b/apps/course/views/course.py index 6804c69..7f8cff2 100644 --- a/apps/course/views/course.py +++ b/apps/course/views/course.py @@ -185,11 +185,12 @@ class CourseDetailAPIView(RetrieveAPIView): def get(self, request, *args, **kwargs): return super().get(request, *args, **kwargs) - +from rest_framework.authentication import TokenAuthentication class MyCourseListAPIView(ListAPIView): serializer_class = MyCourseListSerializer permission_classes = [IsAuthenticated] - pagination_class = StandardResultsSetPagination + pagination_class = StandardResultsSetPagination + authentication_classes = [TokenAuthentication] @swagger_auto_schema(manual_parameters=[ openapi.Parameter( @@ -351,6 +352,7 @@ class GlossaryListAPIView(ListAPIView): class CourseOnlineClassTokenAPIView(GenericAPIView): permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] serializer_class = OnlineClassTokenCreateSerializer @swagger_auto_schema( diff --git a/apps/course/views/lesson.py b/apps/course/views/lesson.py index 16e99d7..18dbb48 100644 --- a/apps/course/views/lesson.py +++ b/apps/course/views/lesson.py @@ -1,4 +1,6 @@ from rest_framework.generics import ListAPIView, RetrieveAPIView, GenericAPIView +from rest_framework.permissions import IsAuthenticated +from rest_framework.authentication import TokenAuthentication from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi @@ -109,6 +111,7 @@ class LessonDetailView(RetrieveAPIView): class LessonCompletionToggleAPIView(GenericAPIView): permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_description="Toggle lesson completion status (Check/Uncheck)", diff --git a/apps/course/views/live_session.py b/apps/course/views/live_session.py index 2ea2a11..c433226 100644 --- a/apps/course/views/live_session.py +++ b/apps/course/views/live_session.py @@ -7,6 +7,7 @@ from django.utils import timezone from rest_framework import status from rest_framework.generics import GenericAPIView from rest_framework.permissions import IsAuthenticated +from rest_framework.authentication import TokenAuthentication from rest_framework.response import Response from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi @@ -21,6 +22,7 @@ logger = logging.getLogger(__name__) class CourseLiveSessionRoomCreateAPIView(GenericAPIView): permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] serializer_class = LiveSessionRoomCreateSerializer @swagger_auto_schema( @@ -190,6 +192,7 @@ class CourseLiveSessionRoomCreateAPIView(GenericAPIView): class CourseLiveSessionTokenAPIView(GenericAPIView): permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] serializer_class = LiveSessionTokenSerializer @swagger_auto_schema( @@ -308,6 +311,7 @@ class CourseLiveSessionTokenAPIView(GenericAPIView): class CourseLiveSessionRecordedFileAPIView(GenericAPIView): permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] serializer_class = LiveSessionRecordingSerializer @swagger_auto_schema( diff --git a/apps/podcast/views.py b/apps/podcast/views.py index 26e81ad..1f65da8 100644 --- a/apps/podcast/views.py +++ b/apps/podcast/views.py @@ -1,5 +1,6 @@ from rest_framework import generics, status from rest_framework.response import Response +from rest_framework.authentication import TokenAuthentication from drf_yasg import openapi from drf_yasg.utils import swagger_auto_schema from apps.library.pagination import NoPagination @@ -40,6 +41,7 @@ class PodcastCategoryListAPIView(generics.ListAPIView): class PinnedPodcastCollectionListView(generics.ListAPIView): serializer_class = PinnedPodcastCollectionSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] pagination_class = NoPagination @swagger_auto_schema( @@ -89,6 +91,7 @@ class PinnedPodcastCollectionListView(generics.ListAPIView): class MiddlePodcastCollectionListView(generics.ListAPIView): serializer_class = MiddlePodcastCollectionSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] pagination_class = NoPagination @swagger_auto_schema( @@ -117,6 +120,7 @@ class PodcastListAPIView(generics.ListAPIView): """ serializer_class = PodcastPlaylistListSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] pagination_class = StandardResultsSetPagination @swagger_auto_schema( @@ -226,6 +230,7 @@ class PodcastDetailAPIView(generics.RetrieveAPIView): serializer_class = PodcastPlaylistDetailSerializer lookup_field = 'slug' permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_description="Get podcast playlist details by slug", @@ -256,6 +261,7 @@ class UserPlaylistListAPIView(generics.ListAPIView): """ serializer_class = PodcastListSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] pagination_class = StandardResultsSetPagination @swagger_auto_schema( @@ -290,6 +296,7 @@ class UserPlaylistCreateAPIView(generics.CreateAPIView): """ serializer_class = UserPlaylistCreateSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_description="Add or update a podcast in the user's personal playlist", diff --git a/apps/quiz/views/participant.py b/apps/quiz/views/participant.py index dbe6bc3..c4d89c4 100644 --- a/apps/quiz/views/participant.py +++ b/apps/quiz/views/participant.py @@ -1,6 +1,7 @@ from django.db.models import Value from rest_framework.generics import RetrieveAPIView, CreateAPIView from rest_framework.permissions import IsAuthenticated +from rest_framework.authentication import TokenAuthentication from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi @@ -13,6 +14,7 @@ from apps.quiz.doc import * class QuizParticipantCreateAPIView(CreateAPIView): serializer_class = QuizParticipantSerializer permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( diff --git a/apps/quiz/views/quiz.py b/apps/quiz/views/quiz.py index 5dd8a00..49a6fa3 100644 --- a/apps/quiz/views/quiz.py +++ b/apps/quiz/views/quiz.py @@ -1,6 +1,7 @@ from django.db.models import Value from rest_framework.generics import RetrieveAPIView from rest_framework.permissions import IsAuthenticated +from rest_framework.authentication import TokenAuthentication from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi @@ -13,6 +14,7 @@ from apps.quiz.doc import * class QuizDetailAPIView(RetrieveAPIView): serializer_class = QuizSerializer permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( diff --git a/apps/transaction/views.py b/apps/transaction/views.py index b2404d3..adde1d1 100644 --- a/apps/transaction/views.py +++ b/apps/transaction/views.py @@ -2,6 +2,7 @@ from rest_framework import generics, status from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView +from rest_framework.authentication import TokenAuthentication from apps.course.models import Participant, Course from apps.transaction.models import TransactionParticipant, TransactionReceipt from apps.transaction.serializers import ( @@ -30,6 +31,7 @@ class TransactionParticipantCreateView(generics.CreateAPIView): queryset = TransactionParticipant.objects.all() serializer_class = TransactionParticipantSerializer permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_description=doc_create_transaction(), @@ -209,6 +211,7 @@ class TransactiontListView(generics.ListAPIView): queryset = TransactionParticipant.objects.all() serializer_class = TransactionListSerializer permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] pagination_class = StandardResultsSetPagination @swagger_auto_schema( @@ -226,6 +229,7 @@ class TransactiontListView(generics.ListAPIView): class SoftDeleteTransactionParticipantView(APIView): permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_summary="Soft delete a transaction participant", @@ -276,6 +280,7 @@ class SoftDeleteTransactionParticipantView(APIView): class UploadTransactionReceiptsView(APIView): permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] @swagger_auto_schema( operation_summary="Upload payment receipts for a transaction", @@ -364,6 +369,7 @@ class UploadTransactionReceiptsView(APIView): class TransactionReceiptsListView(generics.ListAPIView): serializer_class = TransactionReceiptSerializer permission_classes = [IsAuthenticated] + authentication_classes = [TokenAuthentication] pagination_class = StandardResultsSetPagination @swagger_auto_schema( diff --git a/apps/video/views.py b/apps/video/views.py index 4dfdae2..3788463 100644 --- a/apps/video/views.py +++ b/apps/video/views.py @@ -1,5 +1,6 @@ from rest_framework import generics, status from rest_framework.response import Response +from rest_framework.authentication import TokenAuthentication from drf_yasg import openapi from drf_yasg.utils import swagger_auto_schema from apps.library.pagination import NoPagination @@ -44,6 +45,7 @@ class VideoCategoryListAPIView(generics.ListAPIView): class PinnedVideoCollectionListView(generics.ListAPIView): serializer_class = PinnedVideoCollectionSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] pagination_class = NoPagination @swagger_auto_schema( @@ -89,6 +91,7 @@ class PinnedVideoCollectionListView(generics.ListAPIView): class MiddleVideoCollectionListView(generics.ListAPIView): serializer_class = MiddleVideoCollectionSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] pagination_class = NoPagination @swagger_auto_schema( @@ -117,6 +120,7 @@ class VideoPlaylistListAPIView(generics.ListAPIView): """ serializer_class = VideoPlaylistListSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] pagination_class = StandardResultsSetPagination @swagger_auto_schema( @@ -216,6 +220,7 @@ class VideoPlaylistListAPIView(generics.ListAPIView): class VideoPlaylistDetailAPIView(generics.RetrieveAPIView): serializer_class = VideoPlaylistDetailSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] lookup_field = 'slug' @swagger_auto_schema( @@ -244,6 +249,7 @@ class VideoPlaylistDetailAPIView(generics.RetrieveAPIView): class VideoDetailAPIView(generics.RetrieveAPIView): serializer_class = VideoDetailSerializer permission_classes = (IsAuthenticated,) + authentication_classes = [TokenAuthentication] lookup_field = 'slug' @swagger_auto_schema( diff --git a/utils/admin.py b/utils/admin.py index 938aa95..84bc850 100644 --- a/utils/admin.py +++ b/utils/admin.py @@ -408,65 +408,6 @@ class LazyAdminSite(UnfoldAdminSite): project_admin_site = LazyAdminSite(FormulaAdminSite, 'imam_javad_admin') dovoodi_admin_site = LazyAdminSite(DovoodiAdminSite, 'dovoodi_admin') -# from django.contrib.admin.sites import AdminSite - -# class LazyAdminSite(AdminSite): -# """Lazy wrapper that initializes the real admin site on first access""" - -# def __init__(self, site_class, name): -# # Don't call super().__init__() - avoid app registry checks at import time -# self._site_class = site_class -# self._name = name -# self._instance = None - -# def _get_instance(self): -# """Initialize the real site on first access (after Django is ready)""" -# if self._instance is None: -# self._instance = self._site_class(name=self._name) -# return self._instance - -# def __getattr__(self, name): -# """Delegate all attribute access to the real instance""" -# if name.startswith('_'): -# raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'") -# return getattr(self._get_instance(), name) - -# @property -# def urls(self): -# """Required for Django URL routing""" -# return self._get_instance().urls - -# @property -# def media(self): -# """Expose the media from the real admin instance""" -# return self._get_instance().media - -# @property -# def form_class(self): -# """Expose form class""" -# return self._get_instance().form_class - -# def has_permission(self, request): -# """Check if user has admin permission""" -# return self._get_instance().has_permission(request) - -# def each_context(self, request): -# """Return context for admin templates""" -# return self._get_instance().each_context(request) - -# def get_urls(self): -# """Get admin URLs""" -# return self._get_instance().get_urls() - -# def register(self, model, admin_class=None, **options): -# """Register a model with the admin site""" -# return self._get_instance().register(model, admin_class, **options) - - -# # Create lazy instances (NO initialization at import time!) -# project_admin_site = LazyAdminSite(FormulaAdminSite, 'imam_javad_admin') -# dovoodi_admin_site = LazyAdminSite(DovoodiAdminSite, 'dovoodi_admin') - # Function to replace placeholders with real instances when Django is ready def replace_placeholders_with_real_sites(): global project_admin_site, dovoodi_admin_site