Repository: zestedesavoir/zds-site

Issue:
[v17] Impossible de répondre à un message privé à partir de l'API
Serveur : Prod
Version : v17-haïku/8cb7666
Système : OS X
Navigateur : Google Chrome Version 48.0.2564.116 (64-bit)

Scénario :
1. Fournissez-vous de tokens d'authentification et récupérez l'identifiant d'un message privé.
2. Faites une requête depuis l'API pour poster un nouveau message dans ce message privé.
3. Constatez une erreur 403.



Discussion:

Resolving patch:
diff --git a/zds/mp/api/permissions.py b/zds/mp/api/permissions.py
--- a/zds/mp/api/permissions.py
+++ b/zds/mp/api/permissions.py
@@ -24,14 +24,14 @@ def has_permission(self, request, view):
         return private_topic.is_participant(request.user)
 
 
-class IsAloneInPrivatePost(permissions.BasePermission):
+class IsNotAloneInPrivatePost(permissions.BasePermission):
     """
     Custom permission to know if a member is the only participant in a private topic.
     """
 
     def has_permission(self, request, view):
         private_topic = get_object_or_404(PrivateTopic, pk=view.kwargs.get('pk_ptopic'))
-        return private_topic.participants.count() == 0
+        return not private_topic.alone()
 
 
 class IsLastPrivatePostOfCurrentUser(permissions.BasePermission):
diff --git a/zds/mp/api/views.py b/zds/mp/api/views.py
--- a/zds/mp/api/views.py
+++ b/zds/mp/api/views.py
@@ -16,7 +16,7 @@
 from zds.api.DJRF3xPaginationKeyBit import DJRF3xPaginationKeyBit
 
 from zds.mp.api.permissions import IsParticipant, IsParticipantFromPrivatePost, IsLastPrivatePostOfCurrentUser, \
-    IsAloneInPrivatePost, IsAuthor
+    IsAuthor, IsNotAloneInPrivatePost
 from zds.mp.api.serializers import PrivateTopicSerializer, PrivateTopicUpdateSerializer, PrivateTopicCreateSerializer, \
     PrivatePostSerializer, PrivatePostUpdateSerializer, PrivatePostCreateSerializer
 from zds.mp.commons import LeavePrivateTopic, MarkPrivateTopicAsRead
@@ -372,21 +372,18 @@ def post(self, request, *args, **kwargs):
         """
         return self.create(request, *args, **kwargs)
 
+    def get_permissions(self):
+        permission_classes = [IsAuthenticated, IsParticipantFromPrivatePost, DRYPermissions, ]
+        if self.request.method == 'POST':
+            permission_classes.append(IsNotAloneInPrivatePost)
+        return [permission() for permission in permission_classes]
+
     def get_serializer_class(self):
         if self.request.method == 'GET':
             return PrivatePostSerializer
         elif self.request.method == 'POST':
             return PrivatePostCreateSerializer
 
-    def get_permissions(self):
-        permission_classes = [IsAuthenticated, IsParticipantFromPrivatePost, ]
-        if self.request.method == 'GET':
-            permission_classes.append(DRYPermissions)
-        elif self.request.method == 'POST':
-            permission_classes.append(IsAloneInPrivatePost)
-            permission_classes.append(DRYPermissions)
-        return [permission() for permission in permission_classes]
-
     def get_queryset(self):
         return PrivatePost.objects.get_message_of_a_private_topic(self.kwargs.get('pk_ptopic'))
 


Test patch:
diff --git a/zds/mp/api/tests.py b/zds/mp/api/tests.py
--- a/zds/mp/api/tests.py
+++ b/zds/mp/api/tests.py
@@ -620,6 +620,7 @@ def setUp(self):
         authenticate_client(self.client, client_oauth2, self.profile.user.username, 'hostel77')
 
         self.private_topic = PrivateTopicFactory(author=self.profile.user)
+        self.private_topic.participants.add(ProfileFactory().user)
 
         caches[extensions_api_settings.DEFAULT_USE_CACHE].clear()
 
@@ -832,16 +833,32 @@ def test_create_post_with_bad_topic_id(self):
         response = self.client.post(reverse('api-mp-message-list', args=[99999]), data)
         self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
 
-    def test_create_post(self):
+    def test_create_post_in_a_private_topic_with_messages(self):
         """
-        Creates a post in a topic
+        Creates a post in a private topic with existing messages.
         """
+        PrivatePostFactory(author=self.profile.user, privatetopic=self.private_topic, position_in_topic=1)
+        participant = ProfileFactory()
+        self.private_topic.participants.add(participant.user)
+        PrivatePostFactory(author=participant.user, privatetopic=self.private_topic, position_in_topic=2)
+
         data = {
             'text': 'Welcome to this private post!'
         }
         response = self.client.post(reverse('api-mp-message-list', args=[self.private_topic.id]), data)
         self.assertEqual(response.status_code, status.HTTP_201_CREATED)
 
+    def test_create_post_without_any_participant(self):
+        """
+        Creates a post in a topic without any participant.
+        """
+        data = {
+            'text': 'Welcome to this private post!'
+        }
+        private_topic = PrivateTopicFactory(author=self.profile.user)
+        response = self.client.post(reverse('api-mp-message-list', args=[private_topic.id]), data)
+        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+
 
 class PrivatePostDetailAPI(APITestCase):
     def setUp(self):
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
@@ -20,13 +20,14 @@
     SubCategoryFactory, PublishedContentFactory, tricky_text_content, BetaContentFactory
 from zds.tutorialv2.models.models_database import PublishableContent, Validation, PublishedContent, ContentReaction, \
     ContentRead
-from zds.tutorialv2.publication_utils import publish_content
 from zds.gallery.factories import UserGalleryFactory
 from zds.gallery.models import Image
 from zds.forum.factories import ForumFactory, CategoryFactory
 from zds.forum.models import Topic, Post, TopicFollowed, TopicRead
 from zds.mp.models import PrivateTopic
 from django.utils.encoding import smart_text
+
+from zds.tutorialv2.publication_utils import publish_content, Publicator, PublicatorRegistery
 from zds.utils.models import HelpWriting, CommentDislike, CommentLike, Alert
 from zds.utils.factories import HelpWritingFactory
 from zds.utils.templatetags.interventions import interventions_topics
@@ -46,6 +47,13 @@
 overrided_zds_app['content']['extra_content_generation_policy'] = "SYNC"
 
 
+@PublicatorRegistery.register("pdf")
+class FakePDFPublicator(Publicator):
+    def publish(self, md_file_path, base_name, **kwargs):
+        with open(md_file_path[:-2] + "pdf", "w") as f:
+            f.write("plouf")
+
+
 @override_settings(MEDIA_ROOT=os.path.join(BASE_DIR, 'media-test'))
 @override_settings(ZDS_APP=overrided_zds_app)
 class ContentTests(TestCase):