add PictureQuerySet.viewable_by(user) method

This commit is contained in:
thomas girod 2024-08-06 12:37:50 +02:00
parent da6bd84cdf
commit 4506440a62
4 changed files with 25 additions and 12 deletions

View File

@ -41,14 +41,12 @@ class PicturesController(ControllerBase):
cf. https://ae.utbm.fr/user/32663/pictures/) cf. https://ae.utbm.fr/user/32663/pictures/)
""" """
user: User = self.context.request.user user: User = self.context.request.user
if not user.is_subscribed and filters.users_identified != {user.id}: if not user.was_subscribed and filters.users_identified != {user.id}:
# User can view any moderated picture if he/she is subscribed. # User can view any moderated picture if he/she is subscribed.
# If not, he/she can view only the one he/she has been identified on # If not, he/she can view only the one he/she has been identified on
raise PermissionDenied raise PermissionDenied
return ( return (
filters.filter( filters.filter(Picture.objects.viewable_by(user))
Picture.objects.filter(is_moderated=True, asked_for_removal=False)
)
.distinct() .distinct()
.order_by("-parent__date", "date") .order_by("-parent__date", "date")
.annotate(album=F("parent__name")) .annotate(album=F("parent__name"))

View File

@ -14,6 +14,7 @@
# #
from io import BytesIO from io import BytesIO
from typing import Self
from django.conf import settings from django.conf import settings
from django.core.cache import cache from django.core.cache import cache
@ -27,9 +28,25 @@ from core.models import SithFile, User
from core.utils import exif_auto_rotate, resize_image from core.utils import exif_auto_rotate, resize_image
class PictureQuerySet(models.QuerySet):
def viewable_by(self, user: User) -> Self:
"""Filter the pictures that this user can view.
Warnings:
Calling this queryset method may add several additional requests.
"""
if user.is_root or user.is_in_group(pk=settings.SITH_GROUP_SAS_ADMIN_ID):
return self.all()
if user.was_subscribed:
return self.filter(is_moderated=True)
return self.filter(people__user_id=user.id)
class SASPictureManager(models.Manager): class SASPictureManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super().get_queryset().filter(is_in_sas=True, is_folder=False) return PictureQuerySet(self.model, using=self._db).filter(
is_in_sas=True, is_folder=False
)
class SASAlbumManager(models.Manager): class SASAlbumManager(models.Manager):
@ -41,7 +58,7 @@ class Picture(SithFile):
class Meta: class Meta:
proxy = True proxy = True
objects = SASPictureManager() objects = SASPictureManager.from_queryset(PictureQuerySet)()
@property @property
def is_vertical(self): def is_vertical(self):
@ -58,7 +75,7 @@ class Picture(SithFile):
cache.set("%d_can_edit_pictures" % (user.id), perm, timeout=4) cache.set("%d_can_edit_pictures" % (user.id), perm, timeout=4)
return perm return perm
def can_be_viewed_by(self, user): def can_be_viewed_by(self, user: User) -> bool:
# SAS pictures are visible to old subscribers # SAS pictures are visible to old subscribers
# Result is cached 4s for this user # Result is cached 4s for this user
if user.is_anonymous: if user.is_anonymous:

View File

@ -75,7 +75,8 @@ class TestPictureSearch(TestSas):
assert [i["id"] for i in res.json()["results"]] == expected assert [i["id"] for i in res.json()["results"]] == expected
def test_not_subscribed_user(self): def test_not_subscribed_user(self):
"""Test that a user that is not subscribed can only its own pictures.""" """Test that a user that never subscribed can only its own pictures."""
self.user_a.subscriptions.all().delete()
self.client.force_login(self.user_a) self.client.force_login(self.user_a)
res = self.client.get( res = self.client.get(
reverse("api:pictures") + f"?users_identified={self.user_a.id}" reverse("api:pictures") + f"?users_identified={self.user_a.id}"

View File

@ -18,7 +18,6 @@ from ajax_select.fields import AutoCompleteSelectMultipleField
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.core.paginator import InvalidPage, Paginator
from django.http import Http404, HttpResponse from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
@ -318,9 +317,7 @@ class ModerationView(TemplateView):
kwargs["albums_to_moderate"] = Album.objects.filter( kwargs["albums_to_moderate"] = Album.objects.filter(
is_moderated=False, is_in_sas=True, is_folder=True is_moderated=False, is_in_sas=True, is_folder=True
).order_by("id") ).order_by("id")
kwargs["pictures"] = Picture.objects.filter( kwargs["pictures"] = Picture.objects.filter(is_moderated=False)
is_moderated=False, is_in_sas=True, is_folder=False
)
kwargs["albums"] = Album.objects.filter( kwargs["albums"] = Album.objects.filter(
id__in=kwargs["pictures"].values("parent").distinct("parent") id__in=kwargs["pictures"].values("parent").distinct("parent")
) )