diff --git a/server/users/mutations.py b/server/users/mutations.py index f1238497..abe2771f 100644 --- a/server/users/mutations.py +++ b/server/users/mutations.py @@ -209,7 +209,19 @@ class CreateSchoolClass(relay.ClientIDMutation): return cls(success=True, school_class=school_class) -class CreateTeam(relay.ClientIDMutation): +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 Input: name = graphene.String(required=True) @@ -221,9 +233,6 @@ class CreateTeam(relay.ClientIDMutation): name = kwargs.get('name') user = info.context.user - if 'users.can_manage_school_class_content' not in user.get_role_permissions(): - raise PermissionError() - team = Team.objects.create(name=name, creator=user) team.generate_code() user.team = team @@ -231,7 +240,7 @@ class CreateTeam(relay.ClientIDMutation): return cls(success=True, team=team) -class JoinTeam(relay.ClientIDMutation): +class JoinTeam(TeacherOnlyMutation): class Input: code = graphene.String(required=True) diff --git a/server/users/schema.py b/server/users/schema.py index 5149d97d..08937a03 100644 --- a/server/users/schema.py +++ b/server/users/schema.py @@ -12,7 +12,7 @@ from graphql_relay import to_global_id from basicknowledge.models import BasicKnowledge from basicknowledge.queries import InstrumentNode from books.models import Module -from books.schema.queries import ModuleNode +from books.schema.nodes import ModuleNode from users.models import User, SchoolClass, SchoolClassMember, Team @@ -52,6 +52,9 @@ class TeamNode(DjangoObjectType): def resolve_pk(self, *args, **kwargs): return self.id + def resolve_members(self, *args, **kwargs): + return self.members.all() + class RecentModuleFilter(FilterSet): class Meta: diff --git a/server/users/tests/test_teams.py b/server/users/tests/test_teams.py index f6ebe69e..3cd879ec 100644 --- a/server/users/tests/test_teams.py +++ b/server/users/tests/test_teams.py @@ -3,8 +3,10 @@ from graphene import Context from graphene.test import Client from api.schema import schema -from core.factories import TeacherFactory +from api.utils import get_graphql_mutation +from core.factories import TeacherFactory, UserFactory from users.factories import TeamFactory +from users.models import Team ME_QUERY = """ query MeQuery { @@ -17,29 +19,8 @@ ME_QUERY = """ } """ -CREATE_MUTATION = """ - mutation CreateTeamMutation($input: CreateTeamInput!) { - createTeam(input: $input) { - success - team { - name - code - } - } - } -""" - -JOIN_TEAM_MUTATION = """ -mutation JoinTeamMutation($input: JoinTeamInput!) { - joinTeam(input: $input) { - success - team { - name - code - } - } -} -""" +CREATE_TEAM_MUTATION = get_graphql_mutation('createTeam.gql') +JOIN_TEAM_MUTATION = get_graphql_mutation('joinTeam.gql') class TeamTest(TestCase): @@ -49,6 +30,7 @@ class TeamTest(TestCase): self.code = 'AAAA' self.team = TeamFactory(name=self.team_name, code=self.code) self.user = TeacherFactory(username='ueli', team=self.team) + self.student = UserFactory(username='fritzli') self.context = Context(user=self.user) @staticmethod @@ -58,6 +40,11 @@ class TeamTest(TestCase): def no_error(self, result): self.assertIsNone(result.get('errors')) + def permission_error(self, result): + errors = result.get('errors') + self.assertIsNotNone(errors) + self.assertIn('permission', errors[0]['message']) + def check_me(self, context, name, code): result = self.client.execute(ME_QUERY, context=context) self.no_error(result) @@ -103,7 +90,7 @@ class TeamTest(TestCase): "name": team_name } } - result = self.client.execute(CREATE_MUTATION, context=self.context, variables=variables) + result = self.client.execute(CREATE_TEAM_MUTATION, context=self.context, variables=variables) self.no_error(result) create_team = result.get('data').get('createTeam') team = create_team.get('team') @@ -111,3 +98,27 @@ class TeamTest(TestCase): self.assertTrue(success) self.assertEqual(team.get('name'), team_name) self.assertIsNotNone(team.get('code')) + + def test_create_team_mutation_as_student_fails(self): + self.assertEqual(Team.objects.count(), 1) + variables = { + "input": { + "name": 'Nope' + } + } + context = Context(user=self.student) + result = self.client.execute(CREATE_TEAM_MUTATION, context=context, variables=variables) + self.permission_error(result) + self.assertEqual(Team.objects.count(), 1) + + def test_join_create_team_mutation_as_student_fails(self): + self.assertIsNone(self.student.team) + variables = { + "input": { + "code": 'ZZZZ' + } + } + context = Context(user=self.student) + result = self.client.execute(JOIN_TEAM_MUTATION, context=context, variables=variables) + self.permission_error(result) + self.assertIsNone(self.student.team)