skillbox/server/users/mutations.py

173 lines
5.4 KiB
Python

import graphene
from django.contrib.auth import update_session_auth_hash
from django.core.exceptions import PermissionDenied
from django.db.models import Q
from graphene import relay
from graphql_relay import from_global_id
from api.utils import get_object
from users.inputs import PasswordUpdateInput
from users.models import SchoolClass, UserSetting, User, SchoolClassMember
from users.schema import SchoolClassNode
from users.serializers import PasswordSerialzer, AvatarUrlSerializer
class CodeNotFoundException(Exception):
pass
class FieldError(graphene.ObjectType):
code = graphene.String()
class UpdateError(graphene.ObjectType):
field = graphene.String()
errors = graphene.List(FieldError)
class UpdatePassword(relay.ClientIDMutation):
class Input:
password_input = graphene.Argument(PasswordUpdateInput)
success = graphene.Boolean()
errors = graphene.List(UpdateError) # todo: change for consistency
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
user = info.context.user
password_data = kwargs.get('password_input')
serializer = PasswordSerialzer(data=password_data, context=user)
if serializer.is_valid():
user.set_password(password_data['new_password'])
user.save()
update_session_auth_hash(info.context, user)
return cls(success=True)
errors = []
for key, value in serializer.errors.items():
error = UpdateError(field=key, errors=[])
for field_error in serializer.errors[key]:
error.errors.append(FieldError(code=field_error.code))
errors.append(error)
return cls(success=False, errors=errors)
class UpdateAvatar(relay.ClientIDMutation):
class Input:
avatar_url = graphene.String()
success = graphene.Boolean()
errors = graphene.List(UpdateError) # todo: change for consistency
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
user = info.context.user
avatar_data = kwargs.get('avatar_url')
serializer = AvatarUrlSerializer(data={'avatar_url': avatar_data})
if serializer.is_valid():
user.avatar_url = avatar_data
user.save()
return cls(success=True)
errors = []
for key, value in serializer.errors.items():
error = UpdateError(field=key, errors=[])
for field_error in serializer.errors[key]:
error.errors.append(FieldError(code=field_error.code))
errors.append(error)
return cls(success=False, errors=errors)
class UpdateSetting(relay.ClientIDMutation):
class Input:
id = graphene.ID(required=True)
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
class_id = kwargs.get('id')
school_class = get_object(SchoolClass, class_id)
user = info.context.user
if school_class and school_class not in user.school_classes.all():
raise PermissionDenied('Permission denied: Incorrect school class')
user_settings, created = UserSetting.objects.get_or_create(user=user)
user_settings.selected_class = school_class
user_settings.save()
return cls(success=True)
success = graphene.Boolean()
errors = graphene.List(UpdateError)
class JoinClass(relay.ClientIDMutation):
class Input:
code = graphene.String(required=True)
success = graphene.Boolean()
school_class = graphene.Field(SchoolClassNode)
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
user = info.context.user
code = kwargs.get('code')
try:
school_class = SchoolClass.objects.get(Q(code__iexact=code))
if user not in list(school_class.users.all()):
SchoolClassMember.objects.create(
user=user,
school_class=school_class
)
else:
raise CodeNotFoundException('[CAJ] Schüler ist bereits in Klasse') # CAJ = Class Already Joined
return cls(success=True, school_class=school_class)
except SchoolClass.DoesNotExist:
raise CodeNotFoundException('[CNV] Code ist nicht gültig') # CAV = Code Not Valid
class AddRemoveMember(relay.ClientIDMutation):
class Input:
member = graphene.ID(required=True)
school_class = graphene.ID(required=True)
active = graphene.Boolean(required=True)
success = graphene.Boolean()
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
member_id = kwargs.get('member')
school_class_id = kwargs.get('school_class')
active = kwargs.get('active')
user = info.context.user
member_pk = from_global_id(member_id)[1]
school_class = get_object(SchoolClass, school_class_id)
if not user.is_teacher() or not school_class.users.filter(pk=user.pk).exists():
raise PermissionError('Fehlende Berechtigung')
school_class_member = SchoolClassMember.objects.get(user__pk=member_pk, school_class=school_class)
school_class_member.active = active
school_class_member.save()
return cls(success=True)
class ProfileMutations:
update_password = UpdatePassword.Field()
update_avatar = UpdateAvatar.Field()
update_setting = UpdateSetting.Field()
join_class = JoinClass.Field()
add_remove_member = AddRemoveMember.Field()