Repository: liqd/adhocracy4

Issue:
async serializer: also set is_deleted to True for blocked comments
**URL:** 
**user:** 
**expected behaviour:** readable code, comments should have distinctive properties with distinct names, meanings and behavior
**behaviour:** **Async comments** have the properties `is_removed` and `is_deleted`. Comments that are either removed (by a moderator) or deleted (by a creator) are both set to `is_deleted` and their content is permanently deleted.
**important screensize:**
**device & browser:** 
**Comment/Question:** 
Because the serializer does not differentiate between moderator and creator for deleting the comment, does it actually make sense to show this differentiation in the serializer?
This is related to #902 and #903
Screenshot?



Discussion:
is_removed is an actual model field, like is_censored and is_blocked. 
is_deleted is added in the serializer. We use it to determine if we show the ratingBox:
https://github.com/liqd/adhocracy4/search?q=is_deleted
So, that means that we probably also set is_deleted True for is_blocked. You shoudn't be able to rate on blocked comments.
https://github.com/liqd/adhocracy4/blob/635d2a3a2c5c487b5538af4c7d6c255c65b92d5d/adhocracy4/comments_async/serializers.py#L113
Steps to fix:
1. check in kosmo that blocked comments can be rated on. (Is this bug real?)
2. in the serializer: make is_deleted also depend on is_blocked
3. check that it is fine in kosmo

Resolving patch:
diff --git a/adhocracy4/comments_async/serializers.py b/adhocracy4/comments_async/serializers.py
--- a/adhocracy4/comments_async/serializers.py
+++ b/adhocracy4/comments_async/serializers.py
@@ -31,16 +31,15 @@ class Meta:
 
     def to_representation(self, instance):
         """
-        Create a dictionary form categories and don't show blocked comments.
+        Create a dictionary from categories and don't show blocked comments.
 
         Gets the categories and adds them along with their values
-        to a dictionary.
-        Also gets the comments and blocks their content
-        from being shown if they are set to blocked.
+        to a dictionary. Do return empty dict when comment is_blocked.
+        Does return empty string as comment text when comment is_blocked.
         """
         ret = super().to_representation(instance)
         categories = {}
-        if ret['comment_categories']:
+        if ret['comment_categories'] and not instance.is_blocked:
             category_choices = getattr(settings,
                                        'A4_COMMENT_CATEGORIES', '')
             if category_choices:
@@ -53,8 +52,7 @@ def to_representation(self, instance):
                 else:
                     categories[category] = category
         ret['comment_categories'] = categories
-        is_blocked = ret.get('is_blocked')
-        if is_blocked:
+        if instance.is_blocked:
             ret['comment'] = ''
         return ret
 
@@ -70,12 +68,12 @@ def to_internal_value(self, data):
         return data
 
     def get_user_pk(self, obj):
-        if (obj.is_censored or obj.is_removed):
+        if obj.is_censored or obj.is_removed or obj.is_blocked:
             return -1
         return str(obj.creator.id)
 
     def get_user_profile_url(self, obj):
-        if obj.is_censored or obj.is_removed:
+        if obj.is_censored or obj.is_removed or obj.is_blocked:
             return ''
         try:
             return obj.creator.get_absolute_url()
@@ -84,13 +82,13 @@ def get_user_profile_url(self, obj):
 
     def get_user_name(self, obj):
         """Don't show username if comment is marked removed or censored."""
-        if(obj.is_censored or obj.is_removed):
+        if obj.is_censored or obj.is_removed or obj.is_blocked:
             return _('unknown user')
         return obj.creator.get_short_name()
 
     def get_user_image_fallback(self, obj):
         """Load small thumbnail images for default user images."""
-        if(obj.is_censored or obj.is_removed):
+        if obj.is_censored or obj.is_removed or obj.is_blocked:
             return None
         try:
             if obj.creator.avatar_fallback:
@@ -101,7 +99,7 @@ def get_user_image_fallback(self, obj):
 
     def get_user_image(self, obj):
         """Load small thumbnail images for user images."""
-        if(obj.is_censored or obj.is_removed):
+        if obj.is_censored or obj.is_removed or obj.is_blocked:
             return None
         try:
             if obj.creator.avatar:
@@ -116,7 +114,7 @@ def get_is_moderator(self, obj):
 
     def get_is_deleted(self, obj):
         """Return true if one of the flags is set."""
-        return (obj.is_censored or obj.is_removed)
+        return obj.is_censored or obj.is_removed or obj.is_blocked
 
     def get_ratings(self, comment):
         """


Test patch:
diff --git a/tests/comments/test_async_serializer.py b/tests/comments/test_async_serializer.py
--- a/tests/comments/test_async_serializer.py
+++ b/tests/comments/test_async_serializer.py
@@ -83,10 +83,10 @@ def test_serializer(apiclient, question, comment_factory, user):
     # Testing a comment that is set to blocked by a moderator:
     comment_3 = comment_data[4]
     assert comment_3['id'] == 3
-    assert comment_3['user_name'] == ''
-    assert comment_3['user_pk'] == str(user.pk)
+    assert comment_3['user_name'] == 'unknown user'
+    assert comment_3['user_pk'] == -1
     assert comment_3['user_profile_url'] == ''
-    assert comment_3['is_deleted'] is False
+    assert comment_3['is_deleted'] is True
     assert comment_3['is_moderator'] is False
     assert len(comment_3['child_comments']) == 0
     assert comment_3['comment'] != Comment.objects.get(pk=3).comment