From f56de914d519a74e2c53851d06f4fa73d8e89a95 Mon Sep 17 00:00:00 2001 From: Greg Price Date: Wed, 12 Mar 2014 17:58:31 -0400 Subject: [PATCH] Do not allow students to pin/unpin forum threads The wrong permission was being checked for pinning/unpinning, so a sufficiently clever student could pin and unpin threads. JIRA: FOR-499 --- .../django_comment_client/base/tests.py | 48 +++++++++++++++++++ .../django_comment_client/base/views.py | 3 ++ .../django_comment_client/permissions.py | 4 +- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/django_comment_client/base/tests.py b/lms/djangoapps/django_comment_client/base/tests.py index 1e58e75606..4495e648d9 100644 --- a/lms/djangoapps/django_comment_client/base/tests.py +++ b/lms/djangoapps/django_comment_client/base/tests.py @@ -10,6 +10,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from django.core.urlresolvers import reverse from django.core.management import call_command from util.testing import UrlResetMixin +from django_comment_common.models import Role from django_comment_common.utils import seed_permissions_roles from django_comment_client.base import views from django_comment_client.tests.unicode import UnicodeTestMixin @@ -519,6 +520,53 @@ class ViewsTestCase(UrlResetMixin, ModuleStoreTestCase): assert_equal(response.status_code, 200) +@patch("lms.lib.comment_client.utils.requests.request") +@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) +class ViewPermissionsTestCase(UrlResetMixin, ModuleStoreTestCase): + @patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True}) + def setUp(self): + super(ViewPermissionsTestCase, self).setUp() + self.password = "test password" + self.course = CourseFactory.create() + seed_permissions_roles(self.course.id) + self.student = UserFactory.create(password=self.password) + self.moderator = UserFactory.create(password=self.password) + CourseEnrollmentFactory(user=self.student, course_id=self.course.id) + CourseEnrollmentFactory(user=self.moderator, course_id=self.course.id) + self.moderator.roles.add(Role.objects.get(name="Moderator", course_id=self.course.id)) + + def test_pin_thread_as_student(self, mock_request): + mock_request.return_value.text = "{}" + self.client.login(username=self.student.username, password=self.password) + response = self.client.post( + reverse("pin_thread", kwargs={"course_id": self.course.id, "thread_id": "dummy"}) + ) + self.assertEqual(response.status_code, 401) + + def test_pin_thread_as_moderator(self, mock_request): + mock_request.return_value.text = "{}" + self.client.login(username=self.moderator.username, password=self.password) + response = self.client.post( + reverse("pin_thread", kwargs={"course_id": self.course.id, "thread_id": "dummy"}) + ) + self.assertEqual(response.status_code, 200) + + def test_un_pin_thread_as_student(self, mock_request): + mock_request.return_value.text = "{}" + self.client.login(username=self.student.username, password=self.password) + response = self.client.post( + reverse("un_pin_thread", kwargs={"course_id": self.course.id, "thread_id": "dummy"}) + ) + self.assertEqual(response.status_code, 401) + + def test_un_pin_thread_as_moderator(self, mock_request): + mock_request.return_value.text = "{}" + self.client.login(username=self.moderator.username, password=self.password) + response = self.client.post( + reverse("un_pin_thread", kwargs={"course_id": self.course.id, "thread_id": "dummy"}) + ) + self.assertEqual(response.status_code, 200) + @override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE) class CreateThreadUnicodeTestCase(ModuleStoreTestCase, UnicodeTestMixin): diff --git a/lms/djangoapps/django_comment_client/base/views.py b/lms/djangoapps/django_comment_client/base/views.py index 3e571f46d7..c479e6f65a 100644 --- a/lms/djangoapps/django_comment_client/base/views.py +++ b/lms/djangoapps/django_comment_client/base/views.py @@ -431,6 +431,9 @@ def pin_thread(request, course_id, thread_id): return JsonResponse(utils.safe_content(thread.to_dict())) +@require_POST +@login_required +@permitted def un_pin_thread(request, course_id, thread_id): """ given a course id and thread id, remove pin from this thread diff --git a/lms/djangoapps/django_comment_client/permissions.py b/lms/djangoapps/django_comment_client/permissions.py index 4003dfb460..5814c8fbdc 100644 --- a/lms/djangoapps/django_comment_client/permissions.py +++ b/lms/djangoapps/django_comment_client/permissions.py @@ -94,8 +94,8 @@ VIEW_PERMISSIONS = { 'flag_abuse_for_comment': [['vote', 'is_open']], 'un_flag_abuse_for_comment': [['vote', 'is_open']], 'undo_vote_for_thread': [['unvote', 'is_open']], - 'pin_thread': ['create_comment'], - 'un_pin_thread': ['create_comment'], + 'pin_thread': ['openclose_thread'], + 'un_pin_thread': ['openclose_thread'], 'follow_thread': ['follow_thread'], 'follow_commentable': ['follow_commentable'], 'follow_user': ['follow_user'],