Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion pydis_site/apps/api/models/bot/user.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from functools import lru_cache

from django.contrib.postgres.fields import ArrayField
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
Expand Down Expand Up @@ -70,14 +72,20 @@ def __str__(self):
return f"{self.name}#{self.discriminator:04d}"
return self.name

@staticmethod
@lru_cache(maxsize=256)
def _get_roles(role_ids: tuple[int, ...]) -> list[Role]:
"""Fetch the given roles, cached to avoid refetching the same roles for every user."""
return list(Role.objects.filter(id__in=role_ids))

@property
def top_role(self) -> Role:
"""
Attribute that returns the user's top role.

This will fall back to the Developers role if the user does not have any roles.
"""
roles = Role.objects.filter(id__in=self.roles)
roles = self._get_roles(tuple(sorted(self.roles)))
if not roles:
return Role.objects.get(name="Developers")
return max(roles)
Expand Down
9 changes: 5 additions & 4 deletions pydis_site/apps/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,10 +435,11 @@ def to_representation(self, instance: FilterList) -> dict:
into a sub-field called `settings`.
"""
schema = {name: getattr(instance, name) for name in BASE_FILTERLIST_FIELDS}
schema['filters'] = [
FilterSerializer(many=False).to_representation(instance=item)
for item in Filter.objects.filter(filter_list=instance.id).prefetch_related('filter_list')
]
filters = []
for item in instance.filters.all():
item.filter_list = instance
filters.append(FilterSerializer(many=False).to_representation(instance=item))
schema['filters'] = filters

settings = {name: getattr(instance, name) for name in BASE_SETTINGS_FIELDS}
settings['infraction_and_notification'] = {
Expand Down
9 changes: 8 additions & 1 deletion pydis_site/apps/api/signals.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from django.db.models.signals import post_delete
from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver

from pydis_site.apps.api.models.bot import Role, User
Expand All @@ -10,3 +10,10 @@ def delete_role_from_user(sender: Role, instance: Role, **kwargs) -> None:
for user in User.objects.filter(roles__contains=[instance.id]):
del user.roles[user.roles.index(instance.id)]
user.save()


@receiver(signal=post_save, sender=Role)
@receiver(signal=post_delete, sender=Role)
def clear_top_role_cache(sender: Role, **kwargs) -> None:
"""Clear the cached role lookups used by `User.top_role` when a role changes."""
User._get_roles.cache_clear()
14 changes: 14 additions & 0 deletions pydis_site/apps/api/tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,20 @@ def test_filter_unique_constraint(self) -> None:
response = self.client.post(test_filter.url(), data=clean_test_json(test_filter.object))
self.assertEqual(response.status_code, 400)

def test_filter_list_includes_nested_filters(self) -> None:
filter_list = FilterList.objects.create(**get_test_sequences()["filter_list1"].object)
filter_ = Filter.objects.create(
filter_list=filter_list, content="bad word", description="This is a bad word."
)

response = self.client.get(f"{reverse('api:bot:filterlist-list')}/{filter_list.id}")

self.assertEqual(response.status_code, 200)
filters = response.json()["filters"]
self.assertEqual(len(filters), 1)
self.assertEqual(filters[0]["id"], filter_.id)
self.assertEqual(filters[0]["filter_list"], filter_list.id)


class FilterCreationMissingOptionalFieldsTestCase(AuthenticatedAPITestCase):
@classmethod
Expand Down
8 changes: 8 additions & 0 deletions pydis_site/apps/staff/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from django.db.models import Prefetch
from django.views.generic.detail import DetailView

from pydis_site.apps.api.models.bot.deleted_message import DeletedMessage
from pydis_site.apps.api.models.bot.message_deletion_context import MessageDeletionContext


Expand All @@ -9,3 +11,9 @@ class LogView(DetailView):
model = MessageDeletionContext
context_object_name = "deletion_context"
template_name = "staff/logs.html"
queryset = MessageDeletionContext.objects.select_related("actor").prefetch_related(
Prefetch(
"deletedmessage_set",
queryset=DeletedMessage.objects.select_related("author"),
),
)