Add mutation to remove member from class

This commit is contained in:
Ramon Wenger 2020-03-05 15:14:26 +01:00
parent a99a073460
commit b82b82369c
5 changed files with 158 additions and 8 deletions

View File

@ -0,0 +1,5 @@
mutation RemoveMember($input: RemoveMemberInput!) {
removeMember(input: $input) {
success
}
}

View File

@ -7,15 +7,24 @@ from .models import User, SchoolClass, Role, UserRole, UserSetting
class SchoolClassInline(admin.TabularInline):
model = SchoolClass.users.through
extra = 1
class RoleInline(admin.TabularInline):
model = UserRole
extra = 1
@admin.register(SchoolClass)
class SchoolClassAdmin(admin.ModelAdmin):
list_display = ('name', 'code', 'is_deleted')
list_display = ('name', 'code', 'user_list', 'is_deleted')
inlines = [
SchoolClassInline
]
def user_list(self, obj):
return ', '.join([s.username for s in obj.users.all()])
@admin.register(Role)

View File

@ -2,7 +2,7 @@ import random
import factory
from users.models import SchoolClass
from users.models import SchoolClass, SchoolClassMember
class_types = ['DA', 'KV', 'INF', 'EE']
class_suffix = ['A', 'B', 'C', 'D', 'E']
@ -16,7 +16,8 @@ class SchoolClassFactory(factory.django.DjangoModelFactory):
class Meta:
model = SchoolClass
name = factory.Sequence(lambda n: '{}{}{}'.format(random.choice(class_types), '18', class_suffix[n % len(class_suffix)]))
name = factory.Sequence(
lambda n: '{}{}{}'.format(random.choice(class_types), '18', class_suffix[n % len(class_suffix)]))
is_deleted = False
@factory.post_generation
@ -28,4 +29,4 @@ class SchoolClassFactory(factory.django.DjangoModelFactory):
if extracted:
# A list of groups were passed in, use them
for user in extracted:
self.users.add(user)
SchoolClassMember.objects.create(user=user, school_class=self, active=True)

View File

@ -3,10 +3,11 @@ 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
from users.models import SchoolClass, UserSetting, User, SchoolClassMember
from users.schema import SchoolClassNode
from users.serializers import PasswordSerialzer, AvatarUrlSerializer
@ -122,7 +123,6 @@ class JoinClass(relay.ClientIDMutation):
try:
school_class = SchoolClass.objects.get(Q(code__iexact=code))
if user not in list(school_class.users.all()):
school_class.users.add(user)
else:
@ -133,8 +133,35 @@ class JoinClass(relay.ClientIDMutation):
raise CodeNotFoundException('[CNV] Code ist nicht gültig') # CAV = Code Not Valid
class RemoveMember(relay.ClientIDMutation):
class Input:
member = graphene.ID(required=True)
school_class = graphene.ID(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')
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 = False
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()
remove_member = RemoveMember.Field()

View File

@ -0,0 +1,108 @@
from django.test import TestCase
from graphene import Context
from graphene.test import Client
from graphql_relay import to_global_id
from api.utils import get_graphql_mutation
from core.factories import UserFactory
from users.factories import SchoolClassFactory
from users.models import SchoolClass, User, SchoolClassMember
from api.schema import schema
from users.services import create_users
class JoinSchoolClassTest(TestCase):
def setUp(self):
self.client = Client(schema=schema)
self.school_class_name = 'Moordale'
user_data = [
{
'teacher': ('Emily', 'Sands',),
'class': self.school_class_name,
'code': 'SEXED',
'students': [
('Otis', 'Milburn'),
('Maeve', 'Wiley'),
('Adam', 'Groff'),
('Eric', 'Effiong'),
('Jackson', 'Marchetti'),
]
},
{
'teacher': ('Colin', 'Hendricks'),
'class': 'Swing Band',
'students': [
('Ola', 'Nyman'),
]
}
]
create_users(user_data)
teacher = User.objects.get(username='emily.sands')
self.teacher_id = to_global_id('UserNode', teacher.pk)
student = User.objects.get(username='adam.groff')
self.student_id = to_global_id('UserNode', student.pk)
other_student = User.objects.get(username='eric.effiong')
self.other_student_id = to_global_id('UserNode', other_student.pk)
school_class = SchoolClass.objects.get(name=self.school_class_name)
self.school_class_id = to_global_id('SchoolClassNode', school_class.pk)
self.teacher_context = Context(user=teacher)
self.student_context = Context(user=student)
self.mutation = get_graphql_mutation('removeMember.gql')
def test_leave_class(self):
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 6)
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(),
0)
result = self.client.execute(self.mutation, variables={
'input': {
'schoolClass': self.school_class_id,
'member': self.student_id
}
}, context=self.teacher_context)
self.assertIsNone(result.get('errors'))
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 5)
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(),
1)
def test_leave_class_student_raises_error(self):
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 6)
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(), 0)
result = self.client.execute(self.mutation, variables={
'input': {
'schoolClass': self.school_class_id,
'member': self.other_student_id
}
}, context=self.student_context)
self.assertIsNotNone(result['errors'])
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 6)
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(), 0)
def test_leave_class_other_school_class_raises_error(self):
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 6)
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(), 0)
student = User.objects.get(username='ola.nyman')
school_class = SchoolClass.objects.get(name='Swing Band')
result = self.client.execute(self.mutation, variables={
'input': {
'schoolClass': to_global_id('SchoolClassNode', school_class.id),
'member': to_global_id('UserNode', student.id)
}
}, context=self.teacher_context)
self.assertIsNotNone(result['errors'])
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=True).count(), 6)
self.assertEqual(
SchoolClassMember.objects.filter(school_class__name=self.school_class_name, active=False).count(), 0)