Skip to content

Commit

Permalink
fix(mp): Throws a 403 exception when a user try to quote a wrong post.
Browse files Browse the repository at this point in the history
1. Creates a decorator.py file in the mp module.
2. Adds the method is_participant to apply checks on view.
3. Adds this permission on the view PrivatePostAnswer.
4. Adds a test case.
  • Loading branch information
GerardPaligot committed May 4, 2015
1 parent e0d295f commit e4c7cd2
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
23 changes: 23 additions & 0 deletions zds/mp/decorator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# coding: utf-8

from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404
from zds.mp.models import PrivateTopic, PrivatePost


def is_participant(func):
"""
Checks if the current user is a participant of the private topic specified in the URL
and if the post specified in the GET parameter `cite` is on the private topic.
:param func: the decorated function
:return: `True` if the current user can read and write, `False` otherwise.
"""
def _is_participant(request, *args, **kwargs):
private_topic = get_object_or_404(PrivateTopic, pk=kwargs.get('pk'))
if not request.user == private_topic.author and request.user not in list(private_topic.participants.all()):
raise PermissionDenied
if 'cite' in request.GET:
if PrivatePost.objects.filter(privatetopic=private_topic).filter(pk=request.GET.get('cite')).count() != 1:
raise PermissionDenied
return func(request, *args, **kwargs)
return _is_participant
19 changes: 19 additions & 0 deletions zds/mp/tests/tests_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,25 @@ def test_fail_cite_post_no_exist(self):

self.assertEqual(404, response.status_code)

def test_fail_cite_post_not_in_current_topic(self):
another_topic = PrivateTopicFactory(author=self.profile2.user)
another_post = PrivatePostFactory(
privatetopic=another_topic,
author=self.profile2.user,
position_in_topic=1)

response = self.client.get(reverse('private-posts-new', args=[self.topic1.pk, self.topic1.slug()]) +
'?cite={}'.format(another_post.pk))

self.assertEqual(403, response.status_code)

def test_success_cite_post(self):

response = self.client.get(reverse('private-posts-new', args=[self.topic1.pk, self.topic1.slug()]) +
'?cite={}'.format(self.post2.pk))

self.assertEqual(200, response.status_code)

def test_success_preview_answer(self):

response = self.client.post(
Expand Down
5 changes: 2 additions & 3 deletions zds/mp/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from django.utils.translation import ugettext as _

from zds.member.models import Profile
from zds.mp.decorator import is_participant
from zds.utils.mps import send_mp
from zds.utils.paginator import ZdSPagingListView
from zds.utils.templatetags.emarkdown import emarkdown
Expand Down Expand Up @@ -287,6 +288,7 @@ class PrivatePostAnswer(CreateView):
queryset = PrivateTopic.objects.all()

@method_decorator(login_required)
@method_decorator(is_participant)
def dispatch(self, request, *args, **kwargs):
return super(PrivatePostAnswer, self).dispatch(request, *args, **kwargs)

Expand All @@ -296,9 +298,6 @@ def get_object(self, queryset=None):
.filter(privatetopic=self.topic) \
.prefetch_related() \
.order_by("-pubdate")[:settings.ZDS_APP['forum']['posts_per_page']]
if not self.request.user == self.topic.author \
and self.request.user not in list(self.topic.participants.all()):
raise PermissionDenied
return self.topic

def get(self, request, *args, **kwargs):
Expand Down

0 comments on commit e4c7cd2

Please sign in to comment.