From 8adbcfdcad01d468b4b4a83aa17f6316e47acbe4 Mon Sep 17 00:00:00 2001 From: EwoutV Date: Thu, 7 Mar 2024 19:41:02 +0100 Subject: [PATCH] feat: IsStudent permission class and ability to join courses (#60) --- backend/api/permissions/__init__.py | 0 backend/api/permissions/role_permissions.py | 9 +++++ backend/api/views/course_view.py | 38 ++++++++++++++++----- backend/authentication/models.py | 6 ---- 4 files changed, 39 insertions(+), 14 deletions(-) create mode 100644 backend/api/permissions/__init__.py create mode 100644 backend/api/permissions/role_permissions.py diff --git a/backend/api/permissions/__init__.py b/backend/api/permissions/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/api/permissions/role_permissions.py b/backend/api/permissions/role_permissions.py new file mode 100644 index 00000000..dcd85686 --- /dev/null +++ b/backend/api/permissions/role_permissions.py @@ -0,0 +1,9 @@ +from rest_framework.permissions import IsAuthenticated +from api.models.student import Student + +class IsStudent(IsAuthenticated): + def has_permission(self, request, view): + """Returns true if the request contains a user, + with said user being a student""" + return super().has_permission(request, view) and \ + Student.objects.filter(id=request.user.id).exists() \ No newline at end of file diff --git a/backend/api/views/course_view.py b/backend/api/views/course_view.py index 54b1fcf2..05614ced 100644 --- a/backend/api/views/course_view.py +++ b/backend/api/views/course_view.py @@ -1,12 +1,16 @@ +from django.utils.translation import gettext from rest_framework import viewsets, status from rest_framework.decorators import action from rest_framework.response import Response -from ..models.course import Course -from ..serializers.course_serializer import CourseSerializer -from ..serializers.teacher_serializer import TeacherSerializer -from ..serializers.assistant_serializer import AssistantSerializer -from ..serializers.student_serializer import StudentSerializer -from ..serializers.project_serializer import ProjectSerializer +from rest_framework.exceptions import NotFound +from api.models.student import Student +from api.models.course import Course +from api.permissions.role_permissions import IsStudent +from api.serializers.course_serializer import CourseSerializer +from api.serializers.teacher_serializer import TeacherSerializer +from api.serializers.assistant_serializer import AssistantSerializer +from api.serializers.student_serializer import StudentSerializer +from api.serializers.project_serializer import ProjectSerializer class CourseViewSet(viewsets.ModelViewSet): @@ -89,6 +93,24 @@ def projects(self, request, pk=None): except Course.DoesNotExist: # Invalid course ID - return Response( - status=status.HTTP_404_NOT_FOUND, data={"message": "Course not found"} + raise NotFound(gettext("courses.errors.not_found")) + + @action(detail=True, methods=['get'], permission_classes=[IsStudent]) + def join(self, request, pk=None): + try: + # Add the course to the student's enrollment list. + Student.objects.get(id=request.user.id).courses.add( + Course.objects.get(id=pk) ) + + return Response({ + "message": gettext("courses.messages.successful_join") + }) + + except Course.DoesNotExist: + # Invalid course ID + raise NotFound(gettext("courses.errors.not_found")) + except Student.DoesNotExist: + # Invalid student user, this should not happen + # since the IsStudent permission class already checks this. + raise NotFound(gettext("students.errors.not_found")) \ No newline at end of file diff --git a/backend/authentication/models.py b/backend/authentication/models.py index 8a8787f4..dcf28b4d 100644 --- a/backend/authentication/models.py +++ b/backend/authentication/models.py @@ -35,12 +35,6 @@ class User(AbstractBaseUser): USERNAME_FIELD = "username" EMAIL_FIELD = "email" - def has_role(self, model: Type[Self]): - """Simple generic implementation of roles. - This function looks if there exists a model (inheriting from User) with the same ID. - """ - model.objects.exists(self.id) - @staticmethod def get_dummy_admin(): return User(