drop non-public Create activities

fixes #289
pull/290/head
Ryan Barrett 2022-08-23 17:37:50 -07:00
rodzic 2bb76a90e7
commit 8fd49dc882
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
6 zmienionych plików z 46 dodań i 23 usunięć

Wyświetl plik

@ -181,6 +181,13 @@ def inbox(domain):
source_as2=source_as2)
if not sent and type in ('Create', 'Announce'):
# check that this activity is public. only do this check for Creates,
# not Like, Follow, or other activity types, since Mastodon doesn't
# currently mark those as explicitly public.
if not as2.is_public(activity_unwrapped):
logging.info('Dropping non-public activity')
return ''
# normal post, deliver to BF followers
source = activity.get('url') or activity.get('id')
domains = []

Wyświetl plik

@ -24,7 +24,6 @@ TLD_BLOCKLIST = ('7z', 'asp', 'aspx', 'gif', 'html', 'ico', 'jpg', 'jpeg', 'js',
'json', 'php', 'png', 'rar', 'txt', 'yaml', 'yml', 'zip')
XML_UTF8 = "<?xml version='1.0' encoding='UTF-8'?>\n"
LINK_HEADER_RE = re.compile(r""" *< *([^ >]+) *> *; *rel=['"]([^'"]+)['"] *""")
AS2_PUBLIC_AUDIENCE = 'https://www.w3.org/ns/activitystreams#Public'
# Content-Type values. All non-unicode strings because App Engine's wsgi.py
# requires header values to be str, not unicode.
@ -352,8 +351,8 @@ def postprocess_as2(activity, user=None, target=None):
# https://socialhub.activitypub.rocks/t/visibility-to-cc-mapping/284
# https://wordsmith.social/falkreon/securing-activitypub
to = activity.setdefault('to', [])
if AS2_PUBLIC_AUDIENCE not in to:
to.append(AS2_PUBLIC_AUDIENCE)
if as2.PUBLIC_AUDIENCE not in to:
to.append(as2.PUBLIC_AUDIENCE)
# wrap articles and notes in a Create activity
if type in ('Article', 'Note'):

Wyświetl plik

@ -6,6 +6,7 @@ TODO: test error handling
import copy
from unittest.mock import ANY, call, patch
from granary import as2
from oauth_dropins.webutil import util
from oauth_dropins.webutil.testutil import requests_response
from oauth_dropins.webutil.util import json_dumps, json_loads
@ -24,7 +25,7 @@ REPLY_OBJECT = {
'id': 'http://this/reply/id',
'url': 'http://this/reply',
'inReplyTo': 'http://orig/post',
'to': [common.AS2_PUBLIC_AUDIENCE],
'to': [as2.PUBLIC_AUDIENCE],
}
REPLY_OBJECT_WRAPPED = copy.deepcopy(REPLY_OBJECT)
REPLY_OBJECT_WRAPPED['inReplyTo'] = 'http://localhost/r/orig/post'
@ -40,7 +41,7 @@ NOTE_OBJECT = {
'content': '☕ just a normal post',
'id': 'http://this/note/id',
'url': 'http://this/note',
'to': [common.AS2_PUBLIC_AUDIENCE],
'to': [as2.PUBLIC_AUDIENCE],
'cc': [
'https://this/author/followers',
'https://masto.foo/@other',
@ -298,6 +299,21 @@ class ActivityPubTest(testutil.TestCase):
json_loads(activity.source_as2))
self.assert_equals(['foo.com', 'baz.com'], activity.domain)
def test_inbox_not_public(self, mock_head, mock_get, mock_post):
Follower.get_or_create(ACTOR['id'], 'foo.com')
mock_head.return_value = requests_response(url='http://target')
mock_get.return_value = requests_response( # source actor
ACTOR, headers={'Content-Type': common.CONTENT_TYPE_AS2})
not_public = copy.deepcopy(NOTE)
del not_public['object']['to']
with self.client:
got = self.client.post('/foo.com/inbox', json=not_public)
self.assertEqual(200, got.status_code, got.get_data(as_text=True))
self.assertEqual(0, Activity.query().count())
def test_inbox_mention_object(self, *mocks):
self._test_inbox_mention(MENTION_OBJECT, *mocks)

Wyświetl plik

@ -2,6 +2,7 @@
"""Unit tests for common.py."""
from unittest import mock
from granary import as2
from oauth_dropins.webutil import util
from oauth_dropins.webutil.testutil import requests_response
import requests
@ -71,7 +72,7 @@ class CommonTest(testutil.TestCase):
self.assert_equals({
'id': 'http://localhost/r/xyz',
'inReplyTo': 'foo',
'to': [common.AS2_PUBLIC_AUDIENCE],
'to': [as2.PUBLIC_AUDIENCE],
}, common.postprocess_as2({
'id': 'xyz',
'inReplyTo': ['foo', 'bar'],
@ -94,7 +95,7 @@ class CommonTest(testutil.TestCase):
'preferredUsername': 'foo.com',
'url': 'http://localhost/r/https://foo.com/',
}],
'to': [common.AS2_PUBLIC_AUDIENCE],
'to': [as2.PUBLIC_AUDIENCE],
}, common.postprocess_as2({
'attributedTo': [{'id': 'bar'}, {'id': 'baz'}],
'actor': {'id': 'baj'},
@ -114,7 +115,7 @@ class CommonTest(testutil.TestCase):
'object': {
'id': 'http://localhost/r/xyz',
'type': 'Note',
'to': [common.AS2_PUBLIC_AUDIENCE],
'to': [as2.PUBLIC_AUDIENCE],
},
}, common.postprocess_as2({
'id': 'xyz',

Wyświetl plik

@ -3,6 +3,7 @@
import copy
from unittest.mock import patch
from granary import as2
from oauth_dropins.webutil.testutil import requests_response
import common
@ -55,10 +56,10 @@ class RedirectTest(testutil.TestCase):
https://github.com/snarfed/bridgy-fed/issues/39
"""
as2 = copy.deepcopy(REPOST_AS2)
del as2['cc']
as2.update({
'to': [common.AS2_PUBLIC_AUDIENCE],
repost = copy.deepcopy(REPOST_AS2)
del repost['cc']
repost.update({
'to': [as2.PUBLIC_AUDIENCE],
'object': 'http://orig/post',
})
@ -71,4 +72,4 @@ class RedirectTest(testutil.TestCase):
self.assertEqual(('https://foo.com/bar',), args)
self.assertEqual(200, got.status_code)
self.assertEqual(as2, got.json)
self.assertEqual(repost, got.json)

Wyświetl plik

@ -9,7 +9,7 @@ from urllib.parse import urlencode
from django_salmon import magicsigs, utils
import feedparser
from granary import atom, microformats2
from granary import as2, atom, microformats2
from httpsig.sign import HeaderSigner
from oauth_dropins.webutil import util
from oauth_dropins.webutil.testutil import requests_response
@ -18,7 +18,6 @@ import requests
import activitypub
from common import (
AS2_PUBLIC_AUDIENCE,
CONNEG_HEADERS_AS2,
CONNEG_HEADERS_AS2_HTML,
CONTENT_TYPE_AS2,
@ -47,11 +46,11 @@ REPOST_AS2 = {
'url': 'http://localhost/r/http://a/repost',
'name': 'reposted!',
'object': 'tag:orig,2017:as2',
'to': [AS2_PUBLIC_AUDIENCE],
'to': [as2.PUBLIC_AUDIENCE],
'cc': [
'http://orig/author',
'http://orig/recipient',
AS2_PUBLIC_AUDIENCE,
as2.PUBLIC_AUDIENCE,
'http://orig/bystander',
],
'actor': {
@ -100,8 +99,8 @@ class WebmentionTest(testutil.TestCase):
'id': 'tag:orig,2017:as2',
'content': 'Lots of ☕ words...',
'actor': {'url': 'http://orig/author'},
'to': ['http://orig/recipient', AS2_PUBLIC_AUDIENCE],
'cc': ['http://orig/bystander', AS2_PUBLIC_AUDIENCE],
'to': ['http://orig/recipient', as2.PUBLIC_AUDIENCE],
'cc': ['http://orig/bystander', as2.PUBLIC_AUDIENCE],
}
self.orig_as2 = requests_response(
self.orig_as2_data, url='http://orig/as2',
@ -174,11 +173,11 @@ class WebmentionTest(testutil.TestCase):
<a class="u-in-reply-to" href="http://orig/post">foo bar</a>
<a href="http://localhost/"></a>""",
'inReplyTo': 'tag:orig,2017:as2',
'to': [AS2_PUBLIC_AUDIENCE],
'to': [as2.PUBLIC_AUDIENCE],
'cc': [
'http://orig/author',
'http://orig/recipient',
AS2_PUBLIC_AUDIENCE,
as2.PUBLIC_AUDIENCE,
'http://orig/bystander',
],
'attributedTo': [{
@ -223,7 +222,7 @@ class WebmentionTest(testutil.TestCase):
'type': 'Person',
'url': 'http://localhost/r/https://orig',
},
'to': [AS2_PUBLIC_AUDIENCE],
'to': [as2.PUBLIC_AUDIENCE],
}
self.create_html = """\
@ -264,7 +263,7 @@ class WebmentionTest(testutil.TestCase):
'name': 'Ms. ☕ Baz',
'preferredUsername': 'orig',
}],
'to': [AS2_PUBLIC_AUDIENCE],
'to': [as2.PUBLIC_AUDIENCE],
},
}
self.update_as2 = copy.deepcopy(self.create_as2)