Skip to content

Commit

Permalink
add PostModerateView to unapprove a post by staff user
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentporte committed Feb 26, 2025
1 parent 7b692a6 commit a5135ba
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 4 deletions.
134 changes: 134 additions & 0 deletions lacommunaute/forum_conversation/tests/tests_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,140 @@ def test_redirection(self):
self.assertTrue(view.success_message, msgs._queued_messages[0].message)


class TestPostModerateView:
def get_post_moderate_url(self, topic):
return reverse(
"forum_conversation_extension:post_moderate",
kwargs={
"forum_slug": topic.forum.slug,
"forum_pk": topic.forum.pk,
"slug": topic.slug,
"pk": topic.pk,
},
)

@pytest.mark.parametrize(
"method,status_code", [("post", 302), ("get", 405), ("put", 405), ("delete", 405), ("patch", 405)]
)
def test_allowed_method(self, client, db, method, status_code, public_forum_with_topic):
topic = public_forum_with_topic.topics.first()
client.force_login(UserFactory(is_staff=True))
response = getattr(client, method)(self.get_post_moderate_url(topic), data={"post_pk": topic.last_post.pk})
assert response.status_code == status_code

@pytest.mark.parametrize(
"user,topic,status_code",
[
(
lambda: UserFactory(is_staff=True),
lambda: TopicFactory(with_post=True, forum=ForumFactory(with_public_perms=True)),
302,
),
(lambda: UserFactory(is_staff=True), lambda: TopicFactory(with_post=True), 403),
(
lambda: UserFactory(),
lambda: TopicFactory(with_post=True, forum=ForumFactory(with_public_perms=True)),
403,
),
(None, lambda: TopicFactory(with_post=True, forum=ForumFactory(with_public_perms=True)), 403),
],
)
def test_user_permission(self, client, db, user, topic, status_code):
topic = topic()
if user:
client.force_login(user())
response = client.post(self.get_post_moderate_url(topic), data={"post_pk": topic.last_post.pk})
assert response.status_code == status_code

@pytest.mark.parametrize(
"topic,expected_url",
[
(
lambda: TopicFactory(with_post=True, forum=ForumFactory(with_public_perms=True)),
lambda topic: reverse("forum_conversation_extension:topics"),
),
(
lambda: TopicFactory(
with_post=True, forum=ForumFactory(with_public_perms=True, parent=CategoryForumFactory())
),
lambda topic: reverse(
"forum_extension:forum", kwargs={"slug": topic.forum.slug, "pk": topic.forum.pk}
),
),
(
lambda: TopicFactory(with_post=True, answered=True, forum=ForumFactory(with_public_perms=True)),
lambda topic: reverse(
"forum_conversation:topic",
kwargs={
"forum_slug": topic.forum.slug,
"forum_pk": topic.forum.pk,
"slug": topic.slug,
"pk": topic.pk,
},
),
),
],
)
def test_redirection(self, client, db, topic, expected_url):
topic = topic()
expected_url = expected_url(topic=topic)
client.force_login(UserFactory(is_staff=True))
response = client.post(self.get_post_moderate_url(topic), data={"post_pk": topic.last_post.pk})
assert response.url == expected_url

@pytest.mark.parametrize(
"post_exists,kwargs,status_code",
[
(
True,
lambda topic: {
"forum_slug": topic.forum.slug,
"forum_pk": topic.forum.pk,
"slug": topic.slug,
"pk": topic.pk,
},
302,
),
(
False,
{
"forum_slug": faker.slug(),
"forum_pk": 99999,
"slug": faker.slug(),
"pk": 99999,
},
404,
),
],
)
def test_post_existence(self, client, db, post_exists, kwargs, status_code, public_forum_with_topic):
if post_exists:
topic = public_forum_with_topic.topics.first()
kwargs = kwargs(topic=topic)
last_post_pk = topic.last_post.pk
else:
kwargs = kwargs
last_post_pk = 9999
client.force_login(UserFactory(is_staff=True))
url = reverse("forum_conversation_extension:post_moderate", kwargs=kwargs)
response = client.post(url, data={"post_pk": last_post_pk})
assert response.status_code == status_code

def test_pk_is_missing_in_payload(self, client, db, public_forum_with_topic):
topic = public_forum_with_topic.topics.first()
client.force_login(UserFactory(is_staff=True))
response = client.post(self.get_post_moderate_url(topic), data={})
assert response.status_code == 404

def test_post_is_unapproved(self, client, db, public_forum_with_topic):
topic = public_forum_with_topic.topics.first()
client.force_login(UserFactory(is_staff=True))
response = client.post(self.get_post_moderate_url(topic), data={"post_pk": topic.last_post.pk})
assert response.status_code == 302
topic.last_post.refresh_from_db()
assert not topic.last_post.approved


class TopicViewTest(TestCase):
@classmethod
def setUpTestData(cls):
Expand Down
3 changes: 2 additions & 1 deletion lacommunaute/forum_conversation/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.urls import include, path

from lacommunaute.forum_conversation.views import TopicListView
from lacommunaute.forum_conversation.views import PostModerateView, TopicListView
from lacommunaute.forum_conversation.views_htmx import (
CertifiedPostView,
PostFeedCreateView,
Expand All @@ -18,6 +18,7 @@
path("topic/<str:slug>-<int:pk>/showmore/certified", TopicCertifiedPostView.as_view(), name="showmore_certified"),
path("topic/<str:slug>-<int:pk>/comment", PostFeedCreateView.as_view(), name="post_create"),
path("topic/<str:slug>-<int:pk>/certify", CertifiedPostView.as_view(), name="certify"),
path("topic/<str:slug>-<int:pk>/moderate", PostModerateView.as_view(), name="post_moderate"),
]


Expand Down
62 changes: 59 additions & 3 deletions lacommunaute/forum_conversation/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@

from django.conf import settings
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.urls import reverse
from django.views.generic import ListView
from django.views.generic import ListView, View
from machina.apps.forum_conversation import views
from machina.core.loading import get_class

from lacommunaute.forum.models import Forum
from lacommunaute.forum_conversation.forms import PostForm, TopicForm
from lacommunaute.forum_conversation.models import Topic
from lacommunaute.forum_conversation.shortcuts import can_certify_post, get_posts_of_a_topic_except_first_one
from lacommunaute.forum_conversation.models import Post, Topic
from lacommunaute.forum_conversation.shortcuts import (
can_certify_post,
can_moderate_post,
get_posts_of_a_topic_except_first_one,
)
from lacommunaute.forum_conversation.view_mixins import FilteredTopicsListViewMixin
from lacommunaute.notification.models import Notification

Expand Down Expand Up @@ -78,6 +85,55 @@ def get_success_url(self):
)


class PostModerateView(View):
def dispatch(self, request, *args, **kwargs):
if request.method != "POST":
return self.http_method_not_allowed(request)

user = request.user
obj = self.get_object().topic.forum
if not (self.request.forum_permission_handler.can_read_forum(obj, user) and can_moderate_post(user)):
raise PermissionDenied

return super().dispatch(request, *args, **kwargs)

def get_object(self):
if not hasattr(self, "object"):
self.object = get_object_or_404(
Post,
pk=self.request.POST.get("post_pk", None),
)
return self.object

def post(self, request, *args, **kwargs):
post = self.get_object()
post.approved = False
post.save()
return HttpResponseRedirect(self.get_redirection_url())

def get_redirection_url(self):
messages.success(self.request, "Le message a été modéré avec succès.")
if self.object.is_topic_head:
if self.object.topic.forum.is_in_documentation_area:
return reverse(
"forum_extension:forum",
kwargs={
"slug": self.object.topic.forum.slug,
"pk": self.object.topic.forum.pk,
},
)
return reverse("forum_conversation_extension:topics")
return reverse(
"forum_conversation:topic",
kwargs={
"forum_slug": self.object.topic.forum.slug,
"forum_pk": self.object.topic.forum.pk,
"slug": self.object.topic.slug,
"pk": self.object.topic.pk,
},
)


class TopicView(views.TopicView):
def get_topic(self):
topic = super().get_topic()
Expand Down

0 comments on commit a5135ba

Please sign in to comment.