Commit 2c4f6761 authored by Fernando Ribeiro's avatar Fernando Ribeiro
Browse files

Feat: Add Message Professor classes coming from django-courses-legacy to solve part-1 of #158

parent 68db30ef
......@@ -39,3 +39,26 @@ class IsAdmin(permissions.BasePermission):
return True
elif request.user and request.user.is_superuser:
return True
class IsAssistantOrCoordinatorOrReadOnly(permissions.BasePermission):
"""
Check if a user can send messages to students enrolled in a course
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
else:
return obj.course.is_assistant_or_coordinator(request.user)
class IsAdminOrReadOnly(IsAdmin):
"""
Custom permission to only allow not safe methods to admin.
"""
def has_permission(self, request, view):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
return super(IsAdminOrReadOnly, self).has_permission(request, view)
......@@ -5,11 +5,14 @@ from .videos.serializers import VideoSerializer
from .models import (
Course,
CourseProfessor,
ProfessorMessage,
ProfessorMessageRead,
)
User = get_user_model()
class SimpleUserSerializer(serializers.ModelSerializer):
class Meta:
......@@ -107,3 +110,70 @@ class BasicCourseProfessorSerializer(serializers.ModelSerializer):
model = CourseProfessor
class ProfessorMessageReadSerializer(serializers.ModelSerializer):
class Meta:
model = ProfessorMessageRead
fields = ('id', 'message', 'is_read')
class ProfessorMessageSerializer(serializers.ModelSerializer):
professor = SimpleUserSerializer(read_only=True)
course_slug = serializers.SerializerMethodField(read_only=True)
course_name = serializers.SerializerMethodField(read_only=True)
is_read = serializers.SerializerMethodField(read_only=True)
class Meta:
model = ProfessorMessage
fields = ('id', 'course', 'course_name', 'course_slug', 'professor',
'users', 'subject', 'message', 'date', 'is_read')
def get_course_slug(self, obj):
try:
return obj.course.slug
except AttributeError as e:
return '' # no course is associated with this message
def get_course_name(self, obj):
try:
return obj.course.name
except AttributeError as e:
return '' # no course is associated with this message
def get_is_read(self, obj):
try:
read_state = ProfessorMessageRead.objects.get(user=self.context['request'].user, message=obj)
return read_state.is_read
except ProfessorMessageRead.DoesNotExist as e:
return False
class ProfessorGlobalMessageSerializer(ProfessorMessageSerializer):
users = SimpleUserSerializer(read_only=True, required=False, many=True)
def create(self, validated_data):
all_students = self.context['request'].data.get('all_students', None)
groups = self.context['request'].data.get('groups', None)
recipients = self.context['request'].data.get('users', None)
validated_data['professor'] = self.context['request'].user
global_message = ProfessorMessage(**validated_data)
global_message.save()
User = get_user_model()
if all_students:
# If all_students was set to True by the client, this is a global message
global_message.users.add(*[user for user in User.objects.all()])
elif groups:
# If groups were specified, their users are the recipients
global_message.users.add(*[user for user in User.objects.filter(groups__in=groups)])
elif recipients:
# Otherwise, user the recipients list
for user_id in self.context['request'].data['users']:
global_message.users.add(User.objects.get(id=user_id))
global_message.send()
return global_message
......@@ -3,7 +3,12 @@ from django.views.generic import TemplateView
from rest_framework import routers
from .views import CourseViewSet, BaseCourseProfessorViewSet
from .views import (
CourseViewSet, BaseCourseProfessorViewSet,
ProfessorMessageViewSet,
ProfessorMessageReadViewSet,
ProfessorGlobalMessageViewSet,
)
from .course_material.views import CourseMaterialViewSet, CourseMaterialFileViewSet
from .import_export.views import ExportCourseView, ImportCourseView
from courses.workspaces.views import (
......@@ -26,6 +31,7 @@ router.register(r'course', CourseViewSet, base_name='course')
router.register(r'course_material', CourseMaterialViewSet, base_name='course_material')
router.register(r'course_material_file', CourseMaterialFileViewSet, base_name='course_material_file')
# Workspaces
router.register(r'workspaces', WorkspaceViewSet)
router.register(r'group', WorkspaceGroupViewSet, base_name='group')
......@@ -41,9 +47,14 @@ router.register(r'users-by-group', UsersByGroupViewSet, base_name='users-by-grou
router.register(r'users-by-class', UsersByClassViewSet, base_name='users-by-class')
# router.register(r'course_carousel', views.CarouselCourseView, base_name='course_carousel')
#Professor
router.register(r'course_professor_basic', BaseCourseProfessorViewSet, base_name='course_professor')
app_name = 'courses'
router.register(r'professor_message', ProfessorMessageViewSet, base_name='professor_message')
router.register(r'professor_message_global', ProfessorGlobalMessageViewSet, base_name='professor_message_global')
router.register(r'professor_message_read', ProfessorMessageReadViewSet, base_name='professor_message_read')
app_name = 'courses'
urlpatterns = [
url(r'^course/(?P<course_id>[1-9][0-9]*)/export/$', ExportCourseView.as_view(), name="course_export"),
url(r'^course/import/$', ImportCourseView.as_view(), name="course_import"),
......
from django.db.models import Q
from rest_framework import viewsets
from django.db import IntegrityError
from rest_framework import viewsets, mixins
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from .models import (Course, CourseProfessor, ProfessorMessage, ProfessorMessageRead)
from .serializers import (CourseSerializer, BasicCourseProfessorSerializer,
ProfessorMessageSerializer, ProfessorMessageReadSerializer,
ProfessorGlobalMessageSerializer,
)
from .models import Course, CourseProfessor
from .serializers import CourseSerializer, BasicCourseProfessorSerializer
from .permissions import IsProfessorCoordinatorOrAdminPermissionOrReadOnly
from .permissions import (IsProfessorCoordinatorOrAdminPermissionOrReadOnly, IsAssistantOrCoordinatorOrReadOnly, IsAdminOrReadOnly)
class CourseViewSet(viewsets.ModelViewSet):
......@@ -20,7 +27,7 @@ class CourseViewSet(viewsets.ModelViewSet):
queryset = super(CourseViewSet, self).get_queryset()
if not self.request.user.is_authenticated:
return queryset.filter(is_public=True, status='published').prefetch_related('professors')
return queryset.filter(is_public=True, status='published').prefetch_related('professors')
if not self.request.user.is_superuser:
role = self.request.query_params.get('role', None)
......@@ -80,3 +87,73 @@ class BaseCourseProfessorViewSet(viewsets.ModelViewSet):
permission_classes = (IsProfessorCoordinatorOrAdminPermissionOrReadOnly, )
class ProfessorMessageViewSet(viewsets.ModelViewSet):
model = ProfessorMessage
lookup_field = 'id'
filter_fields = ('course',)
serializer_class = ProfessorMessageSerializer
permission_classes = (IsAssistantOrCoordinatorOrReadOnly,)
def perform_create(self, serializer):
obj = serializer.save(professor=self.request.user)
if obj:
obj.send()
def get_queryset(self):
queryset = ProfessorMessage.objects.filter(users__in=[self.request.user]).order_by('-id')
unread = self.request.query_params.get('unread', None)
if unread:
# Exclude read messages
queryset = queryset.exclude(read_status__is_read=True, read_status__user=self.request.user)
limit_to = self.request.query_params.get('limit_to', None)
if limit_to:
queryset = queryset[:int(limit_to)]
return queryset
# This view creates ProfessorMessages targeting specific users and with no ties to any course
# Only site admins can create messages using this endpoint
class ProfessorGlobalMessageViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet):
model = ProfessorMessage
serializer_class = ProfessorGlobalMessageSerializer
permission_classes = (IsAdminOrReadOnly,)
def get_queryset(self):
# Get all admin messages sent using this view
queryset = ProfessorMessage.objects.filter(course=None).order_by('-id')
limit_to = self.request.query_params.get('limit_to', None)
if limit_to:
queryset = queryset[:int(limit_to)]
return queryset
class ProfessorMessageReadViewSet(viewsets.ModelViewSet):
model = ProfessorMessageRead
lookup_field = 'message'
serializer_class = ProfessorMessageReadSerializer
permission_classes = (IsAuthenticated,)
def perform_create(self, serializer):
try:
read_info = serializer.save(user=self.request.user, is_read=True)
except IntegrityError as e:
read_info = ProfessorMessageRead.objects.get(message=self.request.data['message'], user=self.request.user)
read_info.is_read = True
read_info.save()
def get_queryset(self):
queryset = ProfessorMessageRead.objects.filter(user=self.request.user).order_by('-id')
limit_to = self.request.query_params.get('limit_to', None)
if limit_to:
queryset = queryset[:int(limit_to)]
return queryset
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment