Add update team mutation on server and some tests for it
This commit is contained in:
parent
b84aa50443
commit
9bde5dbb20
|
|
@ -6,11 +6,13 @@ from graphene import relay
|
||||||
from graphql_relay import from_global_id
|
from graphql_relay import from_global_id
|
||||||
|
|
||||||
from api.utils import get_object
|
from api.utils import get_object
|
||||||
|
from core.logger import get_logger
|
||||||
from users.inputs import PasswordUpdateInput
|
from users.inputs import PasswordUpdateInput
|
||||||
from users.models import SchoolClass, SchoolClassMember, Team
|
from users.models import SchoolClass, SchoolClassMember, Team
|
||||||
from users.schema import SchoolClassNode, TeamNode
|
from users.schema import SchoolClassNode, TeamNode
|
||||||
from users.serializers import PasswordSerialzer, AvatarUrlSerializer
|
from users.serializers import PasswordSerialzer, AvatarUrlSerializer
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
class CodeNotFoundException(Exception):
|
class CodeNotFoundException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
@ -25,6 +27,18 @@ class UpdateError(graphene.ObjectType):
|
||||||
errors = graphene.List(FieldError)
|
errors = graphene.List(FieldError)
|
||||||
|
|
||||||
|
|
||||||
|
class TeacherOnlyMutation(relay.ClientIDMutation):
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mutate(cls, root, info, input):
|
||||||
|
user = info.context.user
|
||||||
|
if 'users.can_manage_school_class_content' not in user.get_role_permissions():
|
||||||
|
raise PermissionError('Permission denied')
|
||||||
|
return super().mutate(root, info, input)
|
||||||
|
|
||||||
|
|
||||||
class UpdatePassword(relay.ClientIDMutation):
|
class UpdatePassword(relay.ClientIDMutation):
|
||||||
class Input:
|
class Input:
|
||||||
password_input = graphene.Argument(PasswordUpdateInput)
|
password_input = graphene.Argument(PasswordUpdateInput)
|
||||||
|
|
@ -154,7 +168,7 @@ class AddRemoveMember(relay.ClientIDMutation):
|
||||||
school_class = get_object(SchoolClass, school_class_id)
|
school_class = get_object(SchoolClass, school_class_id)
|
||||||
|
|
||||||
if not user.is_teacher() or not school_class.users.filter(pk=user.pk).exists():
|
if not user.is_teacher() or not school_class.users.filter(pk=user.pk).exists():
|
||||||
raise PermissionError('Fehlende Berechtigung')
|
raise PermissionError('Permission denied')
|
||||||
|
|
||||||
school_class_member = SchoolClassMember.objects.get(user__pk=member_pk, school_class=school_class)
|
school_class_member = SchoolClassMember.objects.get(user__pk=member_pk, school_class=school_class)
|
||||||
school_class_member.active = active
|
school_class_member.active = active
|
||||||
|
|
@ -163,7 +177,7 @@ class AddRemoveMember(relay.ClientIDMutation):
|
||||||
return cls(success=True)
|
return cls(success=True)
|
||||||
|
|
||||||
|
|
||||||
class UpdateSchoolClass(relay.ClientIDMutation):
|
class UpdateSchoolClass(TeacherOnlyMutation):
|
||||||
class Input:
|
class Input:
|
||||||
id = graphene.ID(required=True)
|
id = graphene.ID(required=True)
|
||||||
name = graphene.String()
|
name = graphene.String()
|
||||||
|
|
@ -177,9 +191,7 @@ class UpdateSchoolClass(relay.ClientIDMutation):
|
||||||
name = kwargs.get('name')
|
name = kwargs.get('name')
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
|
|
||||||
if 'users.can_manage_school_class_content' not in user.get_role_permissions():
|
# todo: only allow to edit your own school class
|
||||||
raise PermissionError()
|
|
||||||
|
|
||||||
school_class = get_object(SchoolClass, id)
|
school_class = get_object(SchoolClass, id)
|
||||||
school_class.name = name
|
school_class.name = name
|
||||||
school_class.save()
|
school_class.save()
|
||||||
|
|
@ -187,7 +199,7 @@ class UpdateSchoolClass(relay.ClientIDMutation):
|
||||||
return cls(success=True, school_class=school_class)
|
return cls(success=True, school_class=school_class)
|
||||||
|
|
||||||
|
|
||||||
class CreateSchoolClass(relay.ClientIDMutation):
|
class CreateSchoolClass(TeacherOnlyMutation):
|
||||||
class Input:
|
class Input:
|
||||||
name = graphene.String()
|
name = graphene.String()
|
||||||
|
|
||||||
|
|
@ -197,30 +209,14 @@ class CreateSchoolClass(relay.ClientIDMutation):
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
name = kwargs.get('name')
|
name = kwargs.get('name')
|
||||||
|
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
|
|
||||||
if 'users.can_manage_school_class_content' not in user.get_role_permissions():
|
|
||||||
raise PermissionError()
|
|
||||||
|
|
||||||
school_class = SchoolClass.objects.create(name=name)
|
school_class = SchoolClass.objects.create(name=name)
|
||||||
SchoolClassMember.objects.create(school_class=school_class, user=user)
|
SchoolClassMember.objects.create(school_class=school_class, user=user)
|
||||||
user.set_selected_class(school_class)
|
user.set_selected_class(school_class)
|
||||||
return cls(success=True, school_class=school_class)
|
return cls(success=True, school_class=school_class)
|
||||||
|
|
||||||
|
|
||||||
class TeacherOnlyMutation(relay.ClientIDMutation):
|
|
||||||
class Meta:
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def mutate(cls, root, info, input):
|
|
||||||
user = info.context.user
|
|
||||||
if 'users.can_manage_school_class_content' not in user.get_role_permissions():
|
|
||||||
raise PermissionError('Missing permissions')
|
|
||||||
return super().mutate(root, info, input)
|
|
||||||
|
|
||||||
|
|
||||||
class CreateTeam(TeacherOnlyMutation):
|
class CreateTeam(TeacherOnlyMutation):
|
||||||
class Input:
|
class Input:
|
||||||
name = graphene.String(required=True)
|
name = graphene.String(required=True)
|
||||||
|
|
@ -240,6 +236,30 @@ class CreateTeam(TeacherOnlyMutation):
|
||||||
return cls(success=True, team=team)
|
return cls(success=True, team=team)
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateTeam(TeacherOnlyMutation):
|
||||||
|
class Input:
|
||||||
|
id = graphene.ID(required=True)
|
||||||
|
name = graphene.String()
|
||||||
|
|
||||||
|
success = graphene.Boolean()
|
||||||
|
team = graphene.Field(TeamNode)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
|
id = kwargs.get('id')
|
||||||
|
name = kwargs.get('name')
|
||||||
|
user = info.context.user
|
||||||
|
|
||||||
|
team = get_object(Team, id)
|
||||||
|
if user not in team.members.all():
|
||||||
|
logger.info('User not part of this team')
|
||||||
|
raise PermissionError('Permission denied')
|
||||||
|
team.name = name
|
||||||
|
team.save()
|
||||||
|
|
||||||
|
return cls(success=True, team=team)
|
||||||
|
|
||||||
|
|
||||||
class JoinTeam(TeacherOnlyMutation):
|
class JoinTeam(TeacherOnlyMutation):
|
||||||
class Input:
|
class Input:
|
||||||
code = graphene.String(required=True)
|
code = graphene.String(required=True)
|
||||||
|
|
@ -285,3 +305,4 @@ class ProfileMutations:
|
||||||
update_onboarding_progress = UpdateOnboardingProgress.Field()
|
update_onboarding_progress = UpdateOnboardingProgress.Field()
|
||||||
create_team = CreateTeam.Field()
|
create_team = CreateTeam.Field()
|
||||||
join_team = JoinTeam.Field()
|
join_team = JoinTeam.Field()
|
||||||
|
update_team = UpdateTeam.Field()
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,16 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# ITerativ GmbH
|
|
||||||
# http://www.iterativ.ch/
|
|
||||||
#
|
|
||||||
# Copyright (c) 2019 ITerativ GmbH. All rights reserved.
|
|
||||||
#
|
|
||||||
# Created on 2019-10-10
|
|
||||||
# @author: chrigu <christian.cueni@iterativ.ch>
|
|
||||||
from django.conf import settings
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# ITerativ GmbH
|
|
||||||
# http://www.iterativ.ch/
|
|
||||||
#
|
|
||||||
# Copyright (c) 2019 ITerativ GmbH. All rights reserved.
|
|
||||||
#
|
|
||||||
# Created on 2019-04-09
|
|
||||||
# @author: chrigu <christian.cueni@iterativ.ch>
|
|
||||||
from django.test import TestCase, RequestFactory
|
from django.test import TestCase, RequestFactory
|
||||||
|
from graphene import Context
|
||||||
from graphene.test import Client
|
from graphene.test import Client
|
||||||
from graphql_relay import to_global_id
|
from graphql_relay import to_global_id
|
||||||
|
|
||||||
from api.utils import get_graphql_mutation, get_object
|
|
||||||
from core.factories import UserFactory
|
|
||||||
from users.models import SchoolClass, User
|
|
||||||
from api.schema import schema
|
from api.schema import schema
|
||||||
|
from api.utils import get_graphql_mutation, get_object
|
||||||
|
from core.factories import UserFactory, TeacherFactory
|
||||||
|
from users.models import SchoolClass, User
|
||||||
from users.services import create_users
|
from users.services import create_users
|
||||||
|
|
||||||
|
UPDATE_SCHOOL_CLASS_MUTATION = get_graphql_mutation('updateSchoolClass.gql')
|
||||||
|
|
||||||
|
|
||||||
class SchoolClassesTest(TestCase):
|
class SchoolClassesTest(TestCase):
|
||||||
|
|
||||||
|
|
@ -53,6 +37,7 @@ class SchoolClassesTest(TestCase):
|
||||||
class_name = SchoolClass.generate_default_group_name(user=user)
|
class_name = SchoolClass.generate_default_group_name(user=user)
|
||||||
self.assertEqual(f'{self.prefix} {user.pk}', class_name)
|
self.assertEqual(f'{self.prefix} {user.pk}', class_name)
|
||||||
|
|
||||||
|
|
||||||
class ModifySchoolClassTest(TestCase):
|
class ModifySchoolClassTest(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
create_users()
|
create_users()
|
||||||
|
|
@ -72,9 +57,8 @@ class ModifySchoolClassTest(TestCase):
|
||||||
school_class = SchoolClass.objects.get(name='skillbox')
|
school_class = SchoolClass.objects.get(name='skillbox')
|
||||||
self.assertEqual(school_class.name, 'skillbox')
|
self.assertEqual(school_class.name, 'skillbox')
|
||||||
id = to_global_id('SchoolClassNode', school_class.id)
|
id = to_global_id('SchoolClassNode', school_class.id)
|
||||||
mutation = get_graphql_mutation('updateSchoolClass.gql')
|
|
||||||
|
|
||||||
result = self.client.execute(mutation, variables={
|
result = self.client.execute(UPDATE_SCHOOL_CLASS_MUTATION, variables={
|
||||||
'input': {
|
'input': {
|
||||||
'id': id,
|
'id': id,
|
||||||
'name': class_name
|
'name': class_name
|
||||||
|
|
@ -85,15 +69,30 @@ class ModifySchoolClassTest(TestCase):
|
||||||
school_class = get_object(SchoolClass, id)
|
school_class = get_object(SchoolClass, id)
|
||||||
self.assertEqual(school_class.name, class_name)
|
self.assertEqual(school_class.name, class_name)
|
||||||
|
|
||||||
|
def test_update_school_class_not_in_class_fails(self):
|
||||||
|
client = Client(schema=schema)
|
||||||
|
teacher = TeacherFactory(username='conan')
|
||||||
|
context = Context(user=teacher)
|
||||||
|
school_class = SchoolClass.objects.get(name='skillbox')
|
||||||
|
self.assertEqual(school_class.name, 'skillbox')
|
||||||
|
id = to_global_id('SchoolClassNode', school_class.id)
|
||||||
|
variables = {
|
||||||
|
'input': {
|
||||||
|
'id': id,
|
||||||
|
'name': 'Nein'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = client.execute(UPDATE_SCHOOL_CLASS_MUTATION, variables=variables, context=context)
|
||||||
|
self.assertIsNone(result.get('errors'))
|
||||||
|
|
||||||
def test_update_school_class_fail(self):
|
def test_update_school_class_fail(self):
|
||||||
class_name = 'Nanana'
|
class_name = 'Nanana'
|
||||||
|
|
||||||
school_class = SchoolClass.objects.get(name='skillbox')
|
school_class = SchoolClass.objects.get(name='skillbox')
|
||||||
self.assertEqual(school_class.name, 'skillbox')
|
self.assertEqual(school_class.name, 'skillbox')
|
||||||
id = to_global_id('SchoolClassNode', school_class.id)
|
id = to_global_id('SchoolClassNode', school_class.id)
|
||||||
mutation = get_graphql_mutation('updateSchoolClass.gql')
|
|
||||||
|
|
||||||
result = self.student_client.execute(mutation, variables={
|
result = self.student_client.execute(UPDATE_SCHOOL_CLASS_MUTATION, variables={
|
||||||
'input': {
|
'input': {
|
||||||
'id': id,
|
'id': id,
|
||||||
'name': class_name
|
'name': class_name
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from graphene import Context
|
from graphene import Context
|
||||||
from graphene.test import Client
|
from graphene.test import Client
|
||||||
|
from graphql_relay import to_global_id
|
||||||
|
|
||||||
from api.schema import schema
|
from api.schema import schema
|
||||||
from api.utils import get_graphql_mutation
|
from api.utils import get_graphql_mutation
|
||||||
|
|
@ -21,6 +22,7 @@ ME_QUERY = """
|
||||||
|
|
||||||
CREATE_TEAM_MUTATION = get_graphql_mutation('createTeam.gql')
|
CREATE_TEAM_MUTATION = get_graphql_mutation('createTeam.gql')
|
||||||
JOIN_TEAM_MUTATION = get_graphql_mutation('joinTeam.gql')
|
JOIN_TEAM_MUTATION = get_graphql_mutation('joinTeam.gql')
|
||||||
|
UPDATE_TEAM_MUTATION = get_graphql_mutation('updateTeam.gql')
|
||||||
|
|
||||||
|
|
||||||
class TeamTest(TestCase):
|
class TeamTest(TestCase):
|
||||||
|
|
@ -29,6 +31,7 @@ class TeamTest(TestCase):
|
||||||
self.team_name = 'Fiterativ'
|
self.team_name = 'Fiterativ'
|
||||||
self.code = 'AAAA'
|
self.code = 'AAAA'
|
||||||
self.team = TeamFactory(name=self.team_name, code=self.code)
|
self.team = TeamFactory(name=self.team_name, code=self.code)
|
||||||
|
self.team_id = to_global_id('TeamNode', self.team.id)
|
||||||
self.user = TeacherFactory(username='ueli', team=self.team)
|
self.user = TeacherFactory(username='ueli', team=self.team)
|
||||||
self.student = UserFactory(username='fritzli')
|
self.student = UserFactory(username='fritzli')
|
||||||
self.context = Context(user=self.user)
|
self.context = Context(user=self.user)
|
||||||
|
|
@ -43,7 +46,7 @@ class TeamTest(TestCase):
|
||||||
def permission_error(self, result):
|
def permission_error(self, result):
|
||||||
errors = result.get('errors')
|
errors = result.get('errors')
|
||||||
self.assertIsNotNone(errors)
|
self.assertIsNotNone(errors)
|
||||||
self.assertIn('permission', errors[0]['message'])
|
self.assertIn('Permission denied', errors[0]['message'])
|
||||||
|
|
||||||
def check_me(self, context, name, code):
|
def check_me(self, context, name, code):
|
||||||
result = self.client.execute(ME_QUERY, context=context)
|
result = self.client.execute(ME_QUERY, context=context)
|
||||||
|
|
@ -99,6 +102,50 @@ class TeamTest(TestCase):
|
||||||
self.assertEqual(team.get('name'), team_name)
|
self.assertEqual(team.get('name'), team_name)
|
||||||
self.assertIsNotNone(team.get('code'))
|
self.assertIsNotNone(team.get('code'))
|
||||||
|
|
||||||
|
def test_update_team_name(self):
|
||||||
|
new_name = 'Team Böhmermann'
|
||||||
|
variables = {
|
||||||
|
"input": {
|
||||||
|
"name": new_name,
|
||||||
|
"id": self.team_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = self.client.execute(UPDATE_TEAM_MUTATION, context=self.context, variables=variables)
|
||||||
|
self.no_error(result)
|
||||||
|
update_team = result.get('data').get('updateTeam')
|
||||||
|
team = update_team.get('team')
|
||||||
|
success = update_team.get('success')
|
||||||
|
self.assertTrue(success)
|
||||||
|
self.assertEqual(team.get('name'), new_name)
|
||||||
|
|
||||||
|
def test_update_team_name_as_student_fails(self):
|
||||||
|
context = Context(user=self.student)
|
||||||
|
variables = {
|
||||||
|
"input": {
|
||||||
|
"name": 'Not gonna happen',
|
||||||
|
"id": self.team_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = self.client.execute(UPDATE_TEAM_MUTATION, context=context, variables=variables)
|
||||||
|
self.permission_error(result)
|
||||||
|
|
||||||
|
def test_update_team_name_not_in_team_fails(self):
|
||||||
|
schelm = TeacherFactory(username='schelm')
|
||||||
|
context = Context(user=schelm)
|
||||||
|
team = Team.objects.get(pk=self.team.pk)
|
||||||
|
old_name = team.name
|
||||||
|
self.assertFalse(self.team.members.filter(pk=schelm.pk).exists())
|
||||||
|
variables = {
|
||||||
|
"input": {
|
||||||
|
"name": 'Not gonna happen',
|
||||||
|
"id": self.team_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = self.client.execute(UPDATE_TEAM_MUTATION, context=context, variables=variables)
|
||||||
|
self.permission_error(result)
|
||||||
|
team = Team.objects.get(pk=self.team.pk)
|
||||||
|
self.assertEqual(team.name, old_name)
|
||||||
|
|
||||||
def test_create_team_mutation_as_student_fails(self):
|
def test_create_team_mutation_as_student_fails(self):
|
||||||
self.assertEqual(Team.objects.count(), 1)
|
self.assertEqual(Team.objects.count(), 1)
|
||||||
variables = {
|
variables = {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue