diff --git a/backend/api/permissions/assistant_permissions.py b/backend/api/permissions/assistant_permissions.py index 5cb76fc1..77adb6f9 100644 --- a/backend/api/permissions/assistant_permissions.py +++ b/backend/api/permissions/assistant_permissions.py @@ -11,7 +11,7 @@ def has_permission(self, request: Request, view: ViewSet) -> bool: """Check if user has permission to view a general assistant endpoint.""" user = request.user - if view.action == "list": + if view.action in ['list', 'create', 'destroy']: # Only teachers can query the assistant list. return user.is_authenticated and is_teacher(user) diff --git a/backend/api/permissions/student_permissions.py b/backend/api/permissions/student_permissions.py new file mode 100644 index 00000000..ab1afd57 --- /dev/null +++ b/backend/api/permissions/student_permissions.py @@ -0,0 +1,15 @@ +from rest_framework.permissions import IsAuthenticated, SAFE_METHODS +from api.permissions.role_permissions import is_teacher +from authentication.models import User + + +class StudentPermission(IsAuthenticated): + + def has_permission(self, request, view): + """Check if user has permission to view a general student endpoint.""" + return view.action == 'retrieve' + + def has_object_permission(self, request, view, obj): + """Check if user has permission to view a detailed group endpoint""" + user: User = request.user + return request.method in SAFE_METHODS and (user.id == request.user.id or is_teacher(user)) diff --git a/backend/api/permissions/teacher_permissions.py b/backend/api/permissions/teacher_permissions.py new file mode 100644 index 00000000..22b8d96a --- /dev/null +++ b/backend/api/permissions/teacher_permissions.py @@ -0,0 +1,15 @@ +from rest_framework.permissions import IsAuthenticated, SAFE_METHODS +from authentication.models import User + + +# (Almost) same as StudentPermission +class TeacherPermission(IsAuthenticated): + + def has_permission(self, request, view): + """Check if user has permission to view a general Teacher endpoint.""" + return view.action == 'retrieve' + + def has_object_permission(self, request, view, obj): + """Check if user has permission to view a detailed group endpoint""" + user: User = request.user + return request.method in SAFE_METHODS and user.id == request.user.id diff --git a/backend/api/views/assistant_view.py b/backend/api/views/assistant_view.py index e20bec81..87328432 100644 --- a/backend/api/views/assistant_view.py +++ b/backend/api/views/assistant_view.py @@ -1,6 +1,6 @@ from rest_framework.decorators import action from rest_framework.response import Response -from rest_framework.viewsets import ReadOnlyModelViewSet +from rest_framework.viewsets import ModelViewSet from rest_framework.permissions import IsAdminUser from api.permissions.assistant_permissions import AssistantPermission from ..models.assistant import Assistant @@ -8,7 +8,7 @@ from ..serializers.course_serializer import CourseSerializer -class AssistantViewSet(ReadOnlyModelViewSet): +class AssistantViewSet(ModelViewSet): queryset = Assistant.objects.all() serializer_class = AssistantSerializer diff --git a/backend/api/views/student_view.py b/backend/api/views/student_view.py index ef0c0289..1261d6ab 100644 --- a/backend/api/views/student_view.py +++ b/backend/api/views/student_view.py @@ -2,6 +2,7 @@ from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.permissions import IsAdminUser +from api.permissions.student_permissions import StudentPermission from api.permissions.role_permissions import IsSameUser, IsTeacher from api.models.student import Student from api.serializers.student_serializer import StudentSerializer @@ -12,7 +13,7 @@ class StudentViewSet(viewsets.ModelViewSet): queryset = Student.objects.all() serializer_class = StudentSerializer - permission_classes = [IsAdminUser | IsTeacher | IsSameUser] + permission_classes = [IsAdminUser | StudentPermission] @action(detail=True) def courses(self, request, **_): diff --git a/backend/api/views/teacher_view.py b/backend/api/views/teacher_view.py index 20c2c95b..cdc6160d 100644 --- a/backend/api/views/teacher_view.py +++ b/backend/api/views/teacher_view.py @@ -1,19 +1,20 @@ from rest_framework.decorators import action from rest_framework.response import Response -from rest_framework.viewsets import ReadOnlyModelViewSet +from rest_framework.viewsets import ModelViewSet from rest_framework.permissions import IsAdminUser from api.models.teacher import Teacher from api.serializers.teacher_serializer import TeacherSerializer from api.serializers.course_serializer import CourseSerializer -from api.permissions.role_permissions import IsSameUser +from api.permissions.teacher_permissions import TeacherPermission +from rest_framework.permissions import IsAuthenticated -class TeacherViewSet(ReadOnlyModelViewSet): +class TeacherViewSet(ModelViewSet): queryset = Teacher.objects.all() serializer_class = TeacherSerializer - permission_classes = [IsAdminUser | IsSameUser] + permission_classes = [IsAdminUser | TeacherPermission] - @action(detail=True, methods=["get"]) + @action(detail=True, methods=["get"], permission_classes=[IsAuthenticated]) def courses(self, request, pk=None): """Returns a list of courses for the given teacher""" teacher = self.get_object() diff --git a/backend/authentication/models.py b/backend/authentication/models.py index 066d6fbb..dff350cb 100644 --- a/backend/authentication/models.py +++ b/backend/authentication/models.py @@ -34,6 +34,10 @@ class User(AbstractBaseUser): USERNAME_FIELD = "username" EMAIL_FIELD = "email" + def make_admin(self): + self.is_staff = True + self.save() + @staticmethod def get_dummy_admin(): return User(