forked from mirrors/bookwyrm
Moves privacy filter to model class
This commit is contained in:
parent
67c83b8d32
commit
b2671e78ef
2 changed files with 72 additions and 53 deletions
|
@ -2,8 +2,9 @@
|
||||||
import base64
|
import base64
|
||||||
from Crypto import Random
|
from Crypto import Random
|
||||||
|
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied, FieldError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import Q
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
@ -105,6 +106,76 @@ class BookWyrmModel(models.Model):
|
||||||
|
|
||||||
raise PermissionDenied()
|
raise PermissionDenied()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def privacy_filter(
|
||||||
|
cls, viewer, privacy_levels=None, following_only=False, **filters
|
||||||
|
):
|
||||||
|
"""filter objects that have "user" and "privacy" fields"""
|
||||||
|
queryset = cls.objects
|
||||||
|
if hasattr(queryset, "select_subclasses"):
|
||||||
|
queryset = queryset.select_subclasses()
|
||||||
|
|
||||||
|
privacy_levels = privacy_levels or ["public", "unlisted", "followers", "direct"]
|
||||||
|
# if there'd a deleted field, exclude deleted items
|
||||||
|
try:
|
||||||
|
queryset = queryset.filter(deleted=False)
|
||||||
|
except FieldError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# exclude blocks from both directions
|
||||||
|
if not viewer.is_anonymous:
|
||||||
|
queryset = queryset.exclude(
|
||||||
|
Q(user__blocked_by=viewer) | Q(user__blocks=viewer)
|
||||||
|
)
|
||||||
|
|
||||||
|
# you can't see followers only or direct messages if you're not logged in
|
||||||
|
if viewer.is_anonymous:
|
||||||
|
privacy_levels = [
|
||||||
|
p for p in privacy_levels if not p in ["followers", "direct"]
|
||||||
|
]
|
||||||
|
|
||||||
|
# filter to only privided privacy levels
|
||||||
|
queryset = queryset.filter(privacy__in=privacy_levels)
|
||||||
|
|
||||||
|
# only include statuses the user follows
|
||||||
|
if following_only:
|
||||||
|
queryset = queryset.exclude(
|
||||||
|
~Q( # remove everythign except
|
||||||
|
Q(user__followers=viewer)
|
||||||
|
| Q(user=viewer) # user following
|
||||||
|
| Q(mention_users=viewer) # is self # mentions user
|
||||||
|
),
|
||||||
|
)
|
||||||
|
# exclude followers-only statuses the user doesn't follow
|
||||||
|
elif "followers" in privacy_levels:
|
||||||
|
queryset = cls.followers_filter(queryset, viewer)
|
||||||
|
|
||||||
|
# exclude direct messages not intended for the user
|
||||||
|
if "direct" in privacy_levels:
|
||||||
|
queryset = cls.direct_filter(queryset, viewer)
|
||||||
|
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def followers_filter(cls, queryset, viewer):
|
||||||
|
"""Override-able filter for "followers" privacy level"""
|
||||||
|
return queryset.exclude(
|
||||||
|
~Q( # user isn't following and it isn't their own status
|
||||||
|
Q(user__followers=viewer) | Q(user=viewer)
|
||||||
|
),
|
||||||
|
privacy="followers", # and the status is followers only
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def direct_filter(cls, queryset, viewer):
|
||||||
|
"""Override-able filter for "direct" privacy level"""
|
||||||
|
try:
|
||||||
|
return queryset.exclude(
|
||||||
|
~Q(Q(user=viewer) | Q(mention_users=viewer)), privacy="direct"
|
||||||
|
)
|
||||||
|
except FieldError:
|
||||||
|
return queryset.exclude(~Q(user=viewer), privacy="direct")
|
||||||
|
|
||||||
|
|
||||||
@receiver(models.signals.post_save)
|
@receiver(models.signals.post_save)
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
|
|
|
@ -6,8 +6,6 @@ import dateutil.tz
|
||||||
from dateutil.parser import ParserError
|
from dateutil.parser import ParserError
|
||||||
|
|
||||||
from requests import HTTPError
|
from requests import HTTPError
|
||||||
from django.core.exceptions import FieldError
|
|
||||||
from django.db.models import Q
|
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
|
|
||||||
from bookwyrm import activitypub, models
|
from bookwyrm import activitypub, models
|
||||||
|
@ -50,56 +48,6 @@ def is_bookwyrm_request(request):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def privacy_filter(viewer, queryset, privacy_levels=None, following_only=False):
|
|
||||||
"""filter objects that have "user" and "privacy" fields"""
|
|
||||||
privacy_levels = privacy_levels or ["public", "unlisted", "followers", "direct"]
|
|
||||||
# if there'd a deleted field, exclude deleted items
|
|
||||||
try:
|
|
||||||
queryset = queryset.filter(deleted=False)
|
|
||||||
except FieldError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# exclude blocks from both directions
|
|
||||||
if not viewer.is_anonymous:
|
|
||||||
queryset = queryset.exclude(Q(user__blocked_by=viewer) | Q(user__blocks=viewer))
|
|
||||||
|
|
||||||
# you can't see followers only or direct messages if you're not logged in
|
|
||||||
if viewer.is_anonymous:
|
|
||||||
privacy_levels = [p for p in privacy_levels if not p in ["followers", "direct"]]
|
|
||||||
|
|
||||||
# filter to only privided privacy levels
|
|
||||||
queryset = queryset.filter(privacy__in=privacy_levels)
|
|
||||||
|
|
||||||
# only include statuses the user follows
|
|
||||||
if following_only:
|
|
||||||
queryset = queryset.exclude(
|
|
||||||
~Q( # remove everythign except
|
|
||||||
Q(user__followers=viewer)
|
|
||||||
| Q(user=viewer) # user following
|
|
||||||
| Q(mention_users=viewer) # is self # mentions user
|
|
||||||
),
|
|
||||||
)
|
|
||||||
# exclude followers-only statuses the user doesn't follow
|
|
||||||
elif "followers" in privacy_levels:
|
|
||||||
queryset = queryset.exclude(
|
|
||||||
~Q( # user isn't following and it isn't their own status
|
|
||||||
Q(user__followers=viewer) | Q(user=viewer)
|
|
||||||
),
|
|
||||||
privacy="followers", # and the status is followers only
|
|
||||||
)
|
|
||||||
|
|
||||||
# exclude direct messages not intended for the user
|
|
||||||
if "direct" in privacy_levels:
|
|
||||||
try:
|
|
||||||
queryset = queryset.exclude(
|
|
||||||
~Q(Q(user=viewer) | Q(mention_users=viewer)), privacy="direct"
|
|
||||||
)
|
|
||||||
except FieldError:
|
|
||||||
queryset = queryset.exclude(~Q(user=viewer), privacy="direct")
|
|
||||||
|
|
||||||
return queryset
|
|
||||||
|
|
||||||
|
|
||||||
def handle_remote_webfinger(query):
|
def handle_remote_webfinger(query):
|
||||||
"""webfingerin' other servers"""
|
"""webfingerin' other servers"""
|
||||||
user = None
|
user = None
|
||||||
|
|
Loading…
Reference in a new issue