Restrict team mutations to teachers

This commit is contained in:
Ramon Wenger 2021-03-25 16:32:09 +01:00
parent 19bcbaf168
commit ba0059d90f
3 changed files with 54 additions and 31 deletions

View File

@ -209,7 +209,19 @@ class CreateSchoolClass(relay.ClientIDMutation):
return cls(success=True, school_class=school_class) 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: class Input:
name = graphene.String(required=True) name = graphene.String(required=True)
@ -221,9 +233,6 @@ class CreateTeam(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():
raise PermissionError()
team = Team.objects.create(name=name, creator=user) team = Team.objects.create(name=name, creator=user)
team.generate_code() team.generate_code()
user.team = team user.team = team
@ -231,7 +240,7 @@ class CreateTeam(relay.ClientIDMutation):
return cls(success=True, team=team) return cls(success=True, team=team)
class JoinTeam(relay.ClientIDMutation): class JoinTeam(TeacherOnlyMutation):
class Input: class Input:
code = graphene.String(required=True) code = graphene.String(required=True)

View File

@ -12,7 +12,7 @@ from graphql_relay import to_global_id
from basicknowledge.models import BasicKnowledge from basicknowledge.models import BasicKnowledge
from basicknowledge.queries import InstrumentNode from basicknowledge.queries import InstrumentNode
from books.models import Module 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 from users.models import User, SchoolClass, SchoolClassMember, Team
@ -52,6 +52,9 @@ class TeamNode(DjangoObjectType):
def resolve_pk(self, *args, **kwargs): def resolve_pk(self, *args, **kwargs):
return self.id return self.id
def resolve_members(self, *args, **kwargs):
return self.members.all()
class RecentModuleFilter(FilterSet): class RecentModuleFilter(FilterSet):
class Meta: class Meta:

View File

@ -3,8 +3,10 @@ from graphene import Context
from graphene.test import Client from graphene.test import Client
from api.schema import schema 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.factories import TeamFactory
from users.models import Team
ME_QUERY = """ ME_QUERY = """
query MeQuery { query MeQuery {
@ -17,29 +19,8 @@ ME_QUERY = """
} }
""" """
CREATE_MUTATION = """ CREATE_TEAM_MUTATION = get_graphql_mutation('createTeam.gql')
mutation CreateTeamMutation($input: CreateTeamInput!) { JOIN_TEAM_MUTATION = get_graphql_mutation('joinTeam.gql')
createTeam(input: $input) {
success
team {
name
code
}
}
}
"""
JOIN_TEAM_MUTATION = """
mutation JoinTeamMutation($input: JoinTeamInput!) {
joinTeam(input: $input) {
success
team {
name
code
}
}
}
"""
class TeamTest(TestCase): class TeamTest(TestCase):
@ -49,6 +30,7 @@ class TeamTest(TestCase):
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.user = TeacherFactory(username='ueli', team=self.team) self.user = TeacherFactory(username='ueli', team=self.team)
self.student = UserFactory(username='fritzli')
self.context = Context(user=self.user) self.context = Context(user=self.user)
@staticmethod @staticmethod
@ -58,6 +40,11 @@ class TeamTest(TestCase):
def no_error(self, result): def no_error(self, result):
self.assertIsNone(result.get('errors')) 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): def check_me(self, context, name, code):
result = self.client.execute(ME_QUERY, context=context) result = self.client.execute(ME_QUERY, context=context)
self.no_error(result) self.no_error(result)
@ -103,7 +90,7 @@ class TeamTest(TestCase):
"name": team_name "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) self.no_error(result)
create_team = result.get('data').get('createTeam') create_team = result.get('data').get('createTeam')
team = create_team.get('team') team = create_team.get('team')
@ -111,3 +98,27 @@ class TeamTest(TestCase):
self.assertTrue(success) self.assertTrue(success)
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_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)