89 lines
3.9 KiB
Python
89 lines
3.9 KiB
Python
from rest_framework import viewsets, permissions
|
|
from .models import Project, Task
|
|
from .serializers import ProjectSerializer, ProjectDetailSerializer, TaskSerializer, TaskDetailSerializer
|
|
from accounts.permissions import IsAdmin, IsTeacher, IsStudentReadOnly
|
|
from rest_framework.exceptions import PermissionDenied
|
|
|
|
class ProjectViewSet(viewsets.ModelViewSet):
|
|
"""
|
|
CRUD for Projects.
|
|
- list/retrieve: Admin, Teacher, Student
|
|
- create/update/destroy: Admin, Teacher (but Teacher can only update/destroy their own)
|
|
"""
|
|
# Base permissions. Object-level is handled in check_object_permissions or via queryset
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
|
|
def get_queryset(self):
|
|
# Filter by tenant
|
|
return Project.objects.tenant(self.request.tenant).select_related('created_by').order_by('-created_at')
|
|
|
|
def get_serializer_class(self):
|
|
if self.action in ['retrieve']:
|
|
return ProjectDetailSerializer
|
|
return ProjectSerializer
|
|
|
|
def perform_create(self, serializer):
|
|
# Auto-set the tenant and creator
|
|
serializer.save(tenant=self.request.tenant, created_by=self.request.user)
|
|
|
|
def check_permissions(self, request):
|
|
super().check_permissions(request)
|
|
if request.user.role == 'student' and request.method not in permissions.SAFE_METHODS:
|
|
raise PermissionDenied("Students cannot modify projects.")
|
|
|
|
def check_object_permissions(self, request, obj):
|
|
super().check_object_permissions(request, obj)
|
|
if request.method not in permissions.SAFE_METHODS:
|
|
if request.user.role == 'teacher' and obj.created_by != request.user:
|
|
raise PermissionDenied("You can only modify projects you created.")
|
|
|
|
class TaskViewSet(viewsets.ModelViewSet):
|
|
"""
|
|
CRUD for Tasks nested under a Project.
|
|
"""
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
pagination_class = None # Return all tasks as list, not paginated
|
|
|
|
def get_queryset(self):
|
|
# The URL captures project_pk
|
|
project_id = self.kwargs.get('project_pk')
|
|
return Task.objects.tenant(self.request.tenant).filter(project_id=project_id).select_related('assigned_to', 'project').order_by('-created_at')
|
|
|
|
def get_serializer_class(self):
|
|
if self.action in ['retrieve', 'create', 'update', 'partial_update']:
|
|
return TaskDetailSerializer
|
|
return TaskSerializer
|
|
|
|
def perform_create(self, serializer):
|
|
project_id = self.kwargs.get('project_pk')
|
|
try:
|
|
project = Project.objects.get(id=project_id)
|
|
except Project.DoesNotExist:
|
|
raise serializers.ValidationError("Project does not exist.")
|
|
|
|
# Check permissions before allowing to create task
|
|
if self.request.user.role == 'teacher' and project.created_by != self.request.user:
|
|
raise PermissionDenied("You can only add tasks to projects you created.")
|
|
|
|
assigned_to_id = self.request.data.get('assigned_to_id')
|
|
|
|
serializer.save(tenant=self.request.tenant, project=project, assigned_to_id=assigned_to_id)
|
|
|
|
def perform_update(self, serializer):
|
|
assigned_to_id = self.request.data.get('assigned_to_id')
|
|
if 'assigned_to_id' in self.request.data:
|
|
serializer.save(assigned_to_id=assigned_to_id)
|
|
else:
|
|
serializer.save()
|
|
|
|
def check_permissions(self, request):
|
|
super().check_permissions(request)
|
|
if request.user.role == 'student' and request.method not in permissions.SAFE_METHODS:
|
|
raise PermissionDenied("Students cannot modify tasks.")
|
|
|
|
def check_object_permissions(self, request, obj):
|
|
super().check_object_permissions(request, obj)
|
|
if request.method not in permissions.SAFE_METHODS:
|
|
if request.user.role == 'teacher' and obj.project.created_by != request.user:
|
|
raise PermissionDenied("You can only modify tasks in projects you created.")
|