Skip to content

Commit

Permalink
N'envoie pas de MP lors de la dépublication de contenu sans auteur in…
Browse files Browse the repository at this point in the history
…scrit (#6356)

* N'envoie pas de MP lors de la dépublication de contenu sans auteur inscrit

Fix #6353

* Ne garde *que* les destinataires non-bots des MP de validations
  • Loading branch information
philippemilink authored Jul 24, 2022
1 parent b4d2d08 commit d4471a7
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 105 deletions.
10 changes: 10 additions & 0 deletions zds/mp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ def is_reachable(user):
return settings.ZDS_APP["member"]["bot_group"] not in user_group_names


def filter_reachable(users):
"""
Returns a list with only reachable users.
:param user: a list of users
:return: list of reachable users.
"""
return [u for u in users if is_reachable(u)]


class PrivateTopic(models.Model):
"""
Private topic, containing private posts.
Expand Down
137 changes: 86 additions & 51 deletions zds/tutorialv2/tests/tests_opinion_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
from unittest.mock import patch

from django.conf import settings
from django.contrib.auth.models import Group
from django.core.management import call_command
from django.urls import reverse
from django.test import TestCase
from django.utils.translation import gettext_lazy as _

from zds.forum.tests.factories import TagFactory
from zds.gallery.tests.factories import UserGalleryFactory
from zds.member.tests.factories import ProfileFactory, StaffProfileFactory
from zds.member.tests.factories import ProfileFactory, StaffProfileFactory, UserFactory
from zds.tutorialv2.tests.factories import (
PublishableContentFactory,
ExtractFactory,
Expand All @@ -31,7 +32,16 @@ class PublishedContentTests(TutorialTestMixin, TestCase):
def setUp(self):

self.overridden_zds_app["member"]["bot_account"] = ProfileFactory().user.username
self.bot_group = Group()
self.bot_group.name = settings.ZDS_APP["member"]["bot_group"]
self.bot_group.save()
self.licence = LicenceFactory()
self.anonymous = UserFactory(username=settings.ZDS_APP["member"]["anonymous_account"], password="anything")
self.anonymous.groups.add(self.bot_group)
self.anonymous.save()
self.external = UserFactory(username=settings.ZDS_APP["member"]["external_account"], password="anything")
self.external.groups.add(self.bot_group)
self.external.save()

self.user_author = ProfileFactory().user
self.user_staff = StaffProfileFactory().user
Expand Down Expand Up @@ -360,6 +370,25 @@ def test_opinion_unpublication(self, opinions_management):

self.assertEqual(PublishedContent.objects.count(), 1)

# unregister author and unpublish
self.client.force_login(self.user_author)
result = self.client.post(reverse("member-unregister"), follow=False)
self.assertEqual(result.status_code, 302)

self.client.force_login(self.user_staff)

result = self.client.post(
reverse("validation:unpublish-opinion", kwargs={"pk": opinion.pk, "slug": opinion.slug}),
{"text": text_unpublication, "source": "", "version": opinion_draft.current_version},
follow=False,
)
self.assertEqual(result.status_code, 302)

self.assertEqual(PublishedContent.objects.count(), 0)

opinion = PublishableContent.objects.get(pk=opinion.pk)
self.assertIsNone(opinion.public_version)

def test_opinion_validation(self):
"""
Test the validation of PublishableContent where type is OPINION.
Expand Down Expand Up @@ -545,56 +574,62 @@ def test_ignore_opinion(self):
self.assertNotContains(result, opinion.title)

def test_permanently_unpublish_opinion(self):
opinion = PublishableContentFactory(type="OPINION")

opinion.authors.add(self.user_author)
UserGalleryFactory(gallery=opinion.gallery, user=self.user_author, mode="W")
opinion.licence = self.licence
opinion.save()

opinion_draft = opinion.load_version()
ExtractFactory(container=opinion_draft, db_object=opinion)
ExtractFactory(container=opinion_draft, db_object=opinion)

self.client.force_login(self.user_author)

# publish
result = self.client.post(
reverse("validation:publish-opinion", kwargs={"pk": opinion.pk, "slug": opinion.slug}),
{"source": "", "version": opinion_draft.current_version},
follow=False,
)
self.assertEqual(result.status_code, 302)

# login as staff
self.client.force_login(self.user_staff)

# unpublish opinion
result = self.client.post(
reverse("validation:ignore-opinion", kwargs={"pk": opinion.pk, "slug": opinion.slug}),
{
"operation": "REMOVE_PUB",
},
follow=False,
)
self.assertEqual(result.status_code, 200)

# refresh
opinion = PublishableContent.objects.get(pk=opinion.pk)

# check that the opinion is not published
self.assertFalse(opinion.in_public())

# check that it's impossible to publish the opinion again
result = self.client.get(opinion.get_absolute_url())
self.assertContains(result, _("Billet modéré")) # front

result = self.client.post(
reverse("validation:publish-opinion", kwargs={"pk": opinion.pk, "slug": opinion.slug}),
{"source": "", "version": opinion_draft.current_version},
follow=False,
)
self.assertEqual(result.status_code, 403) # back
for unregister_author in [False, True]:
with self.subTest(unregister_author):
opinion = PublishableContentFactory(type="OPINION")

opinion.authors.add(self.user_author)
UserGalleryFactory(gallery=opinion.gallery, user=self.user_author, mode="W")
opinion.licence = self.licence
opinion.save()

opinion_draft = opinion.load_version()
ExtractFactory(container=opinion_draft, db_object=opinion)
ExtractFactory(container=opinion_draft, db_object=opinion)

self.client.force_login(self.user_author)

# publish
result = self.client.post(
reverse("validation:publish-opinion", kwargs={"pk": opinion.pk, "slug": opinion.slug}),
{"source": "", "version": opinion_draft.current_version},
follow=False,
)
self.assertEqual(result.status_code, 302)

if unregister_author:
result = self.client.post(reverse("member-unregister"), follow=False)
self.assertEqual(result.status_code, 302)

# login as staff
self.client.force_login(self.user_staff)

# unpublish opinion
result = self.client.post(
reverse("validation:ignore-opinion", kwargs={"pk": opinion.pk, "slug": opinion.slug}),
{
"operation": "REMOVE_PUB",
},
follow=False,
)
self.assertEqual(result.status_code, 200)

# refresh
opinion = PublishableContent.objects.get(pk=opinion.pk)

# check that the opinion is not published
self.assertFalse(opinion.in_public())

# check that it's impossible to publish the opinion again
result = self.client.get(opinion.get_absolute_url())
self.assertContains(result, _("Billet modéré")) # front

result = self.client.post(
reverse("validation:publish-opinion", kwargs={"pk": opinion.pk, "slug": opinion.slug}),
{"source": "", "version": opinion_draft.current_version},
follow=False,
)
self.assertEqual(result.status_code, 403) # back

def test_defenitely_unpublish_alerted_opinion(self):
opinion = PublishableContentFactory(type="OPINION")
Expand Down
34 changes: 34 additions & 0 deletions zds/tutorialv2/tests/tests_views/tests_published.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ def setUp(self):
bot = Group(name=overridden_zds_app["member"]["bot_group"])
bot.save()
self.external = UserFactory(username=overridden_zds_app["member"]["external_account"], password="anything")
self.external.groups.add(bot)
self.external.save()
self.anonymous = UserFactory(username=settings.ZDS_APP["member"]["anonymous_account"], password="anything")
self.anonymous.groups.add(bot)
self.anonymous.save()

self.beta_forum = ForumFactory(
pk=overridden_zds_app["forum"]["beta_forum_id"],
Expand Down Expand Up @@ -1364,6 +1369,35 @@ def test_unpublish_with_title_change(self):
self.assertEqual(public_count - 1, PublishedContent.objects.count())
self.assertEqual("PENDING", Validation.objects.get(pk=registered_validation.pk).status)

def test_unpublish_unregistered_author(self):
article = PublishedContentFactory(type="ARTICLE", author_list=[self.user_author], licence=self.licence)
registered_validation = Validation(
content=article,
version=article.sha_draft,
status="ACCEPT",
comment_authors="bla",
comment_validator="bla",
date_reserve=datetime.datetime.now(),
date_proposition=datetime.datetime.now(),
date_validation=datetime.datetime.now(),
)
registered_validation.save()

self.client.force_login(self.user_author)
result = self.client.post(reverse("member-unregister"), follow=False)
self.assertEqual(result.status_code, 302)

self.client.force_login(self.user_staff)
public_count = PublishedContent.objects.count()
result = self.client.post(
reverse("validation:revoke", kwargs={"pk": article.pk, "slug": article.public_version.content_public_slug}),
{"text": "This content was bad", "version": article.public_version.sha_public},
follow=False,
)
self.assertEqual(302, result.status_code)
self.assertEqual(public_count - 1, PublishedContent.objects.count())
self.assertEqual("PENDING", Validation.objects.get(pk=registered_validation.pk).status)

def test_unpublish_with_empty_subscription(self):
article = PublishedContentFactory(type="ARTICLE", author_list=[self.user_author], licence=self.licence)
registered_validation = Validation(
Expand Down
56 changes: 29 additions & 27 deletions zds/tutorialv2/views/validations_contents.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from django.views.generic import ListView, FormView

from zds.member.decorator import LoggedWithReadWriteHability
from zds.mp.models import mark_read
from zds.mp.models import mark_read, filter_reachable
from zds.tutorialv2 import signals
from zds.tutorialv2.forms import (
AskValidationForm,
Expand Down Expand Up @@ -572,34 +572,36 @@ def form_valid(self, form):
self.object.save()

# send PM
msg = render_to_string(
"tutorialv2/messages/validation_revoke.md",
{
"content": versioned,
"url": versioned.get_absolute_url() + "?version=" + validation.version,
"admin": self.request.user,
"message_reject": "\n".join(["> " + a for a in form.cleaned_data["text"].split("\n")]),
},
)

bot = get_object_or_404(User, username=settings.ZDS_APP["member"]["bot_account"])
if not validation.content.validation_private_message:
validation.content.validation_private_message = send_mp(
bot,
validation.content.authors.all(),
self.object.validation_message_title,
validation.content.title,
msg,
send_by_mail=True,
direct=False,
hat=get_hat_from_settings("validation"),
)
self.object.save()
else:
send_message_mp(
bot, validation.content.validation_private_message, msg, no_notification_for=[self.request.user]
recipients = filter_reachable(validation.content.authors.all())
if len(recipients) > 0:
msg = render_to_string(
"tutorialv2/messages/validation_revoke.md",
{
"content": versioned,
"url": versioned.get_absolute_url() + "?version=" + validation.version,
"admin": self.request.user,
"message_reject": "\n".join(["> " + a for a in form.cleaned_data["text"].split("\n")]),
},
)

bot = get_object_or_404(User, username=settings.ZDS_APP["member"]["bot_account"])
if not validation.content.validation_private_message:
validation.content.validation_private_message = send_mp(
bot,
recipients,
self.object.validation_message_title,
validation.content.title,
msg,
send_by_mail=True,
direct=False,
hat=get_hat_from_settings("validation"),
)
self.object.save()
else:
send_message_mp(
bot, validation.content.validation_private_message, msg, no_notification_for=[self.request.user]
)

messages.success(self.request, _("Le contenu a bien été dépublié."))
self.success_url = self.versioned_object.get_absolute_url() + "?version=" + validation.version
signals.validation_management.send(
Expand Down
Loading

0 comments on commit d4471a7

Please sign in to comment.