skillbox/server/rooms/mutations.py

153 lines
5.4 KiB
Python

import graphene
from django.core.exceptions import PermissionDenied
from graphene import relay
from graphql_relay import to_global_id, from_global_id
from api.utils import get_object
from rooms.inputs import UpdateRoomArgument, AddRoomArgument, AddRoomEntryArgument, UpdateRoomEntryArgument
from rooms.models import Room, RoomEntry
from rooms.schema import 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):
if not info.context.user.has_perm('users.can_manage_school_class_content'):
return cls(room=None, errors=['not allowed'])
room_data = kwargs.get('room')
room_data['school_class'] = get_object(SchoolClass, room_data.get('school_class').id).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 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()