skillbox/server/rooms/mutations.py

176 lines
6.1 KiB
Python

import graphene
from django.core.exceptions import PermissionDenied
from graphene import relay
from graphql_relay import to_global_id
from api.utils import get_object
from rooms.inputs import UpdateRoomArgument, AddRoomArgument, AddRoomEntryArgument, UpdateRoomEntryArgument
from rooms.models import Comment, Room, RoomEntry
from rooms.schema import CommentNode, RoomNode, RoomEntryNode
from rooms.serializers import RoomSerializer, RoomEntrySerializer
from users.models import SchoolClass
class MutateRoom(relay.ClientIDMutation):
errors = graphene.List(graphene.String)
room = graphene.Field(RoomNode)
@classmethod
def mutate_and_get_payload(cls, *args, **kwargs):
room_data = kwargs.get('room')
school_class = get_object(SchoolClass, room_data.get('school_class').get('id'))
room_data['school_class'] = school_class.id
if room_data.get('id') is not None:
room = get_object(Room, room_data['id'])
serializer = RoomSerializer(room, data=room_data)
else:
serializer = RoomSerializer(data=room_data)
if serializer.is_valid():
serializer.save()
return cls(room=serializer.instance, errors=None)
return cls(room=None, errors=['{}: {}'.format(key, value) for key, value in serializer.errors.items()])
class AddRoom(MutateRoom):
class Input:
room = graphene.Argument(AddRoomArgument) # NB: can't be named AddRoomInput, otherwise graphene complains
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
user = info.context.user
if not user.has_perm('users.can_manage_school_class_content'):
return cls(room=None, errors=['not allowed'])
room_data = kwargs.get('room')
school_class_id = user.selected_class.id
room_data['school_class'] = school_class_id
serializer = RoomSerializer(data=room_data)
if serializer.is_valid():
serializer.save()
return cls(room=serializer.instance)
return cls(room=None, errors=['{}: {}'.format(key, value) for key, value in serializer.errors.items()])
class UpdateRoom(MutateRoom):
class Input:
room = graphene.Argument(UpdateRoomArgument) # NB: can't be named ChangeRoomInput, otherwise graphene complains
class DeleteRoom(relay.ClientIDMutation):
class Input:
id = graphene.ID(required=True)
success = graphene.Boolean()
errors = graphene.List(graphene.String)
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
id = kwargs.get('id')
room = get_object(Room, id)
user = info.context.user
if not user.has_perm('users.can_manage_school_class_content'):
raise PermissionDenied('Missing permissions')
if room.school_class not in user.school_classes.all():
raise PermissionDenied('Permission denied: Incorrect school classes')
room.delete()
return cls(success=True)
class MutateRoomEntry(relay.ClientIDMutation):
room_entry = graphene.Field(RoomEntryNode)
errors = graphene.List(graphene.String)
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
room_entry_data = kwargs.get('room_entry')
if room_entry_data.get('room') is not None:
room_entry_data['room'] = get_object(Room, room_entry_data.get('room')).id
if room_entry_data.get('id') is not None:
# update path
instance = get_object(RoomEntry, room_entry_data.get('id'))
if not instance.room.school_class.is_user_in_schoolclass(info.context.user):
raise Exception('You are in the wrong class')
if instance.author.pk != info.context.user.pk:
raise Exception('You are not the author')
serializer = RoomEntrySerializer(instance, data=room_entry_data, partial=True)
else:
# add path
room_entry_data['author'] = info.context.user.pk
serializer = RoomEntrySerializer(data=room_entry_data)
if serializer.is_valid():
serializer.save()
return cls(room_entry=serializer.instance)
return cls(room_entry=None, errors=['{}: {}'.format(key, value) for key, value in serializer.errors.items()])
class AddRoomEntry(MutateRoomEntry):
class Input:
room_entry = graphene.Argument(AddRoomEntryArgument)
class UpdateRoomEntry(MutateRoomEntry):
class Input:
room_entry = graphene.Argument(UpdateRoomEntryArgument)
class DeleteRoomEntry(relay.ClientIDMutation):
class Input:
id = graphene.ID(required=True)
success = graphene.Boolean()
room_slug = graphene.String()
room_id = graphene.ID()
errors = graphene.List(graphene.String)
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
id = kwargs.get('id')
room_entry = get_object(RoomEntry, id)
if room_entry.author.pk != info.context.user.pk:
raise Exception('You are not the owner of this room entry')
room_id = to_global_id('RoomNode', room_entry.room.pk)
room_slug = room_entry.room.slug
room_entry.delete()
return cls(success=True, room_id=room_id, room_slug=room_slug)
class AddComment(relay.ClientIDMutation):
class Input:
comment = graphene.String(required=True)
room_entry = graphene.ID(required=True)
success = graphene.Boolean()
comment = graphene.Field(CommentNode)
@classmethod
def mutate_and_get_payload(cls, root, info, **args):
room_entry_id = args.get('room_entry')
text = args.get('comment')
user = info.context.user
room_entry = get_object(RoomEntry, room_entry_id)
comment = Comment.objects.create(text=text, room_entry=room_entry, owner=user)
return cls(success=True, comment=comment)
class RoomMutations:
update_room = UpdateRoom.Field()
add_room = AddRoom.Field()
delete_room = DeleteRoom.Field()
add_room_entry = AddRoomEntry.Field()
delete_room_entry = DeleteRoomEntry.Field()
update_room_entry = UpdateRoomEntry.Field()
add_comment = AddComment.Field()