diff --git a/client/src/pages/project.vue b/client/src/pages/project.vue index 21291be3..0765f7a3 100644 --- a/client/src/pages/project.vue +++ b/client/src/pages/project.vue @@ -13,7 +13,7 @@
- +
@@ -23,6 +23,7 @@ import ProjectEntry from '@/components/portfolio/ProjectEntry'; import AddProjectEntry from '@/components/portfolio/AddProjectEntry'; + import ME_QUERY from '@/graphql/gql/meQuery.gql'; import PROJECT_QUERY from '@/graphql/gql/projectQuery.gql'; export default { @@ -40,7 +41,10 @@ specialContainerClass() { const cls = this.project.appearance; return [cls ? `project--${cls}` : '']; - } + }, + isOwner() { + return this.me.id === this.project.student.id; + } }, apollo: { @@ -56,12 +60,22 @@ this.$store.dispatch('setSpecialContainerClass', project.appearance); return project; } + }, + me: { + query: ME_QUERY } }, data() { return { - project: {} + project: { + student: { + id: ' ' + } + }, + me: { + id: '' + } } }, diff --git a/server/portfolio/mutations.py b/server/portfolio/mutations.py index 8e6dee3f..6bd4aa28 100644 --- a/server/portfolio/mutations.py +++ b/server/portfolio/mutations.py @@ -90,11 +90,17 @@ class MutateProjectEntry(relay.ClientIDMutation): project_entry = graphene.Field(ProjectEntryNode) @classmethod - def mutate_and_get_payload(cls, *args, **kwargs): + def mutate_and_get_payload(cls, root, info, **kwargs): data = kwargs.get('project_entry') + project = None if data.get('project') is not None: - data['project'] = get_object(Project, data.get('project')).id + project = get_object(Project, data.get('project')) + data['project'] = project.id + + if info.context.user.id != project.student.id: + return cls(project_entry=None, errors=['not allowed']) + if data.get('id') is not None: entity = get_object(ProjectEntry, data['id']) serializer = ProjectEntrySerializer(entity, data=data, partial=True) diff --git a/server/portfolio/tests/test_project_entry_mutations.py b/server/portfolio/tests/test_project_entry_mutations.py new file mode 100644 index 00000000..092bd730 --- /dev/null +++ b/server/portfolio/tests/test_project_entry_mutations.py @@ -0,0 +1,64 @@ +from django.test import TestCase, RequestFactory +from graphene.test import Client +from graphql_relay import to_global_id + +from api.schema import schema +from portfolio.factories import ProjectFactory +from users.factories import SchoolClassFactory +from users.models import User +from users.services import create_users +from api.test_utils import create_client, DefaultUserTestCase +from portfolio.models import Project, ProjectEntry + + +class ProjectMutationsTestCase(DefaultUserTestCase): + + def setUp(self): + create_users() + self.teacher = User.objects.get(username='teacher') + self.teacher2 = User.objects.get(username='teacher2') + self.student = User.objects.get(username='student1') + self.student2 = User.objects.get(username='student2') + self.project1 = ProjectFactory(student=self.student) + + self.mutation = ''' + mutation AddProjectEntryMutation($input: AddProjectEntryInput!) { + addProjectEntry(input: $input) { + projectEntry { + id + activity + reflection + nextSteps + created + } + errors + } + } + ''' + + self.variables = { + 'input': { + 'projectEntry': { + 'project': to_global_id('ProjectNode', self.project1.id), + 'activity': 'testactivity', + 'nextSteps': 'teststep', + 'reflection': 'testreflection' + } + } + } + + def test_add_project_entry(self): + client = create_client(self.student) + self.assertEqual(ProjectEntry.objects.count(), 0) + result = client.execute(self.mutation, variables=self.variables) + self.assertIsNone(result.get('errors')) + self.assertEqual(ProjectEntry.objects.count(), 1) + project_entry = ProjectEntry.objects.first() + self.assertEqual(project_entry.activity, 'testactivity') + + def test_should_not_be_able_to_add_entry_as_other_person(self): + client = create_client(self.student2) + self.assertEqual(ProjectEntry.objects.count(), 0) + result = client.execute(self.mutation, variables=self.variables) + self.assertIsNone(result.get('errors')) + self.assertEqual(ProjectEntry.objects.count(), 0)