Repository: zestedesavoir/zds-site

Issue:
Réserver son propre contenu crée un MP vide avec 2 fois le même utilisateur
Pour reproduire, avec un utilisateur qui peut valider des contenus (admin par exemple via les fixtures): 
- Créer un contenu (article ou tutoriel)
- Demander la validation du contenu
- Réserver le contenu
- Aller dans ses MP

Bug en image : http://i.imgur.com/b73ojhz.png



Discussion:
Congrats, tu viens de gagner le premier usage du tag `P-Basse`. :)

Dans la vraie vie, c'est pas censé arrivé qu'un staff valide son propre contenu.

Dans ce cas, il faut faire quoi ? Interdire la réservation de ses propres contenus, ou ne pas envoyer de MP quand ça arrive ?

~~Plutôt interdire la réservation de ses propres contenus je dirais, non ? Car ils ne sont pas sensés pouvoir publier un de leur contenu tout seul (si un Staff pète un cable et met un tutoriel nawak en page d'accueil, c'est bof)~~

(voir https://github.com/zestedesavoir/zds-site/issues/3776#issuecomment-241238357)

Ne pas envoyer de MP. Réserver son propre contenu, c'est pratique pour
corriger des fôtes.

Le 20 août 2016 à 21:41, Situphen notifications@github.com a écrit :

> Plutôt interdire la réservation de ses propres contenus je dirais, non ?
> Car ils ne sont pas sensés pouvoir publier un de leur contenu tout seul (si
> un Staff pète un cable et met un tutoriel nawak en page d'accueil, c'est
> bof)
> 
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> https://github.com/zestedesavoir/zds-site/issues/3776#issuecomment-241219674,
> or mute the thread
> https://github.com/notifications/unsubscribe-auth/AFhKnDEqnZYcnpNCNNpN3DKjgAZBjOSHks5qh1hTgaJpZM4JopBe
> .

> Réserver son propre contenu, c'est pratique pour corriger des fôtes.

Tu peux détailler ? Je comprends pas trop. :/

Le jour où on ne peut plus publier ses propres contenus j'arrête la QA !

@Situphen imagine que @SpaceFox soit DTC de ZdS. Il écrit un article à propos de la dernière version de ZdS. Il le publie. Il voit qu'il y a une faute de frappe, il veut la corriger. Il la corrige. Quelle est la procédure idéale ? Soumettre sa correction de faute de frappe à validation, attendre des heures que quelqu'un réserve et valide, ou plutôt réserver lui-même le contenu pour valider immédiatement sa modification ? :)

En y réfléchissant, je suis d'accord avec la proposition de @SpaceFox, réserver son propre tutoriel peut être très utile et puis si jamais un Staff pète un câble, il a 3600 autres manières de faire du site une poubelle xD (mais ça n'arrivera pas, <3 aux Staffeux) !

Et les autres messages (validation annulée, validation refusée), faut-il aussi ne pas les envoyer dans le cas où l’auteur est seul et qu’il est le validateur ?

Aujourd'hui, en parcourant les tests des contenus, je suis tombé là dessus : https://github.com/zestedesavoir/zds-site/blob/dev/zds/tutorialv2/tests/tests_views.py#L1889-L1906

On semble avoir spécifié que nous ne voulons pas s'auto-publier.

Effectivement @GerardPaligot , il faudra penser à enlever ce test.

Non, @GerardPaligot : malgré ce commentaire succin (et pas très explicite), un staff peut très bien s'auto-publier. Le test est plus là pour vérifier qu'on c'est pas foiré sur la gestion des droits et qu'un utilisateur lambda n'as pas le pouvoir d'un staff :)

@pierre-24 : il faudrait tester qu’un utilisateur non staff ne peut pas publier un contenu, pas seulement ses contenus, donc il faudrait tester la réservation et la validation avec un autre utilisateur non staff que l’auteur.

Ce qui est fait [juste en dessous](https://github.com/zestedesavoir/zds-site/blob/dev/zds/tutorialv2/tests/tests_views.py#L1910) ;)

(j'ai assez bien betonné les tests à ce niveau là)

Non, il y a juste le test pour l’accès à la version en validation (`public cannot access a tutorial in validation` et `Same for guest`), il n’y a pas le test pour la réservation et la validation.

Anéfé, j'avais pas vu ;)


Resolving patch:
diff --git a/zds/tutorialv2/views/views_validations.py b/zds/tutorialv2/views/views_validations.py
--- a/zds/tutorialv2/views/views_validations.py
+++ b/zds/tutorialv2/views/views_validations.py
@@ -270,16 +270,20 @@ def post(self, request, *args, **kwargs):
                     'url': versioned.get_absolute_url() + '?version=' + validation.version,
                 })
 
-            send_mp(
-                validation.validator,
-                validation.content.authors.all(),
-                _(u"Contenu réservé - {0}").format(validation.content.title),
-                validation.content.title,
-                msg,
-                True,
-                leave=False,
-                direct=False
-            )
+            authors = list(validation.content.authors.all())
+            if validation.validator in authors:
+                authors.remove(validation.validator)
+            if authors.__len__ > 0:
+                send_mp(
+                    validation.validator,
+                    authors,
+                    _(u"Contenu réservé - {0}").format(validation.content.title),
+                    validation.content.title,
+                    msg,
+                    True,
+                    leave=False,
+                    direct=False
+                )
 
             messages.info(request, _(u"Ce contenu a bien été réservé par {0}.").format(request.user.username))
 


Test patch:
diff --git a/zds/tutorialv2/tests/tests_views.py b/zds/tutorialv2/tests/tests_views.py
--- a/zds/tutorialv2/tests/tests_views.py
+++ b/zds/tutorialv2/tests/tests_views.py
@@ -1886,7 +1886,7 @@ def test_validation_workflow(self):
         self.assertEqual(validation.version, self.tuto_draft.current_version)
         self.assertEqual(validation.status, 'PENDING')
 
-        # ensure that author cannot publish himself
+        # ensure that author (not staff) cannot access to the validation.
         result = self.client.post(
             reverse('validation:reserve', kwargs={'pk': validation.pk}),
             {
@@ -2236,6 +2236,45 @@ def test_validation_workflow(self):
         self.assertEqual(PrivateTopic.objects.filter(author=self.user_staff).count(), 6)
         self.assertEqual(PrivateTopic.objects.last().author, self.user_staff)  # admin has received another PM
 
+    def test_auto_validation(self):
+        """Test that a staff can validate himself"""
+
+        tuto = PublishableContent.objects.get(pk=self.tuto.pk)
+        tuto.authors.add(self.user_staff)
+        tuto.save()
+
+        self.assertEqual(self.client.login(username=self.user_staff.username, password='hostel77'), True)
+        self.assertEqual(Validation.objects.count(), 0)
+
+        result = self.client.post(
+            reverse('validation:ask', kwargs={'pk': tuto.pk, 'slug': tuto.slug}),
+            {
+                'text': u'Valide moi ce truc, s\'il te plait',
+                'version': self.tuto_draft.current_version
+            },
+            follow=False)
+        self.assertEqual(result.status_code, 302)
+        self.assertEqual(Validation.objects.count(), 1)
+
+        validation = Validation.objects.filter(content=tuto).last()
+        self.assertIsNotNone(validation)
+
+        self.assertTrue(self.user_staff in tuto.authors.all())
+        self.assertEqual(0, PrivateTopic.objects.filter(author=self.user_staff, participants=self.user_staff).count())
+        result = self.client.post(
+            reverse('validation:reserve', kwargs={'pk': validation.pk}),
+            {
+                'version': validation.version
+            },
+            follow=False)
+        self.assertEqual(result.status_code, 302)
+        self.assertTrue(self.user_staff in tuto.authors.all())
+        self.assertEqual(0, PrivateTopic.objects.filter(author=self.user_staff, participants=self.user_staff).count())
+
+        validation = Validation.objects.filter(content=tuto).last()
+        self.assertEqual(validation.status, 'PENDING_V')
+        self.assertEqual(validation.validator, self.user_staff)
+
     def test_delete_while_validating(self):
         """this test ensure that the validator is warned if the content he is validing is removed"""