From 706e7ccdc611b3e21246117f63796b33566c0c05 Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Sun, 27 Oct 2019 18:17:08 -0500 Subject: [PATCH] Add tests for permission --- course/constants.py | 1 + course/forms.py | 4 +- .../0114_add_use_forms_permission.py | 34 +++++++++++ tests/base_test_mixins.py | 4 +- tests/test_forms.py | 59 +++++++++++++++++-- 5 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 course/migrations/0114_add_use_forms_permission.py diff --git a/course/constants.py b/course/constants.py index 36e671c17..c6197d959 100644 --- a/course/constants.py +++ b/course/constants.py @@ -130,6 +130,7 @@ class participation_permission: # noqa use_git_endpoint = "use_git_endpoint" use_markup_sandbox = "use_markup_sandbox" use_page_sandbox = "use_page_sandbox" + use_forms = "use_forms" test_flow = "test_flow" edit_events = "edit_events" diff --git a/course/forms.py b/course/forms.py index 7ce823e48..d357006f4 100644 --- a/course/forms.py +++ b/course/forms.py @@ -181,7 +181,7 @@ def get_all_forms(repo, commit_sha): @course_view def view_all_forms(pctx): - if not pctx.has_permission(pperm.update_content): + if not pctx.has_permission(pperm.use_forms): raise PermissionDenied() forms = get_all_forms(pctx.repo, pctx.course_commit_sha) @@ -193,7 +193,7 @@ def view_all_forms(pctx): @course_view def view_form(pctx, form_id): - if not pctx.has_permission(pperm.update_content): + if not pctx.has_permission(pperm.use_forms): raise PermissionDenied() form_info = get_form(pctx.repo, form_id, pctx.course_commit_sha) diff --git a/course/migrations/0114_add_use_forms_permission.py b/course/migrations/0114_add_use_forms_permission.py new file mode 100644 index 000000000..3ecec7be4 --- /dev/null +++ b/course/migrations/0114_add_use_forms_permission.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- + +from __future__ import unicode_literals + +from django.db import migrations + +def add_use_forms_permission(apps, schema_editor): + from course.constants import participation_permission as pperm + + ParticipationRolePermission = apps.get_model("course", "ParticipationRolePermission") # noqa + + roles_pks = ( + ParticipationRolePermission.objects.filter( + permission=pperm.edit_course) + .values_list("role", flat=True) + ) + + if roles_pks.count(): + for pk in roles_pks: + ParticipationRolePermission.objects.get_or_create( + role_id=pk, + permission=pperm.use_forms + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('course', '0113_merge_20190919_1408'), + ] + + operations = [ + migrations.RunPython(add_use_forms_permission) + ] diff --git a/tests/base_test_mixins.py b/tests/base_test_mixins.py index 03ddd3407..f19cf613d 100644 --- a/tests/base_test_mixins.py +++ b/tests/base_test_mixins.py @@ -823,10 +823,10 @@ def create_course(cls, create_course_kwargs, raise_error=True): assert Course.objects.count() == existing_course_count + 1 @classmethod - def get_course_view_url(cls, view_name, course_identifier=None): + def get_course_view_url(cls, view_name, course_identifier=None, *args): course_identifier = ( course_identifier or cls.get_default_course_identifier()) - return reverse(view_name, args=[course_identifier]) + return reverse(view_name, args=[course_identifier] + list(args)) @classmethod def get_course_calender_url(cls, course_identifier=None): diff --git a/tests/test_forms.py b/tests/test_forms.py index 219b81970..723ef7103 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -27,7 +27,10 @@ from course.forms import process_form_fields, CreateForm from course.validation import ValidationError +from course.constants import participation_permission as pperm from relate.utils import dict_to_struct +from tests import factories +from course.models import ParticipationRolePermission, ParticipationRole from tests.base_test_mixins import SingleCourseTestMixin, MockAddMessageMixing @@ -125,15 +128,63 @@ def test_create_form(self): self.assertIn(form.id, form.get_jinja_text()[0]) -class ViewAllFormsTest(SingleCourseTestMixin, MockAddMessageMixing, TestCase): +class FormsBase(SingleCourseTestMixin, MockAddMessageMixing, TestCase): + + initial_commit_sha = "f3e9d31a61714e759a6ea12b900b173accb753f5" + form_title = b"Create an instant flow with one multiple choice question" + + def get_user_with_no_forms(self): + # This user has no form with access, but has access to viewing the + # forms list. + limited_instructor = factories.UserFactory() + limited_instructor_role = factories.ParticipationRoleFactory( + course=self.course, + identifier="limited_instructor" + ) + participation = factories.ParticipationFactory( + course=self.course, + user=limited_instructor) + participation.roles.set([limited_instructor_role]) + ParticipationRolePermission(role=limited_instructor_role, + permission=pperm.use_forms).save() + return limited_instructor + + +class ViewAllFormsTest(FormsBase): def test_student_no_form_access(self): with self.temporarily_switch_to_user(self.student_participation.user): - print(self.get_course_page_url()) resp = self.c.get(self.get_view_all_forms_url()) self.assertEqual(resp.status_code, 403) - def test_instructor_forms_access(self): - with self.temporarily_switch_to_user(self.instructor_participation.user): + def test_use_forms_permission(self): + with self.temporarily_switch_to_user(self.get_user_with_no_forms()): resp = self.c.get(self.get_view_all_forms_url()) self.assertEqual(resp.status_code, 200) + self.assertIn(self.form_title, resp.content) + + +class ViewFormTest(FormsBase): + + def test_student_no_form_access(self): + with self.temporarily_switch_to_user(self.student_participation.user): + resp = self.c.get(self.get_view_form_url(form_id="instant")) + self.assertEqual(resp.status_code, 403) + + def test_user_with_no_forms(self): + with self.temporarily_switch_to_user(self.get_user_with_no_forms()): + resp = self.c.get(self.get_view_form_url(form_id="instant")) + self.assertEqual(resp.status_code, 403) + + def get_instructor_with_perm(self): + role = ParticipationRole.objects.filter( + identifier="instructor", + ).first() + ParticipationRolePermission(role=role, + permission=pperm.use_forms).save() + return self.instructor_participation.user + + def test_instructor_form_access(self): + with self.temporarily_switch_to_user(self.get_instructor_with_perm()): + resp = self.c.get(self.get_view_form_url(form_id="instant")) + self.assertEqual(resp.status_code, 200)