Repository: zestedesavoir/zds-site

Issue:
[v23] Erreur 403 lors de l'accès à la galerie liée à un contenu
Sur la RC2 de la v23, lorsque je crée un contenu (testé avec un article et un billet), j'ai une erreur 403 lorsque j'accède à la galerie liée. Je pense que les droits ne sont pas ajoutés lors de la création du contenu.

Remarque : sur un contenu créé avec la RC1, je n'ai pas ce problème.

- [x] améliorer les tests pour qu'il y ait des assertion sur les galleries
- [x] check `ensure_author_gallery`


Discussion:
ok c'est ma modif de refacto qui a joué alors.

Resolving patch:
diff --git a/zds/tutorialv2/models/models_database.py b/zds/tutorialv2/models/models_database.py
--- a/zds/tutorialv2/models/models_database.py
+++ b/zds/tutorialv2/models/models_database.py
@@ -37,7 +37,7 @@
 from elasticsearch_dsl.field import Text, Keyword, Date, Boolean
 
 from zds.forum.models import Topic
-from zds.gallery.models import Image, Gallery, UserGallery
+from zds.gallery.models import Image, Gallery, UserGallery, GALLERY_WRITE
 from zds.tutorialv2.managers import PublishedContentManager, PublishableContentManager
 from zds.tutorialv2.models import TYPE_CHOICES, STATUS_CHOICES, CONTENT_TYPES_VALIDATION_BEFORE, PICK_OPERATIONS
 from zds.tutorialv2.models.models_versioned import NotAPublicVersion
@@ -218,13 +218,14 @@ def ensure_author_gallery(self):
         """
         ensure all authors subscribe to gallery
         """
-        author_set = UserGallery.objects.filter(user__in=list(self.authors.all()), gallery=self.gallery)
+        author_set = UserGallery.objects.filter(user__in=list(self.authors.all()), gallery=self.gallery)\
+            .values_list('user__pk', flat=True)
         for author in self.authors.all():
-            if author in author_set:
+            if author.pk in author_set:
                 continue
             user_gallery = UserGallery()
             user_gallery.gallery = self.gallery
-            user_gallery.mode = 'W'  # write mode
+            user_gallery.mode = GALLERY_WRITE  # write mode
             user_gallery.user = author
             user_gallery.save()
 
diff --git a/zds/tutorialv2/views/views_contents.py b/zds/tutorialv2/views/views_contents.py
--- a/zds/tutorialv2/views/views_contents.py
+++ b/zds/tutorialv2/views/views_contents.py
@@ -106,7 +106,6 @@ def form_valid(self, form):
 
         self.content.gallery = gal
         self.content.save()
-        self.content.ensure_author_gallery()
         # create image:
         if 'image' in self.request.FILES:
             img = Image()
@@ -122,7 +121,8 @@ def form_valid(self, form):
 
         # We need to save the content before changing its author list since it's a many-to-many relationship
         self.content.authors.add(self.request.user)
-
+        self.content.ensure_author_gallery()
+        self.content.save()
         # Add subcategories on tutorial
         for subcat in form.cleaned_data['subcategory']:
             self.content.subcategory.add(subcat)
@@ -1750,9 +1750,11 @@ def form_valid(self, form):
             _type = _(u'du billet')
 
         bot = get_object_or_404(User, username=settings.ZDS_APP['member']['bot_account'])
+        all_authors_pk = [author.pk for author in self.object.authors.all()]
         for user in form.cleaned_data['users']:
-            if user not in self.object.authors.all() and user != self.request.user:
+            if user.pk not in all_authors_pk and user != self.request.user:
                 self.object.authors.add(user)
+                all_authors_pk.append(user.pk)
                 url_index = reverse('content:find-' + self.object.type.lower(), args=[user.pk])
                 send_mp(
                     bot,
@@ -1769,11 +1771,7 @@ def form_valid(self, form):
                     True,
                     direct=False,
                 )
-                new_user = UserGallery()
-                new_user.gallery = self.object.gallery
-                new_user.user = user
-                new_user.mode = GALLERY_WRITE
-                new_user.save()
+                UserGallery(gallery=self.object.gallery, user=user, mode=GALLERY_WRITE).save()
         self.object.save()
         if not self.already_finished:
             self.success_url = self.object.get_absolute_url()


Test patch:
diff --git a/zds/tutorialv2/tests/tests_models.py b/zds/tutorialv2/tests/tests_models.py
--- a/zds/tutorialv2/tests/tests_models.py
+++ b/zds/tutorialv2/tests/tests_models.py
@@ -7,6 +7,8 @@
 from django.conf import settings
 from django.test import TestCase
 from django.test.utils import override_settings
+
+from zds.gallery.models import UserGallery
 from zds.settings import BASE_DIR
 
 from zds.member.factories import ProfileFactory, StaffProfileFactory
@@ -553,6 +555,18 @@ def test_char_count_after_publication(self):
         published = PublishedContent.objects.filter(content=tuto).first()
         self.assertEqual(published.get_char_count(), 335 + len_date_now)
 
+    def test_ensure_gallery(self):
+        content = PublishedContentFactory()
+        content.authors.add(ProfileFactory().user)
+        content.authors.add(ProfileFactory().user)
+        content.save()
+        content.ensure_author_gallery()
+        self.assertEqual(UserGallery.objects.filter(gallery__pk=content.gallery.pk).count(), content.authors.count())
+        content.authors.add(ProfileFactory().user)
+        content.save()
+        content.ensure_author_gallery()
+        self.assertEqual(UserGallery.objects.filter(gallery__pk=content.gallery.pk).count(), content.authors.count())
+
     def tearDown(self):
         if os.path.isdir(settings.ZDS_APP['content']['repo_private_path']):
             shutil.rmtree(settings.ZDS_APP['content']['repo_private_path'])
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
@@ -294,6 +294,7 @@ def test_basic_tutorial_workflow(self):
         versioned = tuto.load_version()
 
         self.assertEqual(Gallery.objects.filter(pk=tuto.gallery.pk).count(), 1)
+        self.assertEqual(UserGallery.objects.filter(gallery__pk=tuto.gallery.pk).count(), tuto.authors.count())
         self.assertEqual(Image.objects.filter(gallery__pk=tuto.gallery.pk).count(), 1)  # icon is uploaded
 
         # access to tutorial
@@ -3986,7 +3987,12 @@ def test_delete_with_multiple_authors(self):
         tuto = PublishableContent.objects.get(pk=self.tuto.pk)
         self.assertEqual(tuto.authors.count(), 2)
         self.assertEqual(tuto.authors.filter(pk=new_author.pk).count(), 1)
-        self.assertEqual(UserGallery.objects.filter(user=new_author, gallery=tuto.gallery).count(), 1)
+        self.assertEqual(UserGallery.objects.filter(user=new_author, gallery=tuto.gallery).count(), 1,
+                         'nb_author={}, nb_gallery={}, gallery_pk={}'.format(tuto.authors.count(),
+                                                                             UserGallery.objects
+                                                                                        .filter(gallery=tuto.gallery)
+                                                                                        .count(),
+                                                                             tuto.gallery.pk))
 
         # login with this new author, try to delete tuto
         self.assertEqual(