diff --git a/bookwyrm/models/base_model.py b/bookwyrm/models/base_model.py index b781a506..07f6b0d5 100644 --- a/bookwyrm/models/base_model.py +++ b/bookwyrm/models/base_model.py @@ -67,16 +67,15 @@ class BookWyrmModel(models.Model): return # you can see the followers only posts of people you follow - if ( - self.privacy == "followers" - and self.user.followers.filter(id=viewer.id).first() + if self.privacy == "followers" and ( + self.user.followers.filter(id=viewer.id).first() ): return # you can see dms you are tagged in if hasattr(self, "mention_users"): if ( - self.privacy == "direct" + self.privacy in ["direct", "followers"] and self.mention_users.filter(id=viewer.id).first() ): return diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py index a5657a4b..2b395ec8 100644 --- a/bookwyrm/models/status.py +++ b/bookwyrm/models/status.py @@ -224,6 +224,16 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel): ~Q(Q(user=viewer) | Q(mention_users=viewer)), privacy="direct" ) + @classmethod + def followers_filter(cls, queryset, viewer): + """Override-able filter for "followers" privacy level""" + return queryset.exclude( + ~Q( # not yourself, a follower, or someone who is tagged + Q(user__followers=viewer) | Q(user=viewer) | Q(mention_users=viewer) + ), + privacy="followers", # and the status is followers only + ) + class GeneratedNote(Status): """these are app-generated messages about user activity""" diff --git a/bookwyrm/tests/models/test_status_model.py b/bookwyrm/tests/models/test_status_model.py index 084e69fc..00f8a81c 100644 --- a/bookwyrm/tests/models/test_status_model.py +++ b/bookwyrm/tests/models/test_status_model.py @@ -3,11 +3,13 @@ from unittest.mock import patch from io import BytesIO import pathlib -from PIL import Image +from django.http import Http404 from django.core.files.base import ContentFile from django.db import IntegrityError +from django.contrib.auth.models import AnonymousUser from django.test import TestCase from django.utils import timezone +from PIL import Image import responses from bookwyrm import activitypub, models, settings @@ -50,6 +52,9 @@ class Status(TestCase): image.save(output, format=image.format) self.book.cover.save("test.jpg", ContentFile(output.getvalue())) + self.anonymous_user = AnonymousUser + self.anonymous_user.is_authenticated = False + def test_status_generated_fields(self, *_): """setting remote id""" status = models.Status.objects.create(content="bleh", user=self.local_user) @@ -460,3 +465,60 @@ class Status(TestCase): responses.add(responses.GET, "http://fish.com/nothing", status=404) self.assertTrue(models.Status.ignore_activity(activity)) + + def test_raise_visible_to_user_public(self, *_): + """privacy settings""" + status = models.Status.objects.create( + content="bleh", user=self.local_user, privacy="public" + ) + self.assertIsNone(status.raise_visible_to_user(self.remote_user)) + self.assertIsNone(status.raise_visible_to_user(self.local_user)) + self.assertIsNone(status.raise_visible_to_user(self.anonymous_user)) + + def test_raise_visible_to_user_unlisted(self, *_): + """privacy settings""" + status = models.Status.objects.create( + content="bleh", user=self.local_user, privacy="unlisted" + ) + self.assertIsNone(status.raise_visible_to_user(self.remote_user)) + self.assertIsNone(status.raise_visible_to_user(self.local_user)) + self.assertIsNone(status.raise_visible_to_user(self.anonymous_user)) + + @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") + def test_raise_visible_to_user_followers(self, *_): + """privacy settings""" + status = models.Status.objects.create( + content="bleh", user=self.local_user, privacy="followers" + ) + status.raise_visible_to_user(self.local_user) + with self.assertRaises(Http404): + status.raise_visible_to_user(self.remote_user) + with self.assertRaises(Http404): + status.raise_visible_to_user(self.anonymous_user) + + self.local_user.followers.add(self.remote_user) + self.assertIsNone(status.raise_visible_to_user(self.remote_user)) + + def test_raise_visible_to_user_followers_mentioned(self, *_): + """privacy settings""" + status = models.Status.objects.create( + content="bleh", user=self.local_user, privacy="followers" + ) + status.mention_users.set([self.remote_user]) + self.assertIsNone(status.raise_visible_to_user(self.remote_user)) + + @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay") + def test_raise_visible_to_user_direct(self, *_): + """privacy settings""" + status = models.Status.objects.create( + content="bleh", user=self.local_user, privacy="direct" + ) + status.raise_visible_to_user(self.local_user) + with self.assertRaises(Http404): + status.raise_visible_to_user(self.remote_user) + with self.assertRaises(Http404): + status.raise_visible_to_user(self.anonymous_user) + + # mentioned user + status.mention_users.set([self.remote_user]) + self.assertIsNone(status.raise_visible_to_user(self.remote_user))