Esempio n. 1
0
    def test_reuse_old_notification(self):
        """
        When there already is a read notification for a given content, we reuse it.
        """
        topic = send_mp(author=self.user1,
                        users=[self.user2],
                        title="Testing",
                        subtitle="",
                        text="",
                        leave=False)
        send_message_mp(self.user2, topic, "", send_by_mail=True)

        notifications = Notification.objects.get_unread_notifications_of(
            self.user1)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message,
                         notifications.first().content_object)

        mark_read(topic, self.user1)

        send_message_mp(self.user2, topic, "", send_by_mail=True)

        notifications = Notification.objects.filter(
            subscription__user=self.user1)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
Esempio n. 2
0
    def test_generate_a_notification_after_new_post(self):
        """
        When a user posts on a private topic, we generate a notification for all participants.
        """
        topic = send_mp(author=self.user1,
                        users=[self.user2, self.user3],
                        title="Testing",
                        subtitle="",
                        text="",
                        leave=False)

        notifications = Notification.objects.get_unread_notifications_of(
            self.user2)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message,
                         notifications.first().content_object)

        mark_read(topic, self.user2)

        notifications = Notification.objects.get_unread_notifications_of(
            self.user2)
        self.assertEqual(0, len(notifications))

        send_message_mp(self.user3, topic, "")

        notifications = Notification.objects.get_unread_notifications_of(
            self.user2)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message,
                         notifications.first().content_object)
Esempio n. 3
0
 def form_valid(self, form):
     send_message_mp(self.request.user,
                     self.object,
                     form.data.get("text"),
                     True,
                     False,
                     hat=get_hat_from_request(self.request))
     return redirect(self.object.last_message.get_absolute_url())
Esempio n. 4
0
    def create(self, validated_data):
        # Get topic
        pk_ptopic = self.context.get("view").kwargs.get("pk_ptopic")
        topic = get_object_or_404(PrivateTopic, pk=(pk_ptopic))

        # Get author
        author = self.context.get("view").request.user

        # Send post in mp
        send_message_mp(author,
                        topic,
                        self.validated_data.get("text"),
                        send_by_mail=True,
                        direct=False)
        return topic.last_message
Esempio n. 5
0
    def test_remove_notifications_when_a_user_leave_private_topic(self):
        """
        When a user leaves a private topic, we mark the current notification as read
        if it exists.
        """
        topic = send_mp(author=self.user1,
                        users=[self.user2],
                        title="Testing",
                        subtitle="",
                        text="",
                        leave=False)

        notifications = Notification.objects.get_unread_notifications_of(
            self.user2)
        self.assertEqual(1, len(notifications))
        self.assertIsNotNone(notifications.first())
        self.assertEqual(topic.last_message,
                         notifications.first().content_object)

        self.assertIsNotNone(
            PrivateTopicAnswerSubscription.objects.get_existing(
                self.user2, topic, is_active=True))

        send_message_mp(self.user2, topic, "Test")
        topic.remove_participant(self.user2)
        topic.save()

        self.assertEqual(
            0,
            len(Notification.objects.get_unread_notifications_of(self.user2)))
        self.assertIsNotNone(
            PrivateTopicAnswerSubscription.objects.get_existing(
                self.user2, topic, is_active=False))

        self.assertEqual(
            1,
            len(Notification.objects.get_unread_notifications_of(self.user1)))

        response = self.client.post(reverse("mp-delete",
                                            args=[topic.pk, topic.slug]),
                                    follow=True)
        self.assertEqual(200, response.status_code)
        self.assertEqual(
            0,
            len(Notification.objects.get_unread_notifications_of(self.user1)))
Esempio n. 6
0
    def test_no_emails_for_those_who_have_other_things_in_that_place(self):
        """
        Test that we do not try to send e-mails to those who have not registered a valid one.
        """
        self.assertEqual(0, len(mail.outbox))
        topic = send_mp(
            author=self.userStandard1,
            users=[self.userOAuth2],
            title="Testing",
            subtitle="",
            text="",
            send_by_mail=True,
            leave=False,
        )

        self.assertEqual(0, len(mail.outbox))

        send_message_mp(self.userOAuth2, topic, "", send_by_mail=True)

        self.assertEqual(1, len(mail.outbox))
Esempio n. 7
0
    def test_send_an_email_when_we_specify_it(self):
        """
        When the user asked to be notified via email, we actually send the email
        when a topic is created.
        """
        settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
        self.assertEqual(0, len(mail.outbox))

        topic = send_mp(
            author=self.user1,
            users=[self.user2, self.user3],
            title="Testing",
            subtitle="",
            text="",
            send_by_mail=True,
            leave=False,
        )

        self.assertEqual(1, len(mail.outbox))

        self.user1.profile.email_for_answer = True
        self.user1.profile.save()
        self.user2.profile.email_for_answer = True
        self.user2.profile.save()
        self.user3.profile.email_for_answer = False
        self.user3.profile.save()

        send_message_mp(self.user2, topic, "", send_by_mail=True)
        subscriptions = PrivateTopicAnswerSubscription.objects.filter(
            user=self.user2)
        self.assertTrue(subscriptions.last().by_email)

        self.assertEqual(2, len(mail.outbox))

        self.user1.profile.email_for_answer = False
        self.user1.profile.save()

        send_message_mp(self.user2, topic, "", send_by_mail=True)

        self.assertEqual(2, len(mail.outbox))
Esempio n. 8
0
    def setUp(self):
        self.licence = LicenceFactory()
        self.subcategory = SubCategoryFactory()

        self.author = ProfileFactory()
        self.user = ProfileFactory()
        self.staff = StaffProfileFactory()

        self.tuto = PublishableContentFactory(type="TUTORIAL")
        self.tuto.authors.add(self.author.user)
        self.tuto.licence = self.licence
        self.tuto.subcategory.add(self.subcategory)
        self.tuto.save()

        self.validation = Validation(
            content=self.tuto,
            version=self.tuto.sha_draft,
            comment_authors="bla",
            date_proposition=datetime.now(),
        )
        self.validation.save()

        self.topic = send_mp(author=self.author.user,
                             users=[],
                             title="Title",
                             text="Testing",
                             subtitle="",
                             leave=False)
        self.topic.add_participant(self.user.user)
        send_message_mp(self.user.user, self.topic, "Testing")

        # humane_delta test
        periods = ((1, 0), (2, 1), (3, 7), (4, 30), (5, 360))
        cont = dict()
        cont["date_today"] = periods[0][0]
        cont["date_yesterday"] = periods[1][0]
        cont["date_last_week"] = periods[2][0]
        cont["date_last_month"] = periods[3][0]
        cont["date_last_year"] = periods[4][0]
        self.context = Context(cont)
Esempio n. 9
0
 def create_notification_for_pm(self, sender, target):
     topic = PrivateTopicFactory(author=sender)
     topic.add_participant(target, silent=True)
     send_message_mp(author=sender, n_topic=topic, text="Testing")
     return topic
Esempio n. 10
0
    def delete(self, request, *args, **kwargs):
        """rewrite delete() function to ensure repository deletion"""

        self.object = self.get_object()
        object_type = self.object.type.lower()

        _type = _("ce tutoriel")
        if self.object.is_article:
            _type = _("cet article")
        elif self.object.is_opinion:
            _type = _("ce billet")

        if self.object.authors.count() > 1:  # if more than one author, just remove author from list
            RemoveAuthorFromContent.remove_author(self.object, self.request.user)
            messages.success(self.request, _("Vous avez quitté la rédaction de {}.").format(_type))

        else:
            validation = Validation.objects.filter(content=self.object).order_by("-date_proposition").first()

            if validation and validation.status == "PENDING_V":  # if the validation have a validator, warn him by PM
                if "text" not in self.request.POST or len(self.request.POST["text"].strip()) < 3:
                    messages.error(self.request, _("Merci de fournir une raison à la suppression."))
                    return redirect(self.object.get_absolute_url())
                else:
                    bot = get_object_or_404(User, username=settings.ZDS_APP["member"]["bot_account"])
                    msg = render_to_string(
                        "tutorialv2/messages/validation_cancel_on_delete.md",
                        {
                            "content": self.object,
                            "validator": validation.validator.username,
                            "user": self.request.user,
                            "message": "\n".join(["> " + line for line in self.request.POST["text"].split("\n")]),
                        },
                    )
                    if not validation.content.validation_private_message:
                        validation.content.validation_private_message = send_mp(
                            bot,
                            [validation.validator],
                            _("Demande de validation annulée").format(),
                            self.object.title,
                            msg,
                            send_by_mail=False,
                            leave=True,
                            hat=get_hat_from_settings("validation"),
                            automatically_read=validation.validator,
                        )
                        validation.content.save()
                    else:
                        send_message_mp(
                            bot,
                            validation.content.validation_private_message,
                            msg,
                            hat=get_hat_from_settings("validation"),
                            no_notification_for=[self.request.user],
                        )
            if self.object.beta_topic is not None:
                beta_topic = self.object.beta_topic
                beta_topic.is_locked = True
                beta_topic.add_tags(["Supprimé"])
                beta_topic.save()
                post = beta_topic.first_post()
                post.update_content(
                    _("[[a]]\n" "| Malheureusement, {} qui était en bêta a été supprimé par son auteur.\n\n").format(
                        _type
                    )
                    + post.text
                )

                post.save()

            self.object.delete()

            messages.success(self.request, _("Vous avez bien supprimé {}.").format(_type))

        return redirect(reverse(object_type + ":find-" + object_type, args=[request.user.username]))
Esempio n. 11
0
    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
        signals.validation_management.send(
            sender=self.__class__,
            content=validation.content,
            performer=self.request.user,
            version=validation.version,
            action="revoke",
        )
        return super().form_valid(form)
Esempio n. 12
0
    def form_valid(self, form):

        user = self.request.user

        validation = Validation.objects.filter(pk=self.kwargs["pk"]).last()

        if not validation:
            raise PermissionDenied

        if validation.validator != user:
            raise PermissionDenied

        if validation.status != "PENDING_V":
            raise PermissionDenied

        # reject validation:
        validation.comment_validator = form.cleaned_data["text"]
        validation.status = "REJECT"
        validation.date_validation = datetime.now()
        validation.save()

        validation.content.sha_validation = None
        validation.content.save()

        # send PM
        versioned = validation.content.load_version(sha=validation.version)
        msg = render_to_string(
            "tutorialv2/messages/validation_reject.md",
            {
                "content":
                versioned,
                "url":
                versioned.get_absolute_url() + "?version=" +
                validation.version,
                "validator":
                validation.validator,
                "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(),
                _("Rejet de la demande de publication").format(),
                validation.content.title,
                msg,
                send_by_mail=True,
                direct=False,
                hat=get_hat_from_settings("validation"),
            )
            validation.content.save()
        else:
            send_message_mp(bot,
                            validation.content.validation_private_message,
                            msg,
                            no_notification_for=[self.request.user])

        messages.info(self.request, _("Le contenu a bien été refusé."))
        self.success_url = reverse("validation:list")
        signals.validation_management.send(
            sender=self.__class__,
            content=validation.content,
            performer=self.request.user,
            version=validation.version,
            action="reject",
        )
        return super().form_valid(form)
Esempio n. 13
0
    def post(self, request, *args, **kwargs):
        validation = get_object_or_404(Validation, pk=kwargs["pk"])
        if validation.validator:
            validation.validator = None
            validation.date_reserve = None
            validation.status = "PENDING"
            validation.save()
            messages.info(request, _("Ce contenu n'est plus réservé."))
            signals.validation_management.send(
                sender=self.__class__,
                content=validation.content,
                performer=request.user,
                version=validation.version,
                action="unreserve",
            )
            return redirect(reverse("validation:list"))
        else:
            validation.validator = request.user
            validation.date_reserve = datetime.now()
            validation.status = "PENDING_V"
            validation.save()

            versioned = validation.content.load_version(sha=validation.version)
            msg = render_to_string(
                "tutorialv2/messages/validation_reserve.md",
                {
                    "content":
                    versioned,
                    "url":
                    versioned.get_absolute_url() + "?version=" +
                    validation.version,
                },
            )

            authors = list(validation.content.authors.all())
            if validation.validator in authors:
                authors.remove(validation.validator)
            if len(authors) > 0:
                if not validation.content.validation_private_message:
                    validation.content.validation_private_message = send_mp(
                        validation.validator,
                        authors,
                        _("Contenu réservé - {0}").format(
                            validation.content.title),
                        validation.content.title,
                        msg,
                        send_by_mail=True,
                        leave=False,
                        direct=False,
                        hat=get_hat_from_settings("validation"),
                    )
                    validation.content.save()
                else:
                    send_message_mp(
                        validation.validator,
                        validation.content.validation_private_message, msg)
                mark_read(validation.content.validation_private_message,
                          validation.validator)

            messages.info(
                request,
                _("Ce contenu a bien été réservé par {0}.").format(
                    request.user.username))
            signals.validation_management.send(
                sender=self.__class__,
                content=validation.content,
                performer=request.user,
                version=validation.version,
                action="reserve",
            )

            return redirect(
                reverse("content:view",
                        args=[validation.content.pk, validation.content.slug])
                + "?version=" + validation.version)
Esempio n. 14
0
    def form_valid(self, form):

        user = self.request.user

        validation = (Validation.objects.filter(
            pk=self.kwargs["pk"]).prefetch_related("content").prefetch_related(
                "content__authors").last())

        if not validation:
            raise PermissionDenied

        if validation.status not in ["PENDING", "PENDING_V"]:
            raise PermissionDenied  # cannot cancel a validation that is already accepted or rejected

        if user not in validation.content.authors.all(
        ) and not user.has_perm("tutorialv2.change_validation"):
            raise PermissionDenied

        versioned = validation.content.load_version(sha=validation.version)

        # reject validation:
        quote = "\n".join(
            ["> " + line for line in form.cleaned_data["text"].split("\n")])
        validation.status = "CANCEL"
        validation.comment_authors = _(
            "\n\nLa validation a été **annulée** pour la raison suivante :\n\n{}"
        ).format(quote)
        validation.date_validation = datetime.now()
        validation.save()

        validation.content.sha_validation = None
        validation.content.save()

        # warn the former validator that the whole thing has been cancelled
        if validation.validator:
            bot = get_object_or_404(
                User, username=settings.ZDS_APP["member"]["bot_account"])
            msg = render_to_string(
                "tutorialv2/messages/validation_cancel.md",
                {
                    "content":
                    versioned,
                    "validator":
                    validation.validator.username,
                    "url":
                    versioned.get_absolute_url() + "?version=" +
                    validation.version,
                    "user":
                    self.request.user,
                    "message":
                    quote,
                },
            )
            if not validation.content.validation_private_message:
                validation.content.validation_private_message = send_mp(
                    bot,
                    [validation.validator],
                    _("Demande de validation annulée").format(),
                    versioned.title,
                    msg,
                    send_by_mail=False,
                    hat=get_hat_from_settings("validation"),
                )
                validation.content.save()
            else:
                send_message_mp(bot,
                                validation.content.validation_private_message,
                                msg)

        messages.info(self.request,
                      _("La validation de ce contenu a bien été annulée."))
        signals.validation_management.send(
            sender=self.__class__,
            content=validation.content,
            performer=self.request.user,
            version=validation.version,
            action="cancel",
        )
        self.success_url = (
            reverse("content:view",
                    args=[validation.content.pk, validation.content.slug]) +
            "?version=" + validation.version)

        return super().form_valid(form)
Esempio n. 15
0
    def form_valid(self, form):

        old_validation = Validation.objects.filter(
            content__pk=self.object.pk, status__in=["PENDING",
                                                    "PENDING_V"]).first()

        if old_validation:  # if an old validation exists, cancel it!
            old_validator = old_validation.validator
            old_validation.status = "CANCEL"
            old_validation.date_validation = datetime.now()
            old_validation.save()
        else:
            old_validator = None

        # create a 'validation' object
        validation = Validation()
        validation.content = self.object
        validation.date_proposition = datetime.now()
        validation.comment_authors = form.cleaned_data["text"]
        validation.version = form.cleaned_data["version"]
        if old_validator:
            validation.validator = old_validator
            validation.date_reserve = old_validation.date_reserve
            validation.status = "PENDING_V"
        validation.save()

        # warn the former validator that an update has been made, if any
        if old_validator:
            bot = get_object_or_404(
                User, username=settings.ZDS_APP["member"]["bot_account"])
            msg = render_to_string(
                "tutorialv2/messages/validation_change.md",
                {
                    "content":
                    self.versioned_object,
                    "validator":
                    validation.validator.username,
                    "url":
                    self.versioned_object.get_absolute_url() + "?version=" +
                    form.cleaned_data["version"],
                    "url_history":
                    reverse("content:history",
                            args=[self.object.pk, self.object.slug]),
                },
            )
            if not self.object.validation_private_message:
                self.object.validation_private_message = send_mp(
                    bot,
                    [old_validator],
                    self.object.validation_message_title,
                    self.versioned_object.title,
                    msg,
                    send_by_mail=False,
                    hat=get_hat_from_settings("validation"),
                )
            else:
                send_message_mp(bot, self.object.validation_private_message,
                                msg)

        # update the content with the source and the version of the validation
        self.object.source = self.versioned_object.source
        self.object.sha_validation = validation.version
        self.object.save()

        messages.success(
            self.request,
            _("Votre demande de validation a été transmise à l'équipe."))
        signals.validation_management.send(
            sender=self.__class__,
            content=validation.content,
            performer=self.request.user,
            version=validation.version,
            action="request",
        )

        self.success_url = self.versioned_object.get_absolute_url(
            version=self.sha)
        return super().form_valid(form)
Esempio n. 16
0
    def form_valid(self, form):
        beta_version = self.versioned_object
        sha_beta = beta_version.current_version

        # topic of the beta version:
        topic = self.object.beta_topic

        if topic:
            if topic.forum_id != settings.ZDS_APP["forum"]["beta_forum_id"]:
                # if the topic is moved from the beta forum, then a new one is created instead
                topic = None

        _type = self.object.type.lower()
        if _type == "tutorial":
            _type = _("tutoriel")
        elif _type == "opinion":
            raise PermissionDenied

        # perform actions:
        if self.action == "inactive":
            self.object.sha_beta = None

            msg_post = render_to_string(
                "tutorialv2/messages/beta_desactivate.md", {
                    "content": beta_version,
                    "type": _type
                })
            send_post(self.request, topic, self.request.user, msg_post)
            lock_topic(topic)
            signals.beta_management.send(
                sender=self.__class__,
                content=self.object,
                performer=self.request.user,
                version=sha_beta,
                action="deactivate",
            )

        elif self.action == "set":
            already_in_beta = self.object.in_beta()
            all_tags = []

            if not already_in_beta or self.object.sha_beta != sha_beta:
                self.object.sha_beta = sha_beta
                self.versioned_object.in_beta = True
                self.versioned_object.sha_beta = sha_beta

                msg = render_to_string(
                    "tutorialv2/messages/beta_activate_topic.md",
                    {
                        "content":
                        beta_version,
                        "type":
                        _type,
                        "url":
                        settings.ZDS_APP["site"]["url"] +
                        self.versioned_object.get_absolute_url_beta(),
                    },
                )

                if not topic:
                    # if first time putting the content in beta, send a message on the forum and a PM

                    # find tags
                    all_tags = self._get_all_tags()
                    topic = self._create_beta_topic(msg, beta_version, _type,
                                                    all_tags)

                    bot = get_object_or_404(
                        User,
                        username=settings.ZDS_APP["member"]["bot_account"])
                    msg_pm = render_to_string(
                        "tutorialv2/messages/beta_activate_pm.md",
                        {
                            "content":
                            beta_version,
                            "type":
                            _type,
                            "url":
                            settings.ZDS_APP["site"]["url"] +
                            topic.get_absolute_url(),
                            "user":
                            self.request.user,
                        },
                    )
                    if not self.object.validation_private_message:
                        self.object.validation_private_message = send_mp(
                            bot,
                            self.object.authors.all(),
                            self.object.validation_message_title,
                            beta_version.title,
                            msg_pm,
                            send_by_mail=False,
                            leave=True,
                            hat=get_hat_from_settings("validation"),
                        )
                        self.object.save()
                    else:
                        send_message_mp(
                            bot,
                            self.object.validation_private_message,
                            msg,
                            hat=get_hat_from_settings("validation"))

                # When the anti-spam triggers (because the author of the
                # message posted themselves within the last 15 minutes),
                # it is likely that we want to avoid to generate a duplicated
                # post that couldn't be deleted. We hence avoid to add another
                # message to the topic.

                else:
                    all_tags = self._get_all_tags()

                    if not already_in_beta:
                        unlock_topic(topic)
                        msg_post = render_to_string(
                            "tutorialv2/messages/beta_reactivate.md",
                            {
                                "content":
                                beta_version,
                                "type":
                                _type,
                                "url":
                                settings.ZDS_APP["site"]["url"] +
                                self.versioned_object.get_absolute_url_beta(),
                            },
                        )
                        topic = send_post(self.request, topic,
                                          self.request.user, msg_post)
                    elif not topic.antispam():
                        msg_post = render_to_string(
                            "tutorialv2/messages/beta_update.md",
                            {
                                "content":
                                beta_version,
                                "type":
                                _type,
                                "url":
                                settings.ZDS_APP["site"]["url"] +
                                self.versioned_object.get_absolute_url_beta(),
                            },
                        )
                        topic = send_post(self.request, topic,
                                          self.request.user, msg_post)

                # make sure that all authors follow the topic:
                for author in self.object.authors.all():
                    TopicAnswerSubscription.objects.get_or_create_active(
                        author, topic)
                    mark_read(topic, author)

            # finally set the tags on the topic
            if topic:
                topic.tags.clear()
                for tag in all_tags:
                    topic.tags.add(tag)
                topic.save()

            signals.beta_management.send(
                sender=self.__class__,
                content=self.object,
                performer=self.request.user,
                version=sha_beta,
                action="activate",
            )

        self.object.save(
        )  # we should prefer .update but it needs a huge refactoring

        self.success_url = self.versioned_object.get_absolute_url(
            version=sha_beta)

        if self.object.is_beta(sha_beta):
            self.success_url = self.versioned_object.get_absolute_url_beta()

        return super().form_valid(form)