From 9139c0c03d13d5027b9b769d01c343ce56ac0967 Mon Sep 17 00:00:00 2001 From: mohsentaba Date: Tue, 7 Apr 2026 14:49:02 +0330 Subject: [PATCH] course visibility fixed enhanced course visibility logic to do not miss and show the participated users the course contexts --- apps/course/serializers/course.py | 42 +++++++++++++++++++++++++------ apps/course/serializers/lesson.py | 29 +++++++++++++-------- apps/course/views/course.py | 12 ++++++--- apps/transaction/signals.py | 2 +- 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/apps/course/serializers/course.py b/apps/course/serializers/course.py index 76237ff..3723ae3 100644 --- a/apps/course/serializers/course.py +++ b/apps/course/serializers/course.py @@ -211,10 +211,8 @@ class CourseDetailSerializer(serializers.ModelSerializer): def get_access(self, obj): - if student := self._get_authenticated_user(): - if not self._is_participant(student, obj): - return False - return True + if user := self._get_authenticated_user(): + return self._has_access(user, obj) return False def get_professor(self, obj): @@ -248,9 +246,29 @@ class CourseDetailSerializer(serializers.ModelSerializer): return min(completed_count, total_lessons) return None + def _has_access(self, user, course): + """ + Check if the user has access to the course content. + Access is granted if: + 1. User is the professor of the course. + 2. User is staff (admin). + 3. User is an active participant in the course. + """ + if user.is_staff or user.is_superuser: + return True + + if course.professor_id == user.id: + return True + + return Participant.objects.filter( + student_id=user.id, + course=course, + is_active=True + ).exists() + def _is_participant(self, student, course): - """Helper method to check if a student is a participant in the given course.""" - return Participant.objects.filter(student=student, course=course).exists() + """Deprecated: use _has_access instead. Kept for backward compatibility if needed.""" + return self._has_access(student, course) def _get_authenticated_user(self): """Helper method to retrieve the authenticated user from the context.""" @@ -349,11 +367,19 @@ class MyCourseListSerializer(serializers.ModelSerializer): def _is_participant(self, student, course): """Helper method to check if a student is a participant in the given course.""" + if student.is_staff or student.is_superuser: + return True + # اگر کاربر استاد دوره است، دسترسی کامل دارد - if course.professor == student: + if course.professor_id == student.id: return True + # در غیر این صورت چک می‌کنیم که آیا participant است یا خیر - return Participant.objects.filter(student=student, course=course).exists() + return Participant.objects.filter( + student_id=student.id, + course=course, + is_active=True + ).exists() def _get_authenticated_user(self): """Helper method to retrieve the authenticated user from the context.""" diff --git a/apps/course/serializers/lesson.py b/apps/course/serializers/lesson.py index dd8c972..0c39c63 100644 --- a/apps/course/serializers/lesson.py +++ b/apps/course/serializers/lesson.py @@ -23,20 +23,29 @@ class CourseLessonSerializer(serializers.ModelSerializer): fields = ['id', 'title', 'priority', 'is_active', 'permission', 'duration', 'content_type', 'content_file', 'video_link', 'is_complated', 'quizs'] def get_permission(self, obj): - if student := self._get_authenticated_user(): - if not self._is_participant(student, obj.course): - return False - return True + if user := self._get_authenticated_user(): + return self._has_access(user, obj.course) return False - def _get_authenticated_user(self): - """Helper method to retrieve the authenticated user from the context.""" - request = self.context.get('request') - return request.user if request and request.user.is_authenticated else None + def _has_access(self, user, course): + """ + Check if the user has access to the course content. + """ + if user.is_staff or user.is_superuser: + return True + + if course.professor_id == user.id: + return True + + return Participant.objects.filter( + student_id=user.id, + course=course, + is_active=True + ).exists() def _is_participant(self, student, course): - """Helper method to check if a student is a participant in the given course.""" - return Participant.objects.filter(student=student, course=course).exists() + """Deprecated: use _has_access instead.""" + return self._has_access(student, course) def get_is_complated(self, obj): request = self.context.get('request') diff --git a/apps/course/views/course.py b/apps/course/views/course.py index e036cff..8f5e993 100644 --- a/apps/course/views/course.py +++ b/apps/course/views/course.py @@ -731,11 +731,17 @@ class CourseOnlineClassTokenValidateAPIView(GenericAPIView): @staticmethod def _user_can_join_live_session(user, course: Course) -> bool: - if not user: + if not user or not user.is_authenticated: return False - if user.can_manage_course(course): + + if user.is_staff or user.is_superuser or user.can_manage_course(course): return True - return Participant.objects.filter(course=course, student_id=user.id, is_active=True).exists() + + return Participant.objects.filter( + course=course, + student_id=user.id, + is_active=True + ).exists() @staticmethod def _format_datetime(value): diff --git a/apps/transaction/signals.py b/apps/transaction/signals.py index cf870f9..fa42c8c 100644 --- a/apps/transaction/signals.py +++ b/apps/transaction/signals.py @@ -49,7 +49,7 @@ def create_course_participant(transaction_instance): # بررسی اینکه آیا قبلاً participant ایجاد شده یا نه existing_participant = Participant.objects.filter( - student=transaction_instance.user, + student_id=transaction_instance.user.id, course=transaction_instance.course ).first()