From 3e888c17dd1ac01f14f1e711bc98644c09f7d041 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Tue, 23 Mar 2021 14:59:51 -0700 Subject: [PATCH] Fixes audience filters with tests --- bookwyrm/activitystreams.py | 11 +- bookwyrm/tests/test_activitystreams.py | 216 +++++++++++++++++++++++++ 2 files changed, 224 insertions(+), 3 deletions(-) create mode 100644 bookwyrm/tests/test_activitystreams.py diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 1c8f78be0..88f1f0114 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -98,8 +98,14 @@ class ActivityStream(ABC): Q(id__in=status.user.blocks.all()) | Q(blocks=status.user) # not blocked ) + # only visible to the poster and mentioned users + if status.privacy == "direct": + audience = audience.filter( + Q(id=status.user.id) # if the user is the post's author + | Q(id__in=status.mention_users.all()) # if the user is mentioned + ) # only visible to the poster's followers and tagged users - if status.privacy == "followers": + elif status.privacy == "followers": audience = audience.filter( Q(id=status.user.id) # if the user is the post's author | Q(following=status.user) # if the user is following the author @@ -125,7 +131,6 @@ class HomeStream(ActivityStream): return audience.filter( Q(id=status.user.id) # if the user is the post's author | Q(following=status.user) # if the user is following the author - | Q(id__in=status.mention_users.all()) # or the user is mentioned ) def stream_statuses(self, user): @@ -144,7 +149,7 @@ class LocalStream(ActivityStream): def stream_users(self, status): # this stream wants no part in non-public statuses - if status.privacy != "public": + if status.privacy != "public" or not status.user.local: return None return super().stream_users(status) diff --git a/bookwyrm/tests/test_activitystreams.py b/bookwyrm/tests/test_activitystreams.py new file mode 100644 index 000000000..a8daea84a --- /dev/null +++ b/bookwyrm/tests/test_activitystreams.py @@ -0,0 +1,216 @@ +""" testing activitystreams """ +from unittest.mock import patch +from django.test import TestCase +from bookwyrm import activitystreams, models + + +class Activitystreams(TestCase): + """ using redis to build activity streams """ + + def setUp(self): + """ use a test csv """ + self.local_user = models.User.objects.create_user( + "mouse", "mouse@mouse.mouse", "password", local=True, localname="mouse" + ) + self.another_user = models.User.objects.create_user( + "nutria", "nutria@nutria.nutria", "password", local=True, localname="nutria" + ) + with patch("bookwyrm.models.user.set_remote_server.delay"): + self.remote_user = models.User.objects.create_user( + "rat", + "rat@rat.com", + "ratword", + local=False, + remote_id="https://example.com/users/rat", + inbox="https://example.com/users/rat/inbox", + outbox="https://example.com/users/rat/outbox", + ) + self.book = models.Edition.objects.create(title="test book") + + class TestStream(activitystreams.ActivityStream): + """ test stream, don't have to do anything here """ + + key = "test" + + self.test_stream = TestStream() + + def test_activitystream_class_ids(self): + """ the abstract base class for stream objects """ + self.assertEqual( + self.test_stream.stream_id(self.local_user), + "{}-test".format(self.local_user.id), + ) + self.assertEqual( + self.test_stream.unread_id(self.local_user), + "{}-test-unread".format(self.local_user.id), + ) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_abstractstream_stream_users(self, _): + """ get a list of users that should see a status """ + status = models.Status.objects.create( + user=self.remote_user, content="hi", privacy="public" + ) + users = self.test_stream.stream_users(status) + # remote users don't have feeds + self.assertFalse(self.remote_user in users) + self.assertTrue(self.local_user in users) + self.assertTrue(self.another_user in users) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_abstractstream_stream_users_direct(self, _): + """ get a list of users that should see a status """ + status = models.Status.objects.create( + user=self.remote_user, + content="hi", + privacy="direct", + ) + status.mention_users.add(self.local_user) + users = self.test_stream.stream_users(status) + self.assertIsNone(users) + + status = models.Comment.objects.create( + user=self.remote_user, + content="hi", + privacy="direct", + book=self.book, + ) + status.mention_users.add(self.local_user) + users = self.test_stream.stream_users(status) + self.assertTrue(self.local_user in users) + self.assertFalse(self.another_user in users) + self.assertFalse(self.remote_user in users) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_abstractstream_stream_users_followers_remote_user(self, _): + """ get a list of users that should see a status """ + status = models.Status.objects.create( + user=self.remote_user, + content="hi", + privacy="followers", + ) + users = self.test_stream.stream_users(status) + self.assertFalse(users.exists()) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_abstractstream_stream_users_followers_self(self, _): + """ get a list of users that should see a status """ + status = models.Comment.objects.create( + user=self.local_user, + content="hi", + privacy="direct", + book=self.book, + ) + users = self.test_stream.stream_users(status) + self.assertTrue(self.local_user in users) + self.assertFalse(self.another_user in users) + self.assertFalse(self.remote_user in users) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_abstractstream_stream_users_followers_with_mention(self, _): + """ get a list of users that should see a status """ + status = models.Comment.objects.create( + user=self.remote_user, + content="hi", + privacy="direct", + book=self.book, + ) + status.mention_users.add(self.local_user) + + users = self.test_stream.stream_users(status) + self.assertTrue(self.local_user in users) + self.assertFalse(self.another_user in users) + self.assertFalse(self.remote_user in users) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_abstractstream_stream_users_followers_with_relationship(self, _): + """ get a list of users that should see a status """ + self.remote_user.followers.add(self.local_user) + status = models.Comment.objects.create( + user=self.remote_user, + content="hi", + privacy="direct", + book=self.book, + ) + users = self.test_stream.stream_users(status) + self.assertFalse(self.local_user in users) + self.assertFalse(self.another_user in users) + self.assertFalse(self.remote_user in users) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_homestream_stream_users(self, _): + """ get a list of users that should see a status """ + status = models.Status.objects.create( + user=self.remote_user, content="hi", privacy="public" + ) + users = activitystreams.HomeStream().stream_users(status) + self.assertFalse(users.exists()) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_homestream_stream_users_with_mentions(self, _): + """ get a list of users that should see a status """ + status = models.Status.objects.create( + user=self.remote_user, content="hi", privacy="public" + ) + status.mention_users.add(self.local_user) + users = activitystreams.HomeStream().stream_users(status) + self.assertFalse(self.local_user in users) + self.assertFalse(self.another_user in users) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_homestream_stream_users_with_relationship(self, _): + """ get a list of users that should see a status """ + self.remote_user.followers.add(self.local_user) + status = models.Status.objects.create( + user=self.remote_user, content="hi", privacy="public" + ) + users = activitystreams.HomeStream().stream_users(status) + self.assertTrue(self.local_user in users) + self.assertFalse(self.another_user in users) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_localstream_stream_users_remote_status(self, _): + """ get a list of users that should see a status """ + status = models.Status.objects.create( + user=self.remote_user, content="hi", privacy="public" + ) + users = activitystreams.LocalStream().stream_users(status) + self.assertIsNone(users) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_localstream_stream_users_local_status(self, _): + """ get a list of users that should see a status """ + status = models.Status.objects.create( + user=self.local_user, content="hi", privacy="public" + ) + users = activitystreams.LocalStream().stream_users(status) + self.assertTrue(self.local_user in users) + self.assertTrue(self.another_user in users) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_localstream_stream_users_unlisted(self, _): + """ get a list of users that should see a status """ + status = models.Status.objects.create( + user=self.local_user, content="hi", privacy="unlisted" + ) + users = activitystreams.LocalStream().stream_users(status) + self.assertIsNone(users) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_federatedstream_stream_users(self, _): + """ get a list of users that should see a status """ + status = models.Status.objects.create( + user=self.remote_user, content="hi", privacy="public" + ) + users = activitystreams.FederatedStream().stream_users(status) + self.assertTrue(self.local_user in users) + self.assertTrue(self.another_user in users) + + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_federatedstream_stream_users_unlisted(self, _): + """ get a list of users that should see a status """ + status = models.Status.objects.create( + user=self.remote_user, content="hi", privacy="unlisted" + ) + users = activitystreams.FederatedStream().stream_users(status) + self.assertIsNone(users)