diff --git a/community/serializer_min.py b/community/serializer_min.py index 0b1e32df..4f638006 100644 --- a/community/serializer_min.py +++ b/community/serializer_min.py @@ -48,7 +48,8 @@ class CommunityPostSerializerMin(serializers.ModelSerializer): reactions_count = serializers.SerializerMethodField() user_reaction = serializers.SerializerMethodField() comments_count = serializers.SerializerMethodField() - posted_by = UserProfileSerializer(read_only=True) + # posted_by = UserProfileSerializer(read_only=True) + posted_by = serializers.SerializerMethodField() image_url = serializers.SerializerMethodField() most_liked_comment = serializers.SerializerMethodField() community = CommunitySerializerMin(read_only=True) @@ -58,13 +59,34 @@ class CommunityPostSerializerMin(serializers.ModelSerializer): has_user_reported = serializers.SerializerMethodField() posted_by = serializers.SerializerMethodField() + # def get_posted_by(self, obj): + # pb = UserProfile.objects.get(id=obj.posted_by.id) + # if obj.anonymous: + # pb.name = "Anonymous" + # pb.id = "null" + # pb.ldap_id = "null" + # pb.profile_pic = \ + # 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSM9q9XJKxlskry5gXTz1OXUyem5Ap59lcEGg&usqp=CAU' + # return UserProfileSerializer(pb).data + def get_posted_by(self, obj): - pb = UserProfile.objects.get(id=obj.posted_by.id) - if(obj.anonymous): + pb = UserProfile.objects.get(id=obj.posted_by.id) + if ( + obj.anonymous + and "return_for_mod" in self.context + and not self.context["return_for_mod"] + ): pb.name = "Anonymous" pb.id = "null" - pb.ldap_id = "null" - pb.profile_pic = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSM9q9XJKxlskry5gXTz1OXUyem5Ap59lcEGg&usqp=CAU" + pb.ldap_id = "null" + pb.profile_pic = \ + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSM9q9XJKxlskry5gXTz1OXUyem5Ap59lcEGg&usqp=CAU' + elif ( + obj.anonymous + and "return_for_mod" in self.context + and self.context["return_for_mod"] + ): + pb.name += " (Anon)" return UserProfileSerializer(pb).data def get_most_liked_comment(self, obj): diff --git a/community/serializers.py b/community/serializers.py index 22ef4fe5..91a22b96 100644 --- a/community/serializers.py +++ b/community/serializers.py @@ -74,19 +74,40 @@ class CommunityPostSerializers(CommunityPostSerializerMin): comments = serializers.SerializerMethodField() posted_by = serializers.SerializerMethodField() - def get_posted_by(self, obj): - pb = UserProfile.objects.get(id=obj.posted_by.id) - if(obj.anonymous): - pb.name = "Anonymous" - pb.id = "null" - pb.ldap_id = "null" - pb.profile_pic = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSM9q9XJKxlskry5gXTz1OXUyem5Ap59lcEGg&usqp=CAU" - return UserProfileSerializer(pb).data + # def get_posted_by(self, obj): + # pb = UserProfile.objects.get(id=obj.posted_by.id) + # if obj.anonymous: + # pb.name = "Anonymous" + # pb.id = "null" + # pb.ldap_id = "null" + # pb.profile_pic = \ + # 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSM9q9XJKxlskry5gXTz1OXUyem5Ap59lcEGg&usqp=CAU' + # return UserProfileSerializer(pb).data def get_comments(self, obj): comments = obj.comments.filter(deleted=False, status=1) return CommunityPostSerializerMin(comments, many=True).data + def get_posted_by(self, obj): + pb = UserProfile.objects.get(id=obj.posted_by.id) + if ( + obj.anonymous + and "return_for_mod" in self.context + and not self.context["return_for_mod"] + ): + pb.name = "Anonymous" + pb.id = "null" + pb.ldap_id = "null" + pb.profile_pic = \ + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSM9q9XJKxlskry5gXTz1OXUyem5Ap59lcEGg&usqp=CAU' + elif ( + obj.anonymous + and "return_for_mod" in self.context + and self.context["return_for_mod"] + ): + pb.name += " (Anon)" + return UserProfileSerializer(pb).data + class Meta: model = CommunityPost fields = ( diff --git a/community/tests.py b/community/tests.py index fe8675a3..c76867c7 100644 --- a/community/tests.py +++ b/community/tests.py @@ -71,7 +71,7 @@ def test_community_get(self): def test_communitypost_alllist(self): """Test if communityposts can be listed.""" - url = "/api/communityposts?status=1" + url = "/api/communityposts?status=1&community=" + str(self.test_community_1.id) response = self.client1.get(url, format="json") data = response.data["data"] self.assertEqual(response.status_code, 200) @@ -82,14 +82,14 @@ def test_communitypost_alllist(self): ) def test_communitypost_yourlist(self): - url = "/api/communityposts" + url = "/api/communityposts?community=" + str(self.test_community_1.id) response = self.client1.get(url, format="json") data = response.data["data"] self.assertEqual(response.status_code, 200) self.assertEqual( response.data["count"], CommunityPost.objects.filter( - thread_rank=1, posted_by=self.user1.profile + thread_rank=1, posted_by=self.user1.profile, community=self.test_community_1 ).count(), ) self.assertListEqual( @@ -98,7 +98,7 @@ def test_communitypost_yourlist(self): ) def test_communitypost_pendinglist(self): - url = "/api/communityposts?status=0" + url = "/api/communityposts?status=0&community=" + str(self.test_community_1.id) response = self.client1.get(url, format="json") data = response.data["data"] self.assertEqual(response.status_code, 200) diff --git a/community/urls.py b/community/urls.py index 47d80213..0b00ddfc 100644 --- a/community/urls.py +++ b/community/urls.py @@ -4,12 +4,7 @@ urlpatterns = [ path( - "communities", - CommunityViewSet.as_view( - { - "get": "list", - } - ), + "communities", CommunityViewSet.as_view({"get": "list", "post": "create"}) ), # viewing the list of communities path( "communities/", diff --git a/community/views.py b/community/views.py index a9a70082..df942298 100644 --- a/community/views.py +++ b/community/views.py @@ -11,6 +11,7 @@ from roles.helpers import forbidden_no_privileges from helpers.misc import query_from_num from helpers.misc import query_search +from users.models import UserProfile class ModeratorViewSet(viewsets.ModelViewSet): @@ -70,7 +71,12 @@ def retrieve_full(self, request, pk): self.queryset, request ) post = self.get_community_post(pk) - serialized = CommunityPostSerializers(post, context={"request": request}).data + return_for_mod = False + if user_has_privilege(request.user.profile, post.community.body.id, "AppP"): + return_for_mod = True + serialized = CommunityPostSerializers( + post, context={"return_for_mod": return_for_mod} + ).data return Response(serialized) @@ -81,29 +87,36 @@ def list(self, request): # Check for time and date filtered query params status = request.GET.get("status") + comm_id = request.GET.get("community") + if comm_id is None: + return Response({"message": "comm_id is required"}, status=400) + community = get_object_or_404(Community.objects, id=comm_id) # If your posts if status is None: queryset = CommunityPost.objects.filter( - thread_rank=1, posted_by=request.user.profile + thread_rank=1, community=community, posted_by=request.user.profile ).order_by("-time_of_modification") else: # If reported posts if status == "3": queryset = CommunityPost.objects.filter( - status=status, deleted=False + status=status, community=community, deleted=False ).order_by("-time_of_modification") # queryset = CommunityPost.objects.all() else: queryset = CommunityPost.objects.filter( - status=status, deleted=False, thread_rank=1 + status=status, community=community, deleted=False, thread_rank=1 ).order_by("-time_of_modification") queryset = query_search(request, 3, queryset, ["content"], "posts") queryset = query_from_num(request, 20, queryset) + return_for_mod = False + if user_has_privilege(request.user.profile, community.body.id, "AppP"): + return_for_mod = True serializer = CommunityPostSerializerMin( - queryset, many=True, context={"request": request} + queryset, many=True, context={"return_for_mod": return_for_mod} ) data = serializer.data @@ -117,6 +130,7 @@ def create(self, request): if "community" not in request.data or not request.data["community"]: return forbidden_no_privileges() + user, created = UserProfile.objects.get_or_create(user=request.user) return super().create(request) @login_required_ajax @@ -235,3 +249,13 @@ def get_community(self, pk): return get_object_or_404(self.queryset, id=pk) except ValueError: return get_object_or_404(self.queryset, str_id=pk) + + @login_required_ajax + def create(self, request): + name = request.data["name"] + user, created = UserProfile.objects.get_or_create(user=request.user) + if not Community.objects.all().filter(name=name).exists(): + super().create(request) + return Response({"message": "Community created"}) + + return Response({"message": "Community already exists"}, status=400) diff --git a/helpers/misc.py b/helpers/misc.py index 7ff6f58e..06a020fd 100644 --- a/helpers/misc.py +++ b/helpers/misc.py @@ -40,6 +40,7 @@ def query_from_num(request, default_num, queryset): return queryset[from_i: from_i + num] + def query_search( # pylint: disable=too-many-arguments request, min_length, queryset, fields, collection, order_relevance=False ): diff --git a/other/tasks.py b/other/tasks.py index b9de543c..f4d90f0b 100644 --- a/other/tasks.py +++ b/other/tasks.py @@ -82,11 +82,14 @@ def notify_new_commpost(pk): notify.send(instance, recipient=users, verb="New post added in " + community.name) for interest in instance.interests.all(): - users = User.objects.filter( - id__in=UserInterest.filter(title=interest.title) - .user.filter(active=True) - .values("user_id") + users = ( + User.objects.filter( + id__in=UserInterest.objects.filter(title=interest.title) + ) + .filter(is_active=True) + .values("id") ) + notify.send( instance, recipient=users, diff --git a/roles/migrations/0020_communityrole.py b/roles/migrations/0020_communityrole.py new file mode 100644 index 00000000..dc7a868e --- /dev/null +++ b/roles/migrations/0020_communityrole.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.16 on 2023-07-07 14:40 + +from django.db import migrations, models +import django.db.models.deletion +import multiselectfield.db.fields +import uuid + + +class Migration(migrations.Migration): + dependencies = [ + ("community", "0028_auto_20221003_2130"), + ("roles", "0019_alter_bodyrole_permissions"), + ] + + operations = [ + migrations.CreateModel( + name="CommunityRole", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, + editable=False, + primary_key=True, + serialize=False, + ), + ), + ("time_of_creation", models.DateTimeField(auto_now_add=True)), + ("name", models.CharField(max_length=50)), + ("inheritable", models.BooleanField(default=False)), + ( + "permissions", + multiselectfield.db.fields.MultiSelectField( + choices=[ + ("AddE", "Add Event"), + ("UpdE", "Update Event"), + ("DelE", "Delete Event"), + ("UpdB", "Update Body"), + ("Role", "Modify Roles"), + ("VerA", "Verify Achievements"), + ("AppP", "Moderate Post"), + ("ModC", "Moderate Comment"), + ], + max_length=39, + ), + ), + ("priority", models.IntegerField(default=0)), + ("official_post", models.BooleanField(default=True)), + ("permanent", models.BooleanField(default=False)), + ( + "community", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="roles", + to="community.community", + ), + ), + ], + options={ + "verbose_name": "Community Role", + "verbose_name_plural": "Community Roles", + "ordering": ("community__name", "priority"), + }, + ), + ] diff --git a/roles/migrations/0021_delete_communityrole.py b/roles/migrations/0021_delete_communityrole.py new file mode 100644 index 00000000..f4c7c1aa --- /dev/null +++ b/roles/migrations/0021_delete_communityrole.py @@ -0,0 +1,16 @@ +# Generated by Django 3.2.16 on 2023-07-22 13:35 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("users", "0043_remove_userprofile_community_roles"), + ("roles", "0020_communityrole"), + ] + + operations = [ + migrations.DeleteModel( + name="CommunityRole", + ), + ] diff --git a/roles/models.py b/roles/models.py index e024f091..9f87d400 100644 --- a/roles/models.py +++ b/roles/models.py @@ -39,6 +39,33 @@ def __str__(self): return self.body.name + " " + self.name +""" +Added Community Role Model : To allow to have various communities in a single body and have different roles for each +community. +Ditched For Now +""" +# class CommunityRole(models.Model): +# """A role for a bodywhich can be granted to multiple users.""" + +# id = models.UUIDField(primary_key=True, default=uuid4, editable=False) +# time_of_creation = models.DateTimeField(auto_now_add=True) +# name = models.CharField(max_length=50) +# community = models.ForeignKey('community.Community', on_delete=models.CASCADE, related_name='roles') +# inheritable = models.BooleanField(default=False) +# permissions = MultiSelectField(choices=PERMISSION_CHOICES) +# priority = models.IntegerField(default=0) +# official_post = models.BooleanField(default=True) +# permanent = models.BooleanField(default=False) + +# class Meta: +# verbose_name = "Community Role" +# verbose_name_plural = "Community Roles" +# ordering = ("community__name", "priority") + +# def __str__(self): +# return self.community.name + " " + self.name + + INSTITUTE_PERMISSION_CHOICES = ( ("AddB", "Add Body"), ("DelB", "Delete Body"), diff --git a/users/migrations/0041_userprofile_community_roles.py b/users/migrations/0041_userprofile_community_roles.py new file mode 100644 index 00000000..223480c5 --- /dev/null +++ b/users/migrations/0041_userprofile_community_roles.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.16 on 2023-07-07 14:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("roles", "0020_communityrole"), + ("users", "0040_remove_userprofile_followed_communities"), + ] + + operations = [ + migrations.AddField( + model_name="userprofile", + name="community_roles", + field=models.ManyToManyField( + blank=True, related_name="users", to="roles.CommunityRole" + ), + ), + ] diff --git a/users/migrations/0042_userprofile_followed_communities.py b/users/migrations/0042_userprofile_followed_communities.py new file mode 100644 index 00000000..f3f8649d --- /dev/null +++ b/users/migrations/0042_userprofile_followed_communities.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.16 on 2023-07-07 23:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("community", "0028_auto_20221003_2130"), + ("users", "0041_userprofile_community_roles"), + ] + + operations = [ + migrations.AddField( + model_name="userprofile", + name="followed_communities", + field=models.ManyToManyField( + blank=True, related_name="community_followers", to="community.Community" + ), + ), + ] diff --git a/users/migrations/0043_remove_userprofile_community_roles.py b/users/migrations/0043_remove_userprofile_community_roles.py new file mode 100644 index 00000000..24242966 --- /dev/null +++ b/users/migrations/0043_remove_userprofile_community_roles.py @@ -0,0 +1,16 @@ +# Generated by Django 3.2.16 on 2023-07-22 13:35 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("users", "0042_userprofile_followed_communities"), + ] + + operations = [ + migrations.RemoveField( + model_name="userprofile", + name="community_roles", + ), + ] diff --git a/users/migrations/0044_remove_userprofile_followed_communities.py b/users/migrations/0044_remove_userprofile_followed_communities.py new file mode 100644 index 00000000..2d30cdfe --- /dev/null +++ b/users/migrations/0044_remove_userprofile_followed_communities.py @@ -0,0 +1,16 @@ +# Generated by Django 3.2.16 on 2023-07-24 18:08 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("users", "0043_remove_userprofile_community_roles"), + ] + + operations = [ + migrations.RemoveField( + model_name="userprofile", + name="followed_communities", + ), + ] diff --git a/users/models.py b/users/models.py index 7c6f337a..849859e8 100644 --- a/users/models.py +++ b/users/models.py @@ -63,7 +63,7 @@ class UserProfile(models.Model): institute_roles = models.ManyToManyField( "roles.InstituteRole", related_name="users", blank=True ) - + # community_roles = models.ManyToManyField('roles.CommunityRole', related_name='users', blank=True) # User exposed fields show_contact_no = models.BooleanField(default=False) fcm_id = models.CharField(max_length=200, null=True, blank=True)