Browse Source

handle user leave thread

Rafał Pitoń 8 years ago
parent
commit
ad176fbaf0

+ 1 - 7
misago/readtracker/signals.py

@@ -1,7 +1,7 @@
 from django.dispatch import Signal, receiver
 
 from misago.categories.signals import move_category_content
-from misago.threads.signals import move_thread, remove_thread_participant
+from misago.threads.signals import move_thread
 
 
 all_read = Signal()
@@ -31,9 +31,3 @@ def decrease_unread_private_count(sender, **kwargs):
     if user.pk != thread.starter_id and user.unread_private_threads:
         user.unread_private_threads -= 1
         user.save(update_fields=['unread_private_threads'])
-
-
-@receiver(remove_thread_participant)
-def remove_private_thread_readtrackers(sender, **kwargs):
-    user = kwargs['user']
-    user.threadread_set.filter(thread=sender).delete()

+ 19 - 17
misago/threads/api/threadendpoints/patch.py

@@ -75,26 +75,27 @@ thread_patch_dispatcher.replace('weight', patch_weight)
 
 
 def patch_move(request, thread, value):
-    if thread.acl.get('can_move'):
-        category_pk = get_int_or_404(value)
-        new_category = get_object_or_404(
-            Category.objects.all_categories().select_related('parent'),
-            pk=category_pk
-        )
+    if not thread.acl.get('can_move'):
+        raise PermissionDenied(_("You don't have permission to move this thread."))
 
-        add_acl(request.user, new_category)
-        allow_see_category(request.user, new_category)
-        allow_browse_category(request.user, new_category)
-        allow_start_thread(request.user, new_category)
+    category_pk = get_int_or_404(value)
+    new_category = get_object_or_404(
+        Category.objects.all_categories().select_related('parent'),
+        pk=category_pk
+    )
 
-        if new_category == thread.category:
-            raise PermissionDenied(_("You can't move thread to the category it's already in."))
+    add_acl(request.user, new_category)
+    allow_see_category(request.user, new_category)
+    allow_browse_category(request.user, new_category)
+    allow_start_thread(request.user, new_category)
 
-        moderation.move_thread(request, thread, new_category)
+    if new_category == thread.category:
+        raise PermissionDenied(_("You can't move thread to the category it's already in."))
+
+    moderation.move_thread(request, thread, new_category)
+
+    return {'category': CategorySerializer(new_category).data}
 
-        return {'category': CategorySerializer(new_category).data}
-    else:
-        raise PermissionDenied(_("You don't have permission to move this thread."))
 thread_patch_dispatcher.replace('category', patch_move)
 
 
@@ -238,8 +239,9 @@ def patch_remove_participant(request, thread, value):
         raise PermissionDenied(_("Participant doesn't exist."))
 
     allow_remove_participant(request.user, thread, participant.user)
+    remove_participant(request, thread, participant.user)
 
-    raise NotImplementedError('this execution path is incomplete!')
+    return {}
 
 thread_patch_dispatcher.remove('participants', patch_remove_participant)
 

+ 35 - 5
misago/threads/participants.py

@@ -5,7 +5,6 @@ from misago.core.mail import build_mail, send_messages
 
 from .events import record_event
 from .models import ThreadParticipant
-from .signals import remove_thread_participant
 
 
 def has_participants(thread):
@@ -85,11 +84,42 @@ def build_noticiation_email(request, thread, user):
     )
 
 
-def remove_participant(thread, user):
+def remove_participant(request, thread, user):
     """
     Remove thread participant, set "recound private threads" flag on user
     """
-    thread.threadparticipant_set.filter(user=user).delete()
-    set_users_unread_private_threads_sync([user])
+    removed_owner = False
+    remaining_participants = []
 
-    remove_thread_participant.send(thread, user=user)
+    for participant in thread.participants_list:
+        if participant.user == user:
+            removed_owner = participant.is_owner
+        else:
+            remaining_participants.append(participant.user)
+
+    set_users_unread_private_threads_sync(remaining_participants + [user])
+
+    if not remaining_participants:
+        thread.delete()
+    else:
+        thread.threadparticipant_set.filter(user=user).delete()
+
+        if removed_owner:
+            thread.is_closed = True # flag thread to close
+
+            if request.user == user:
+                event_type = 'owner_left'
+            else:
+                event_type = 'removed_owner'
+        else:
+            if request.user == user:
+                event_type = 'participant_left'
+            else:
+                event_type = 'removed_participant'
+
+        record_event(request, thread, event_type, {
+            'user': {
+                'username': user.username,
+                'url': user.get_absolute_url(),
+            }
+        })

+ 0 - 1
misago/threads/signals.py

@@ -17,7 +17,6 @@ merge_post = Signal(providing_args=["other_post"])
 merge_thread = Signal(providing_args=["other_thread"])
 move_post = Signal()
 move_thread = Signal()
-remove_thread_participant = Signal(providing_args=["user"])
 
 
 """

+ 0 - 13
misago/threads/tests/test_participants.py

@@ -8,7 +8,6 @@ from ..models import Post, Thread, ThreadParticipant
 from ..participants import (
     has_participants,
     make_participants_aware,
-    remove_participant,
     set_owner,
     set_users_unread_private_threads_sync
 )
@@ -96,18 +95,6 @@ class ParticipantsTests(TestCase):
         else:
             self.fail("thread.participants_list didn't contain user")
 
-    def test_remove_participant(self):
-        """remove_participant removes user from thread"""
-        User = get_user_model()
-        user = User.objects.create_user("Bob", "bob@boberson.com", "Pass.123")
-
-        set_owner(self.thread, user)
-        remove_participant(self.thread, user)
-
-        self.assertEqual(self.thread.participants.count(), 0)
-        with self.assertRaises(ThreadParticipant.DoesNotExist):
-            self.thread.threadparticipant_set.get(user=user)
-
     def test_set_owner(self):
         """set_owner sets user as thread owner"""
         User = get_user_model()

+ 14 - 2
misago/threads/tests/test_privatethread_patch_api.py

@@ -6,7 +6,7 @@ from django.core import mail
 from misago.acl.testutils import override_acl
 
 from .. import testutils
-from ..models import ThreadParticipant
+from ..models import Thread, ThreadParticipant
 from .test_privatethreads import PrivateThreadsTestCase
 
 
@@ -177,7 +177,19 @@ class PrivateThreadRemoveParticipantApiTests(PrivateThreadPatchApiTestCase):
             {'op': 'remove', 'path': 'participants', 'value': self.user.pk}
         ])
 
-        raise NotImplementedError('this test scenario is incomplete!')
+        self.assertEqual(response.status_code, 200)
+
+        # thread still exists
+        self.assertTrue(Thread.objects.get(pk=self.thread.pk))
+
+        # users were flagged to sync
+        User = get_user_model()
+        self.assertTrue(User.objects.get(pk=self.other_user.pk).sync_unread_private_threads)
+        self.assertTrue(User.objects.get(pk=self.user.pk).sync_unread_private_threads)
+
+        # user was removed from participation
+        self.assertEqual(self.thread.participants.count(), 1)
+        self.assertEqual(self.thread.participants.filter(pk=self.user.pk).count(), 0)
 
     def test_owner_remove_user(self):
         """api allows owner to remove other user"""