def test_no_persistant_comment_notif_on_revoke(self): from zds.tutorialv2.publication_utils import unpublish_content content = PublishedContentFactory(author_list=[self.user2]) ContentReactionAnswerSubscription.objects.get_or_create_active(self.user1, content) ContentReactionFactory(related_content=content, author=self.user2, position=1) self.assertEqual(1, len(Notification.objects.get_unread_notifications_of(self.user1))) unpublish_content(content, moderator=self.user2) self.assertEqual(0, len(Notification.objects.get_unread_notifications_of(self.user1)))
def test_no_persistant_notif_on_revoke(self): from zds.tutorialv2.publication_utils import unpublish_content NewPublicationSubscription.objects.get_or_create_active(self.user1, self.user2) content = PublishedContentFactory(author_list=[self.user2]) notif_signals.new_content.send(sender=self.tuto.__class__, instance=content, by_email=False) self.assertEqual(1, len(Notification.objects.get_notifications_of(self.user1))) unpublish_content(content) self.assertEqual(0, len(Notification.objects.get_notifications_of(self.user1)))
def test_publish_content_article(self): """test and ensure the behavior of ``publish_content()`` and ``unpublish_content()``""" # 1. Article: article = PublishableContentFactory(type='ARTICLE') article.authors.add(self.user_author) UserGalleryFactory(gallery=article.gallery, user=self.user_author, mode='W') article.licence = self.licence article.save() # populate the article article_draft = article.load_version() ExtractFactory(container=article_draft, db_object=article) ExtractFactory(container=article_draft, db_object=article) self.assertEqual(len(article_draft.children), 2) # publish ! article = PublishableContent.objects.get(pk=article.pk) published = publish_content(article, article_draft) self.assertEqual(published.content, article) self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_type, article.type) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.sha_public, article.sha_draft) public = article.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # it's a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test object created in database self.assertEqual(PublishedContent.objects.filter(content=article).count(), 1) published = PublishedContent.objects.filter(content=article).last() self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.content_type, article.type) self.assertEqual(published.sha_public, public.current_version) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue(os.path.isfile(os.path.join(published.get_prod_path(), 'manifest.json'))) prod_path = public.get_prod_path() self.assertTrue(prod_path.endswith('.html'), prod_path) self.assertTrue(os.path.isfile(prod_path), prod_path) # normally, an HTML file should exists self.assertIsNone(public.introduction) # since all is in the HTML file, introduction does not exists anymore self.assertIsNone(public.conclusion) article.public_version = published article.save() # depublish it ! unpublish_content(article) self.assertEqual(PublishedContent.objects.filter(content=article).count(), 0) # published object disappear self.assertFalse(os.path.exists(public.get_prod_path())) # article was removed
def test_no_alert_on_unpublish(self): """related to #4860""" published = PublishedContentFactory(type='OPINION', author_list=[self.user_author]) reaction = ContentReactionFactory(related_content=published, author=ProfileFactory().user, position=1, pubdate=datetime.datetime.now()) Alert.objects.create(scope='CONTENT', comment=reaction, text='a text', author=ProfileFactory().user, pubdate=datetime.datetime.now(), content=published) staff = StaffProfileFactory().user self.assertEqual(1, get_header_notifications(staff)['alerts']['total']) unpublish_content(published, staff) self.assertEqual(0, get_header_notifications(staff)['alerts']['total'])
def form_valid(self, form): versioned = self.versioned_object if form.cleaned_data['version'] != self.object.sha_public: raise PermissionDenied validation = Validation.objects.filter( content=self.object, version=self.object.sha_public, status='ACCEPT').prefetch_related('content__authors').last() if not validation: raise PermissionDenied unpublish_content(self.object) validation.status = 'PENDING' validation.validator = None # remove previous validator validation.date_validation = None validation.save() self.object.sha_public = None self.object.sha_validation = validation.version self.object.pubdate = None 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']) send_mp( bot, validation.content.authors.all(), _('Dépublication'), validation.content.title, msg, True, direct=False, hat=get_hat_from_settings('validation'), ) messages.success(self.request, _('Le contenu a bien été dépublié.')) self.success_url = self.versioned_object.get_absolute_url() + '?version=' + validation.version return super(RevokeValidation, self).form_valid(form)
def form_valid(self, form): # get database representation and validated version db_object = self.object versioned = self.versioned_object self.success_url = versioned.get_absolute_url_online() if not db_object.in_public(): raise Http404('This opinion is not published.') elif PickListOperation.objects.filter(content=self.object, is_effective=True).exists(): raise PermissionDenied( 'There is already an effective operation for this content.') try: PickListOperation.objects.create( content=self.object, operation=form.cleaned_data['operation'], staff_user=self.request.user, operation_date=datetime.now(), version=db_object.sha_public) if form.cleaned_data['operation'] == 'REMOVE_PUB': unpublish_content(self.object, moderator=self.request.user) # send PM msg = render_to_string( 'tutorialv2/messages/validation_unpublish_opinion.md', { 'content': versioned, 'url': versioned.get_absolute_url(), 'moderator': self.request.user, }) bot = get_object_or_404( User, username=settings.ZDS_APP['member']['bot_account']) send_mp( bot, versioned.authors.all(), _('Dépublication'), versioned.title, msg, True, direct=False, hat=get_hat_from_settings('moderation'), ) except ValueError: logger.exception('Could not %s the opinion %s', form.cleaned_data['operation'], str(self.object)) return HttpResponse(json.dumps({ 'result': 'FAIL', 'reason': str(_('Mauvaise opération')) }), status=400) self.success_url = self.object.get_absolute_url_online() return HttpResponse(json.dumps({'result': 'OK'}))
def form_valid(self, form): versioned = self.versioned_object user = self.request.user if user not in versioned.authors.all() and not user.has_perm("tutorialv2.change_validation"): raise PermissionDenied if form.cleaned_data["version"] != self.object.sha_public: raise PermissionDenied unpublish_content(self.object, moderator=self.request.user) if [self.request.user] != list(self.object.authors.all()): # Sends PM if the deleter is not the author # (or is not the only one) of the opinion. msg = render_to_string( "tutorialv2/messages/validation_revoke.md", { "content": versioned, "url": versioned.get_absolute_url(), "admin": 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 self.object.validation_private_message: self.object.validation_private_message = send_mp( bot, versioned.authors.all(), self.object.validation_message_title, versioned.title, msg, send_by_mail=True, direct=False, hat=get_hat_from_settings("moderation"), ) self.object.save() else: send_message_mp( bot, self.object.validation_private_message, msg, hat=get_hat_from_settings("moderation"), 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() return super().form_valid(form)
def form_valid(self, form): versioned = self.versioned_object if form.cleaned_data['version'] != self.object.sha_public: raise PermissionDenied validation = Validation.objects.filter( content=self.object, version=self.object.sha_public, status='ACCEPT').prefetch_related('content__authors').last() if not validation: raise PermissionDenied unpublish_content(self.object) validation.status = "PENDING" validation.validator = None # remove previous validator validation.date_validation = None validation.save() self.object.sha_public = None self.object.sha_validation = validation.version self.object.pubdate = None 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']) send_mp( bot, validation.content.authors.all(), _(u"Dépublication"), validation.content.title, msg, True, direct=False ) messages.success(self.request, _(u"Le contenu a bien été dépublié.")) self.success_url = self.versioned_object.get_absolute_url() + "?version=" + validation.version return super(RevokeValidation, self).form_valid(form)
def test_no_persistant_notif_on_revoke(self): from zds.tutorialv2.publication_utils import unpublish_content NewPublicationSubscription.objects.get_or_create_active( self.user1, self.user2) content = PublishedContentFactory(author_list=[self.user2]) notif_signals.new_content.send(sender=self.tuto.__class__, instance=content, by_email=False) self.assertEqual( 1, len(Notification.objects.get_notifications_of(self.user1))) unpublish_content(content) self.assertEqual( 0, len(Notification.objects.get_notifications_of(self.user1)))
def form_valid(self, form): # get database representation and validated version db_object = self.object versioned = self.versioned_object self.success_url = versioned.get_absolute_url_online() if not db_object.in_public(): raise Http404('This opinion is not published.') elif PickListOperation.objects.filter(content=self.object, is_effective=True).exists() \ and form.cleaned_data['operation'] != 'REMOVE_PUB': raise PermissionDenied('There is already an effective operation for this content.') try: PickListOperation.objects.filter(content=self.object).update(is_effective=False, canceler_user=self.request.user) PickListOperation.objects.create(content=self.object, operation=form.cleaned_data['operation'], staff_user=self.request.user, operation_date=datetime.now(), version=db_object.sha_public) if form.cleaned_data['operation'] == 'REMOVE_PUB': unpublish_content(self.object, moderator=self.request.user) # send PM msg = render_to_string( 'tutorialv2/messages/validation_unpublish_opinion.md', { 'content': versioned, 'url': versioned.get_absolute_url(), 'moderator': self.request.user, }) bot = get_object_or_404(User, username=settings.ZDS_APP['member']['bot_account']) send_mp( bot, versioned.authors.all(), _('Billet modéré'), versioned.title, msg, True, direct=False, hat=get_hat_from_settings('moderation'), ) except ValueError: logger.exception('Could not %s the opinion %s', form.cleaned_data['operation'], str(self.object)) return HttpResponse(json.dumps({'result': 'FAIL', 'reason': str(_('Mauvaise opération'))}), status=400) if not form.cleaned_data['redirect']: return HttpResponse(json.dumps({'result': 'OK'})) else: self.success_url = reverse('opinion:list') messages.success(self.request, _('Le billet a bien été modéré.')) return super().form_valid(form)
def test_no_persistant_comment_notif_on_revoke(self): from zds.tutorialv2.publication_utils import unpublish_content content = PublishedContentFactory(author_list=[self.user2]) ContentReactionAnswerSubscription.objects.get_or_create_active( self.user1, content) ContentReactionFactory(related_content=content, author=self.user2, position=1) self.assertEqual( 1, len(Notification.objects.get_unread_notifications_of(self.user1))) unpublish_content(content, moderator=self.user2) self.assertEqual( 0, len(Notification.objects.get_unread_notifications_of(self.user1)))
def form_valid(self, form): versioned = self.versioned_object user = self.request.user if user not in versioned.authors.all( ) and not user.has_perm('tutorialv2.change_validation'): raise PermissionDenied if form.cleaned_data['version'] != self.object.sha_public: raise PermissionDenied unpublish_content(self.object, moderator=self.request.user) if [self.request.user] != list(self.object.authors.all()): # Sends PM if the deleter is not the author # (or is not the only one) of the opinion. msg = render_to_string( 'tutorialv2/messages/validation_revoke.md', { 'content': versioned, 'url': versioned.get_absolute_url(), 'admin': 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']) send_mp( bot, versioned.authors.all(), _('Dépublication'), versioned.title, msg, True, direct=False, hat=get_hat_from_settings('moderation'), ) messages.success(self.request, _('Le contenu a bien été dépublié.')) self.success_url = self.versioned_object.get_absolute_url() return super(UnpublishOpinion, self).form_valid(form)
def form_valid(self, form): versioned = self.versioned_object user = self.request.user if user not in versioned.authors.all() and not user.has_perm('tutorialv2.change_validation'): raise PermissionDenied if form.cleaned_data['version'] != self.object.sha_public: raise PermissionDenied unpublish_content(self.object, moderator=self.request.user) if [self.request.user] != list(self.object.authors.all()): # Sends PM if the deleter is not the author # (or is not the only one) of the opinion. msg = render_to_string( 'tutorialv2/messages/validation_revoke.md', { 'content': versioned, 'url': versioned.get_absolute_url(), 'admin': 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']) send_mp( bot, versioned.authors.all(), _('Dépublication'), versioned.title, msg, True, direct=False, hat=get_hat_from_settings('moderation'), ) messages.success(self.request, _('Le contenu a bien été dépublié.')) self.success_url = self.versioned_object.get_absolute_url() return super(UnpublishOpinion, self).form_valid(form)
def form_valid(self, form): versioned = self.versioned_object if form.cleaned_data["version"] != self.object.sha_public: raise PermissionDenied validation = (Validation.objects.filter( content=self.object, version=self.object.sha_public, status="ACCEPT").prefetch_related("content__authors").last()) if not validation: raise PermissionDenied unpublish_content(self.object) validation.status = "PENDING" validation.validator = None # remove previous validator validation.date_validation = None validation.save() self.object.sha_public = None self.object.sha_validation = validation.version self.object.pubdate = None 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]) messages.success(self.request, _("Le contenu a bien été dépublié.")) self.success_url = self.versioned_object.get_absolute_url( ) + "?version=" + validation.version return super(RevokeValidation, self).form_valid(form)
def test_publish_content(self): """test and ensure the behavior of ``publish_content()`` and ``unpublish_content()``""" # 1. Article: article = PublishableContentFactory(type='ARTICLE') article.authors.add(self.user_author) UserGalleryFactory(gallery=article.gallery, user=self.user_author, mode='W') article.licence = self.licence article.save() # populate the article article_draft = article.load_version() ExtractFactory(container=article_draft, db_object=article) ExtractFactory(container=article_draft, db_object=article) self.assertEqual(len(article_draft.children), 2) # publish ! article = PublishableContent.objects.get(pk=article.pk) published = publish_content(article, article_draft) self.assertEqual(published.content, article) self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_type, article.type) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.sha_public, article.sha_draft) public = article.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object ! self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test object created in database self.assertEqual(PublishedContent.objects.filter(content=article).count(), 1) published = PublishedContent.objects.filter(content=article).last() self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.content_type, article.type) self.assertEqual(published.sha_public, public.current_version) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue(os.path.isfile(os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue(os.path.isfile(public.get_prod_path())) # normally, an HTML file should exists self.assertIsNone(public.introduction) # since all is in the HTML file, introduction does not exists anymore self.assertIsNone(public.conclusion) article.public_version = published article.save() # depublish it ! unpublish_content(article) self.assertEqual(PublishedContent.objects.filter(content=article).count(), 0) # published object disappear self.assertFalse(os.path.exists(public.get_prod_path())) # article was removed # ... For the next tests, I will assume that the unpublication works. # 2. Mini-tutorial → Not tested, because at this point, it's the same as an article (with a different metadata) # 3. Medium-size tutorial midsize_tuto = PublishableContentFactory(type='TUTORIAL') midsize_tuto.authors.add(self.user_author) UserGalleryFactory(gallery=midsize_tuto.gallery, user=self.user_author, mode='W') midsize_tuto.licence = self.licence midsize_tuto.save() # populate with 2 chapters (1 extract each) midsize_tuto_draft = midsize_tuto.load_version() chapter1 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter1, db_object=midsize_tuto) chapter2 = ContainerFactory(parent=midsize_tuto_draft, db_objet=midsize_tuto) ExtractFactory(container=chapter2, db_object=midsize_tuto) # publish it midsize_tuto = PublishableContent.objects.get(pk=midsize_tuto.pk) published = publish_content(midsize_tuto, midsize_tuto_draft) self.assertEqual(published.content, midsize_tuto) self.assertEqual(published.content_pk, midsize_tuto.pk) self.assertEqual(published.content_type, midsize_tuto.type) self.assertEqual(published.content_public_slug, midsize_tuto_draft.slug) self.assertEqual(published.sha_public, midsize_tuto.sha_draft) public = midsize_tuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue(os.path.isfile(os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue(os.path.isfile(os.path.join(public.get_prod_path(), public.introduction))) self.assertTrue(os.path.isfile(os.path.join(public.get_prod_path(), public.conclusion))) self.assertEqual(len(public.children), 2) for child in public.children: self.assertTrue(os.path.isfile(child.get_prod_path())) # an HTML file for each chapter self.assertIsNone(child.introduction) self.assertIsNone(child.conclusion) # 4. Big tutorial: bigtuto = PublishableContentFactory(type='TUTORIAL') bigtuto.authors.add(self.user_author) UserGalleryFactory(gallery=bigtuto.gallery, user=self.user_author, mode='W') bigtuto.licence = self.licence bigtuto.save() # populate with 2 part (1 chapter with 1 extract each) bigtuto_draft = bigtuto.load_version() part1 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter1 = ContainerFactory(parent=part1, db_objet=bigtuto) ExtractFactory(container=chapter1, db_object=bigtuto) part2 = ContainerFactory(parent=bigtuto_draft, db_objet=bigtuto) chapter2 = ContainerFactory(parent=part2, db_objet=bigtuto) ExtractFactory(container=chapter2, db_object=bigtuto) # publish it bigtuto = PublishableContent.objects.get(pk=bigtuto.pk) published = publish_content(bigtuto, bigtuto_draft) self.assertEqual(published.content, bigtuto) self.assertEqual(published.content_pk, bigtuto.pk) self.assertEqual(published.content_type, bigtuto.type) self.assertEqual(published.content_public_slug, bigtuto_draft.slug) self.assertEqual(published.sha_public, bigtuto.sha_draft) public = bigtuto.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # its a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue(os.path.isfile(os.path.join(published.get_prod_path(), 'manifest.json'))) self.assertTrue(os.path.isfile(os.path.join(public.get_prod_path(), public.introduction))) self.assertTrue(os.path.isfile(os.path.join(public.get_prod_path(), public.conclusion))) self.assertEqual(len(public.children), 2) for part in public.children: self.assertTrue(os.path.isdir(part.get_prod_path())) # a directory for each part # ... and an HTML file for introduction and conclusion self.assertTrue(os.path.isfile(os.path.join(public.get_prod_path(), part.introduction))) self.assertTrue(os.path.isfile(os.path.join(public.get_prod_path(), part.conclusion))) self.assertEqual(len(part.children), 1) for chapter in part.children: # the HTML file is located in the good directory: self.assertEqual(part.get_prod_path(), os.path.dirname(chapter.get_prod_path())) self.assertTrue(os.path.isfile(chapter.get_prod_path())) # an HTML file for each chapter self.assertIsNone(chapter.introduction) self.assertIsNone(chapter.conclusion)
def test_publish_content_article(self): """test and ensure the behavior of ``publish_content()`` and ``unpublish_content()``""" # 1. Article: article = PublishableContentFactory(type='ARTICLE') article.authors.add(self.user_author) UserGalleryFactory(gallery=article.gallery, user=self.user_author, mode='W') article.licence = self.licence article.save() # populate the article article_draft = article.load_version() ExtractFactory(container=article_draft, db_object=article) ExtractFactory(container=article_draft, db_object=article) self.assertEqual(len(article_draft.children), 2) # publish ! article = PublishableContent.objects.get(pk=article.pk) published = publish_content(article, article_draft) self.assertEqual(published.content, article) self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_type, article.type) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.sha_public, article.sha_draft) public = article.load_version(sha=published.sha_public, public=published) self.assertIsNotNone(public) self.assertTrue(public.PUBLIC) # it's a PublicContent object self.assertEqual(public.type, published.content_type) self.assertEqual(public.current_version, published.sha_public) # test object created in database self.assertEqual( PublishedContent.objects.filter(content=article).count(), 1) published = PublishedContent.objects.filter(content=article).last() self.assertEqual(published.content_pk, article.pk) self.assertEqual(published.content_public_slug, article_draft.slug) self.assertEqual(published.content_type, article.type) self.assertEqual(published.sha_public, public.current_version) # test creation of files: self.assertTrue(os.path.isdir(published.get_prod_path())) self.assertTrue( os.path.isfile( os.path.join(published.get_prod_path(), 'manifest.json'))) prod_path = public.get_prod_path() self.assertTrue(prod_path.endswith('.html'), prod_path) self.assertTrue(os.path.isfile(prod_path), prod_path) # normally, an HTML file should exists self.assertIsNone( public.introduction ) # since all is in the HTML file, introduction does not exists anymore self.assertIsNone(public.conclusion) article.public_version = published article.save() # depublish it ! unpublish_content(article) self.assertEqual( PublishedContent.objects.filter(content=article).count(), 0) # published object disappear self.assertFalse(os.path.exists( public.get_prod_path())) # article was removed
def form_valid(self, form): # get database representation and validated version db_object = self.object versioned = self.versioned_object self.success_url = versioned.get_absolute_url_online() if not db_object.in_public(): raise Http404("This opinion is not published.") elif (PickListOperation.objects.filter(content=self.object, is_effective=True).exists() and form.cleaned_data["operation"] != "REMOVE_PUB"): raise PermissionDenied( "There is already an effective operation for this content.") try: PickListOperation.objects.filter(content=self.object).update( is_effective=False, canceler_user=self.request.user) PickListOperation.objects.create( content=self.object, operation=form.cleaned_data["operation"], staff_user=self.request.user, operation_date=datetime.now(), version=db_object.sha_public, ) if form.cleaned_data["operation"] == "REMOVE_PUB": unpublish_content(self.object, moderator=self.request.user) # send PM msg = render_to_string( "tutorialv2/messages/validation_unpublish_opinion.md", { "content": versioned, "url": versioned.get_absolute_url(), "moderator": self.request.user, }, ) bot = get_object_or_404( User, username=settings.ZDS_APP["member"]["bot_account"]) if not self.object.validation_private_message: self.object.validation_private_message = send_mp( bot, versioned.authors.all(), self.object.validation_message_title, versioned.title, msg, send_by_mail=True, direct=False, hat=get_hat_from_settings("moderation"), ) self.object.save() else: send_message_mp( bot, self.object.validation_private_message, msg, hat=get_hat_from_settings("moderation"), no_notification_for=[self.request.user], ) except ValueError: logger.exception("Could not %s the opinion %s", form.cleaned_data["operation"], str(self.object)) return HttpResponse(json.dumps({ "result": "FAIL", "reason": str(_("Mauvaise opération")) }), status=400) if not form.cleaned_data["redirect"]: return HttpResponse(json.dumps({"result": "OK"})) else: self.success_url = reverse("opinion:list") messages.success(self.request, _("Le billet a bien été modéré.")) return super().form_valid(form)