Adjust permissions, add unit tests
This commit is contained in:
parent
0eba96fd5e
commit
b0591d9c7e
|
|
@ -26,7 +26,8 @@ from users.schema import AllUsersQuery, UsersQuery, ProfileMutations
|
||||||
|
|
||||||
|
|
||||||
class Query(UsersQuery, AllUsersQuery, ModuleRoomsQuery, RoomsQuery, ObjectivesQuery, BookQuery, AssignmentsQuery,
|
class Query(UsersQuery, AllUsersQuery, ModuleRoomsQuery, RoomsQuery, ObjectivesQuery, BookQuery, AssignmentsQuery,
|
||||||
StudentSubmissionQuery, InstrumentQuery, PortfolioQuery, SurveysQuery, AllNewsTeasersQuery, graphene.ObjectType):
|
StudentSubmissionQuery, InstrumentQuery, PortfolioQuery, SurveysQuery, AllNewsTeasersQuery,
|
||||||
|
graphene.ObjectType):
|
||||||
node = relay.Node.Field()
|
node = relay.Node.Field()
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
|
|
@ -34,8 +35,8 @@ class Query(UsersQuery, AllUsersQuery, ModuleRoomsQuery, RoomsQuery, ObjectivesQ
|
||||||
|
|
||||||
|
|
||||||
class Mutation(BookMutations, RoomMutations, AssignmentMutations, ObjectiveMutations, OauthMutations,
|
class Mutation(BookMutations, RoomMutations, AssignmentMutations, ObjectiveMutations, OauthMutations,
|
||||||
PortfolioMutations, ProfileMutations, SurveyMutations, NoteMutations, SpellCheckMutations,
|
PortfolioMutations, ProfileMutations, SurveyMutations, NoteMutations, SpellCheckMutations,
|
||||||
graphene.ObjectType):
|
graphene.ObjectType):
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
debug = graphene.Field(DjangoDebug, name='_debug')
|
debug = graphene.Field(DjangoDebug, name='_debug')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ from graphql_relay import from_global_id
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied
|
||||||
|
|
||||||
from api.utils import get_object
|
from api.utils import get_object
|
||||||
from assignments.models import Assignment, SubmissionFeedback
|
from assignments.models import Assignment, StudentSubmission, SubmissionFeedback
|
||||||
from assignments.schema.types import AssignmentNode, StudentSubmissionNode, SubmissionFeedbackNode
|
from assignments.schema.types import AssignmentNode, StudentSubmissionNode, SubmissionFeedbackNode
|
||||||
from .inputs import AssignmentInput, SubmissionFeedbackInput
|
from .inputs import AssignmentInput, SubmissionFeedbackInput
|
||||||
|
|
||||||
|
|
@ -57,18 +57,23 @@ class UpdateSubmissionFeedback(relay.ClientIDMutation):
|
||||||
submission_feedback_data = kwargs.get('submission_feedback')
|
submission_feedback_data = kwargs.get('submission_feedback')
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
student_submission_id = from_global_id(submission_feedback_data['student_submission'])[1]
|
student_submission_id = from_global_id(submission_feedback_data['student_submission'])[1]
|
||||||
|
student_submission = StudentSubmission.objects.get(id=student_submission_id)
|
||||||
|
|
||||||
if not user.is_teacher():
|
if not user.is_teacher() or not student_submission.student in user.users_in_active_school_class():
|
||||||
raise PermissionDenied('Missing permissions')
|
raise PermissionDenied('Missing permissions')
|
||||||
|
|
||||||
# todo: replace with middleware
|
# todo: replace with middleware
|
||||||
if user.read_only:
|
if user.read_only:
|
||||||
raise PermissionError('No valid license')
|
raise PermissionError('No valid license')
|
||||||
|
|
||||||
(submission_feedback, created) = SubmissionFeedback.objects.get_or_create(student_submission_id=student_submission_id)
|
(submission_feedback, created) = SubmissionFeedback.objects.get_or_create(
|
||||||
|
student_submission_id=student_submission_id,
|
||||||
|
defaults={
|
||||||
|
'teacher': user
|
||||||
|
})
|
||||||
|
|
||||||
|
final = submission_feedback_data.get(
|
||||||
final = submission_feedback_data.get('final') if 'final' in submission_feedback_data else submission_feedback.final
|
'final') if 'final' in submission_feedback_data else submission_feedback.final
|
||||||
|
|
||||||
submission_feedback.teacher = user
|
submission_feedback.teacher = user
|
||||||
submission_feedback.final = final
|
submission_feedback.final = final
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import graphene
|
import graphene
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
|
|
||||||
|
from api.utils import get_object
|
||||||
|
from assignments.models import StudentSubmission
|
||||||
from assignments.schema.types import AssignmentNode, StudentSubmissionNode
|
from assignments.schema.types import AssignmentNode, StudentSubmissionNode
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -9,5 +11,14 @@ class AssignmentsQuery(object):
|
||||||
assignments = graphene.List(AssignmentNode)
|
assignments = graphene.List(AssignmentNode)
|
||||||
|
|
||||||
|
|
||||||
class StudentSubmissionQuery(object):
|
|
||||||
student_submission = relay.Node.Field(StudentSubmissionNode)
|
class StudentSubmissionQuery:
|
||||||
|
student_submission = graphene.Field(StudentSubmissionNode, id=graphene.ID(required=True))
|
||||||
|
|
||||||
|
def resolve_student_submission(root, info, *args, **kwargs):
|
||||||
|
user = info.context.user
|
||||||
|
id = kwargs.get('id')
|
||||||
|
submission = get_object(StudentSubmission, id)
|
||||||
|
if user == submission.student or (user.is_teacher() and submission.student in user.users_in_active_school_class()):
|
||||||
|
return root
|
||||||
|
return None
|
||||||
|
|
|
||||||
|
|
@ -22,19 +22,20 @@ class StudentSubmissionNode(DjangoObjectType):
|
||||||
filter_fields = []
|
filter_fields = []
|
||||||
interfaces = (relay.Node,)
|
interfaces = (relay.Node,)
|
||||||
|
|
||||||
def resolve_submission_feedback(self, info, **kwargs):
|
@staticmethod
|
||||||
|
def resolve_submission_feedback(root: StudentSubmission, info, **kwargs):
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
|
|
||||||
if not hasattr(self, 'submission_feedback'):
|
if not hasattr(root, 'submission_feedback'):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# teacher path
|
# teacher path
|
||||||
if user.is_teacher():
|
if user.is_teacher() and root.student in user.users_in_active_school_class():
|
||||||
return self.submission_feedback
|
return root.submission_feedback
|
||||||
|
|
||||||
# student path
|
# student path
|
||||||
if self.submission_feedback.final:
|
if root.submission_feedback.final:
|
||||||
return self.submission_feedback
|
return root.submission_feedback
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ class SubmissionFeedbackTestCase(SkillboxTestCase):
|
||||||
self.student_submission_id = to_global_id('StudentSubmissionNode', self.student_submission.pk)
|
self.student_submission_id = to_global_id('StudentSubmissionNode', self.student_submission.pk)
|
||||||
|
|
||||||
school_class = SchoolClassFactory()
|
school_class = SchoolClassFactory()
|
||||||
for user in [self.student1, self.teacher, self.teacher2]:
|
for user in [self.student1, self.teacher]:
|
||||||
SchoolClassMember.objects.create(
|
SchoolClassMember.objects.create(
|
||||||
user=user,
|
user=user,
|
||||||
school_class=school_class
|
school_class=school_class
|
||||||
|
|
@ -94,6 +94,24 @@ class SubmissionFeedbackTestCase(SkillboxTestCase):
|
||||||
'id': self.assignment_id
|
'id': self.assignment_id
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def _fetch_submission_teacher(self, user):
|
||||||
|
client = self.get_client(user)
|
||||||
|
query = '''
|
||||||
|
query StudentSubmission($id: ID!) {
|
||||||
|
studentSubmission(id: $id) {
|
||||||
|
id
|
||||||
|
text
|
||||||
|
document
|
||||||
|
submissionFeedback {
|
||||||
|
text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
return client.execute(query, variables={
|
||||||
|
'id': self.student_submission_id
|
||||||
|
})
|
||||||
|
|
||||||
def _fetch_submission_feedback(self, user):
|
def _fetch_submission_feedback(self, user):
|
||||||
client = create_client(user)
|
client = create_client(user)
|
||||||
query = '''
|
query = '''
|
||||||
|
|
@ -125,6 +143,8 @@ class SubmissionFeedbackTestCase(SkillboxTestCase):
|
||||||
def test_student_cannot_create_feedback(self):
|
def test_student_cannot_create_feedback(self):
|
||||||
result = self._create_submission_feedback(self.student1, False, 'Balalal', self.student_submission_id)
|
result = self._create_submission_feedback(self.student1, False, 'Balalal', self.student_submission_id)
|
||||||
self.assertIsNotNone(result.errors)
|
self.assertIsNotNone(result.errors)
|
||||||
|
self.assertEqual(len(result.errors), 1)
|
||||||
|
self.assertEqual(result.errors[0].get('message'), 'Missing permissions')
|
||||||
|
|
||||||
def test_teacher_can_update_feedback(self):
|
def test_teacher_can_update_feedback(self):
|
||||||
assignment = AssignmentFactory(
|
assignment = AssignmentFactory(
|
||||||
|
|
@ -146,7 +166,7 @@ class SubmissionFeedbackTestCase(SkillboxTestCase):
|
||||||
self.assertTrue(submission_feedback_response.get('final'))
|
self.assertTrue(submission_feedback_response.get('final'))
|
||||||
self.assertEqual(submission_feedback_response.get('text'), 'Some')
|
self.assertEqual(submission_feedback_response.get('text'), 'Some')
|
||||||
|
|
||||||
def test_rogue_teacher_cannot_update_feedback(self):
|
def test_external_teacher_cannot_update_feedback(self):
|
||||||
assignment = AssignmentFactory(
|
assignment = AssignmentFactory(
|
||||||
owner=self.teacher
|
owner=self.teacher
|
||||||
)
|
)
|
||||||
|
|
@ -183,11 +203,21 @@ class SubmissionFeedbackTestCase(SkillboxTestCase):
|
||||||
self.assertEqual(result.data.get('assignment').get('submissions')[0].get('submissionFeedback')
|
self.assertEqual(result.data.get('assignment').get('submissions')[0].get('submissionFeedback')
|
||||||
.get('text'), submission_feedback.text)
|
.get('text'), submission_feedback.text)
|
||||||
|
|
||||||
def test_rogue_teacher_cannot_see_feedback(self):
|
def test_external_teacher_cannot_see_assignment_with_feedback(self):
|
||||||
SubmissionFeedbackFactory(teacher=self.teacher, final=False,
|
SubmissionFeedbackFactory(teacher=self.teacher, final=False,
|
||||||
student_submission=self.student_submission)
|
student_submission=self.student_submission)
|
||||||
self.student_submission.final = True
|
self.student_submission.final = True
|
||||||
self.student_submission.save()
|
self.student_submission.save()
|
||||||
|
|
||||||
result = self._fetch_assignment_teacher(self.teacher2)
|
result = self._fetch_assignment_teacher(self.teacher2)
|
||||||
self.assertIsNone(result.data.get('assignment').get('submissions')[0].get('submissionFeedback'))
|
self.assertEqual(result.data.get('assignment').get('submissions'), [])
|
||||||
|
|
||||||
|
def test_external_teacher_cannot_see_feedback(self):
|
||||||
|
SubmissionFeedbackFactory(teacher=self.teacher, final=False,
|
||||||
|
student_submission=self.student_submission)
|
||||||
|
self.student_submission.final = True
|
||||||
|
self.student_submission.save()
|
||||||
|
|
||||||
|
result = self._fetch_submission_teacher(self.teacher2)
|
||||||
|
self.assertIsNone(result.errors)
|
||||||
|
self.assertIsNone(result.data.get('studentSubmission'))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue