kopia lustrzana https://github.com/snarfed/bridgy-fed
rodzic
7f2e0178d7
commit
f933c7e237
|
@ -298,13 +298,13 @@ def postprocess_as2(activity, target=None, wrap=True):
|
||||||
if not activity or isinstance(activity, str):
|
if not activity or isinstance(activity, str):
|
||||||
return activity
|
return activity
|
||||||
|
|
||||||
assert g.user
|
assert bool(g.user) ^ bool(g.external_user) # should have one but not both
|
||||||
type = activity.get('type')
|
type = activity.get('type')
|
||||||
|
|
||||||
# actor objects
|
# actor objects
|
||||||
if type == 'Person':
|
if type == 'Person':
|
||||||
postprocess_as2_actor(activity)
|
postprocess_as2_actor(activity)
|
||||||
if not activity.get('publicKey'):
|
if g.user and not activity.get('publicKey'):
|
||||||
# underspecified, inferred from this issue and Mastodon's implementation:
|
# underspecified, inferred from this issue and Mastodon's implementation:
|
||||||
# https://github.com/w3c/activitypub/issues/203#issuecomment-297553229
|
# https://github.com/w3c/activitypub/issues/203#issuecomment-297553229
|
||||||
# https://github.com/tootsuite/mastodon/blob/bc2c263504e584e154384ecc2d804aeb1afb1ba3/app/services/activitypub/process_account_service.rb#L77
|
# https://github.com/tootsuite/mastodon/blob/bc2c263504e584e154384ecc2d804aeb1afb1ba3/app/services/activitypub/process_account_service.rb#L77
|
||||||
|
@ -364,12 +364,16 @@ def postprocess_as2(activity, target=None, wrap=True):
|
||||||
activity['object'] = target_id
|
activity['object'] = target_id
|
||||||
elif not id:
|
elif not id:
|
||||||
obj['id'] = util.get_first(obj, 'url') or target_id
|
obj['id'] = util.get_first(obj, 'url') or target_id
|
||||||
elif g.user.is_homepage(id):
|
elif g.user and g.user.is_homepage(id):
|
||||||
obj['id'] = g.user.actor_id()
|
obj['id'] = g.user.actor_id()
|
||||||
|
elif g.external_user:
|
||||||
|
obj['id'] = redirect_wrap(g.external_user)
|
||||||
|
|
||||||
# for Accepts
|
# for Accepts
|
||||||
if g.user.is_homepage(obj.get('object')):
|
if g.user and g.user.is_homepage(obj.get('object')):
|
||||||
obj['object'] = g.user.actor_id()
|
obj['object'] = g.user.actor_id()
|
||||||
|
elif g.external_user and g.external_user == obj.get('object'):
|
||||||
|
obj['object'] = redirect_wrap(g.external_user)
|
||||||
|
|
||||||
# id is required for most things. default to url if it's not set.
|
# id is required for most things. default to url if it's not set.
|
||||||
if not activity.get('id'):
|
if not activity.get('id'):
|
||||||
|
@ -453,8 +457,12 @@ def postprocess_as2_actor(actor, wrap=True):
|
||||||
Returns:
|
Returns:
|
||||||
actor dict
|
actor dict
|
||||||
"""
|
"""
|
||||||
if not actor or isinstance(actor, str):
|
if not actor:
|
||||||
return g.user.actor_id() if g.user.is_homepage(actor) else actor
|
return actor
|
||||||
|
elif isinstance(actor, str):
|
||||||
|
if g.user and g.user.is_homepage(actor):
|
||||||
|
return g.user.actor_id()
|
||||||
|
return redirect_wrap(actor)
|
||||||
|
|
||||||
url = g.user.homepage if g.user else None
|
url = g.user.homepage if g.user else None
|
||||||
urls = util.get_list(actor, 'url')
|
urls = util.get_list(actor, 'url')
|
||||||
|
@ -465,7 +473,12 @@ def postprocess_as2_actor(actor, wrap=True):
|
||||||
if wrap:
|
if wrap:
|
||||||
urls[0] = redirect_wrap(urls[0])
|
urls[0] = redirect_wrap(urls[0])
|
||||||
|
|
||||||
actor.setdefault('id', host_url(domain))
|
id = actor.get('id')
|
||||||
|
if g.user and (not id or g.user.is_homepage(id)):
|
||||||
|
actor['id'] = g.user.actor_id()
|
||||||
|
elif g.external_user and (not id or id == g.external_user):
|
||||||
|
actor['id'] = redirect_wrap(g.external_user)
|
||||||
|
|
||||||
actor.update({
|
actor.update({
|
||||||
'url': urls if len(urls) > 1 else urls[0],
|
'url': urls if len(urls) > 1 else urls[0],
|
||||||
# This has to be the domain for Mastodon interop/Webfinger discovery!
|
# This has to be the domain for Mastodon interop/Webfinger discovery!
|
||||||
|
|
|
@ -36,7 +36,12 @@ if appengine_info.LOCAL:
|
||||||
|
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def init_globals():
|
def init_globals():
|
||||||
g.user = None
|
"""Set request globals.
|
||||||
|
|
||||||
|
* g.user: Current internal user we're operating on behalf of.
|
||||||
|
* g.external_user: Current external user we're operating on behalf of.
|
||||||
|
"""
|
||||||
|
g.user = g.external_user = None
|
||||||
|
|
||||||
# don't redirect API requests with blank path elements
|
# don't redirect API requests with blank path elements
|
||||||
app.url_map.redirect_defaults = True
|
app.url_map.redirect_defaults = True
|
||||||
|
|
|
@ -82,8 +82,8 @@ def redir(to):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if accept_as2:
|
if accept_as2:
|
||||||
# TODO: this is a kind of gross hack, should we do it differently?
|
g.external_user = urllib.parse.urljoin(to, '/')
|
||||||
g.user = User(id=to_domain)
|
logging.info(f'No User for {g.external_user}')
|
||||||
else:
|
else:
|
||||||
return f'No user found for any of {domains}', 404
|
return f'No user found for any of {domains}', 404
|
||||||
|
|
||||||
|
|
|
@ -226,7 +226,7 @@ class ActivityPubTest(testutil.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.user = self.make_user('user.com', has_hcard=True, actor_as2=ACTOR)
|
self.user = self.make_user('user.com', has_hcard=True, actor_as2=ACTOR)
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
self.key_id_obj = Object(id='http://my/key/id', as2={
|
self.key_id_obj = Object(id='http://my/key/id', as2={
|
||||||
**ACTOR,
|
**ACTOR,
|
||||||
'publicKey': {
|
'publicKey': {
|
||||||
|
@ -427,7 +427,7 @@ class ActivityPubTest(testutil.TestCase):
|
||||||
'id': 'https://user.com/orig',
|
'id': 'https://user.com/orig',
|
||||||
}
|
}
|
||||||
del note['url']
|
del note['url']
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id=orig_url, mf2=microformats2.object_to_json(as2.to_as1(note))).put()
|
Object(id=orig_url, mf2=microformats2.object_to_json(as2.to_as1(note))).put()
|
||||||
|
|
||||||
repost = copy.deepcopy(REPOST_FULL)
|
repost = copy.deepcopy(REPOST_FULL)
|
||||||
|
@ -1165,12 +1165,11 @@ class ActivityPubTest(testutil.TestCase):
|
||||||
class ActivityPubUtilsTest(testutil.TestCase):
|
class ActivityPubUtilsTest(testutil.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.app_context = app.test_request_context('/')
|
self.request_context.push()
|
||||||
self.app_context.__enter__()
|
|
||||||
g.user = self.make_user('user.com', has_hcard=True, actor_as2=ACTOR)
|
g.user = self.make_user('user.com', has_hcard=True, actor_as2=ACTOR)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.app_context.__exit__(None, None, None)
|
self.request_context.pop()
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
|
||||||
def test_postprocess_as2_multiple_in_reply_tos(self):
|
def test_postprocess_as2_multiple_in_reply_tos(self):
|
||||||
|
|
|
@ -23,12 +23,11 @@ class CommonTest(testutil.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.app_context = app.test_request_context('/')
|
self.request_context.push()
|
||||||
self.app_context.push()
|
|
||||||
g.user = User(id='site')
|
g.user = User(id='site')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.app_context.pop()
|
self.request_context.pop()
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
|
||||||
def test_pretty_link(self):
|
def test_pretty_link(self):
|
||||||
|
|
|
@ -22,8 +22,7 @@ class UserTest(testutil.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.app_context = app.test_request_context('/')
|
self.request_context.push()
|
||||||
self.app_context.push()
|
|
||||||
g.user = self.make_user('y.z')
|
g.user = self.make_user('y.z')
|
||||||
|
|
||||||
self.full_redir = requests_response(
|
self.full_redir = requests_response(
|
||||||
|
@ -31,7 +30,7 @@ class UserTest(testutil.TestCase):
|
||||||
redirected_url='http://localhost/.well-known/webfinger?resource=acct:y.z@y.z')
|
redirected_url='http://localhost/.well-known/webfinger?resource=acct:y.z@y.z')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.app_context.pop()
|
self.request_context.pop()
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
|
||||||
def test_get_or_create(self):
|
def test_get_or_create(self):
|
||||||
|
@ -271,12 +270,11 @@ http://this/404s
|
||||||
class ObjectTest(testutil.TestCase):
|
class ObjectTest(testutil.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.app_context = app.test_request_context('/')
|
self.request_context.push()
|
||||||
self.app_context.push()
|
|
||||||
g.user = None
|
g.user = None
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.app_context.pop()
|
self.request_context.pop()
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
|
||||||
def test_proxy_url(self):
|
def test_proxy_url(self):
|
||||||
|
|
|
@ -56,7 +56,7 @@ class PagesTest(testutil.TestCase):
|
||||||
self.assert_equals('/user/user.com', got.headers['Location'])
|
self.assert_equals('/user/user.com', got.headers['Location'])
|
||||||
|
|
||||||
def test_user_object_bare_string_id(self):
|
def test_user_object_bare_string_id(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='a', domains=['user.com'], labels=['notification'],
|
Object(id='a', domains=['user.com'], labels=['notification'],
|
||||||
as2=REPOST_AS2).put()
|
as2=REPOST_AS2).put()
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ class PagesTest(testutil.TestCase):
|
||||||
self.assert_equals(200, got.status_code)
|
self.assert_equals(200, got.status_code)
|
||||||
|
|
||||||
def test_user_object_url_object(self):
|
def test_user_object_url_object(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='a', domains=['user.com'], labels=['notification'], our_as1={
|
Object(id='a', domains=['user.com'], labels=['notification'], our_as1={
|
||||||
**REPOST_AS2,
|
**REPOST_AS2,
|
||||||
'object': {
|
'object': {
|
||||||
|
|
|
@ -28,12 +28,11 @@ class ProtocolTest(testutil.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.user = self.make_user('foo.com', has_hcard=True)
|
self.user = self.make_user('foo.com', has_hcard=True)
|
||||||
self.app_context = app.test_request_context('/')
|
self.request_context.push()
|
||||||
self.app_context.__enter__()
|
|
||||||
g.user = None
|
g.user = None
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.app_context.__exit__(None, None, None)
|
self.request_context.pop()
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
|
||||||
@patch('requests.get')
|
@patch('requests.get')
|
||||||
|
|
|
@ -7,24 +7,34 @@ from granary import as2
|
||||||
from oauth_dropins.webutil.testutil import requests_response
|
from oauth_dropins.webutil.testutil import requests_response
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from flask_app import app, cache, g
|
from flask_app import app, cache
|
||||||
from common import redirect_unwrap
|
from common import redirect_unwrap
|
||||||
from models import Object, User
|
from models import Object, User
|
||||||
from .test_webmention import ACTOR_AS2, REPOST_AS2, REPOST_HTML
|
from .test_webmention import (
|
||||||
|
ACTOR_AS2,
|
||||||
|
ACTOR_AS2_FULL,
|
||||||
|
ACTOR_HTML,
|
||||||
|
REPOST_AS2,
|
||||||
|
REPOST_HTML,
|
||||||
|
)
|
||||||
from . import testutil
|
from . import testutil
|
||||||
|
|
||||||
REPOST_AS2 = copy.deepcopy(REPOST_AS2)
|
REPOST_AS2 = copy.deepcopy(REPOST_AS2)
|
||||||
del REPOST_AS2['cc']
|
del REPOST_AS2['cc']
|
||||||
|
|
||||||
|
EXTERNAL_REPOST_AS2 = copy.deepcopy(REPOST_AS2)
|
||||||
|
EXTERNAL_REPOST_AS2['actor'] = {
|
||||||
|
**ACTOR_AS2,
|
||||||
|
'id': 'http://localhost/r/https://user.com/',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class RedirectTest(testutil.TestCase):
|
class RedirectTest(testutil.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.user = self.make_user('user.com')
|
self.user = self.make_user('user.com')
|
||||||
|
|
||||||
with app.test_request_context('/'):
|
|
||||||
g.user = None
|
|
||||||
|
|
||||||
def test_redirect(self):
|
def test_redirect(self):
|
||||||
got = self.client.get('/r/https://user.com/bar?baz=baj&biff')
|
got = self.client.get('/r/https://user.com/bar?baz=baj&biff')
|
||||||
self.assertEqual(301, got.status_code)
|
self.assertEqual(301, got.status_code)
|
||||||
|
@ -58,16 +68,46 @@ class RedirectTest(testutil.TestCase):
|
||||||
self._test_as2(as2.CONTENT_TYPE_LD)
|
self._test_as2(as2.CONTENT_TYPE_LD)
|
||||||
|
|
||||||
def test_as2_no_user(self):
|
def test_as2_no_user(self):
|
||||||
|
with self.request_context:
|
||||||
|
Object(id='https://user.com/post', as2=EXTERNAL_REPOST_AS2).put()
|
||||||
|
|
||||||
self.user.key.delete()
|
self.user.key.delete()
|
||||||
self._test_as2(as2.CONTENT_TYPE)
|
|
||||||
|
resp = self.client.get('/r/https://user.com/post',
|
||||||
|
headers={'Accept': as2.CONTENT_TYPE})
|
||||||
|
self.assertEqual(200, resp.status_code, resp.get_data(as_text=True))
|
||||||
|
self.assert_equals(EXTERNAL_REPOST_AS2, resp.json)
|
||||||
|
|
||||||
@patch('requests.get')
|
@patch('requests.get')
|
||||||
def test_as2_fetch_post(self, mock_get):
|
def test_as2_fetch_post(self, mock_get):
|
||||||
mock_get.return_value = requests_response(REPOST_HTML)
|
mock_get.return_value = requests_response(REPOST_HTML)
|
||||||
self._test_as2(as2.CONTENT_TYPE, stored_object=False, expected={
|
|
||||||
|
resp = self.client.get('/r/https://user.com/post',
|
||||||
|
headers={'Accept': as2.CONTENT_TYPE})
|
||||||
|
self.assertEqual(200, resp.status_code, resp.get_data(as_text=True))
|
||||||
|
self.assert_equals({
|
||||||
**REPOST_AS2,
|
**REPOST_AS2,
|
||||||
'actor': ACTOR_AS2,
|
'actor': ACTOR_AS2,
|
||||||
})
|
}, resp.json)
|
||||||
|
|
||||||
|
@patch('requests.get')
|
||||||
|
def test_as2_no_user_fetch_homepage(self, mock_get):
|
||||||
|
mock_get.return_value = requests_response(ACTOR_HTML)
|
||||||
|
self.user.key.delete()
|
||||||
|
|
||||||
|
resp = self.client.get('/r/https://user.com/',
|
||||||
|
headers={'Accept': as2.CONTENT_TYPE})
|
||||||
|
self.assertEqual(200, resp.status_code, resp.get_data(as_text=True))
|
||||||
|
self.assert_equals({
|
||||||
|
**ACTOR_AS2,
|
||||||
|
'id': 'http://localhost/r/https://user.com/',
|
||||||
|
'summary': '',
|
||||||
|
'attachment': [{
|
||||||
|
'name': 'Ms. ☕ Baz',
|
||||||
|
'type': 'PropertyValue',
|
||||||
|
'value': '<a rel="me" href="https://user.com/">user.com</a>',
|
||||||
|
}],
|
||||||
|
}, resp.json)
|
||||||
|
|
||||||
def test_accept_header_cache_key(self):
|
def test_accept_header_cache_key(self):
|
||||||
app.config['CACHE_TYPE'] = 'SimpleCache'
|
app.config['CACHE_TYPE'] = 'SimpleCache'
|
||||||
|
@ -90,20 +130,17 @@ class RedirectTest(testutil.TestCase):
|
||||||
self.assertEqual(301, resp.status_code)
|
self.assertEqual(301, resp.status_code)
|
||||||
self.assertEqual('https://user.com/bar', resp.headers['Location'])
|
self.assertEqual('https://user.com/bar', resp.headers['Location'])
|
||||||
|
|
||||||
def _test_as2(self, content_type, stored_object=True, expected=REPOST_AS2):
|
def _test_as2(self, content_type):
|
||||||
if stored_object:
|
with self.request_context:
|
||||||
with app.test_request_context('/'):
|
self.obj = Object(id='https://user.com/', as2=REPOST_AS2).put()
|
||||||
self.obj = Object(id='https://user.com/repost', as2=REPOST_AS2).put()
|
|
||||||
|
|
||||||
resp = self.client.get('/r/https://user.com/repost',
|
resp = self.client.get('/r/https://user.com/', headers={'Accept': content_type})
|
||||||
headers={'Accept': content_type})
|
|
||||||
self.assertEqual(200, resp.status_code, resp.get_data(as_text=True))
|
self.assertEqual(200, resp.status_code, resp.get_data(as_text=True))
|
||||||
self.assertEqual(content_type, resp.content_type)
|
self.assertEqual(content_type, resp.content_type)
|
||||||
|
self.assert_equals(REPOST_AS2, resp.json)
|
||||||
self.assert_equals(expected, resp.json)
|
|
||||||
|
|
||||||
def test_as2_deleted(self):
|
def test_as2_deleted(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='https://user.com/bar', as2={}, deleted=True).put()
|
Object(id='https://user.com/bar', as2={}, deleted=True).put()
|
||||||
|
|
||||||
resp = self.client.get('/r/https://user.com/bar',
|
resp = self.client.get('/r/https://user.com/bar',
|
||||||
|
|
|
@ -66,14 +66,14 @@ class RenderTest(testutil.TestCase):
|
||||||
self.assertEqual(404, resp.status_code)
|
self.assertEqual(404, resp.status_code)
|
||||||
|
|
||||||
def test_render(self):
|
def test_render(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='abc', as2=as2.from_as1(COMMENT)).put()
|
Object(id='abc', as2=as2.from_as1(COMMENT)).put()
|
||||||
resp = self.client.get('/render?id=abc')
|
resp = self.client.get('/render?id=abc')
|
||||||
self.assertEqual(200, resp.status_code)
|
self.assertEqual(200, resp.status_code)
|
||||||
self.assert_multiline_equals(EXPECTED_HTML, resp.get_data(as_text=True), ignore_blanks=True)
|
self.assert_multiline_equals(EXPECTED_HTML, resp.get_data(as_text=True), ignore_blanks=True)
|
||||||
|
|
||||||
def test_render_with_author(self):
|
def test_render_with_author(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='abc', as2=as2.from_as1({**COMMENT, 'author': 'def'})).put()
|
Object(id='abc', as2=as2.from_as1({**COMMENT, 'author': 'def'})).put()
|
||||||
Object(id='def', as2=as2.from_as1(ACTOR)).put()
|
Object(id='def', as2=as2.from_as1(ACTOR)).put()
|
||||||
resp = self.client.get('/render?id=abc')
|
resp = self.client.get('/render?id=abc')
|
||||||
|
@ -84,7 +84,7 @@ class RenderTest(testutil.TestCase):
|
||||||
def test_render_no_url(self):
|
def test_render_no_url(self):
|
||||||
comment = copy.deepcopy(COMMENT)
|
comment = copy.deepcopy(COMMENT)
|
||||||
del comment['url']
|
del comment['url']
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='abc', as2=as2.from_as1(comment)).put()
|
Object(id='abc', as2=as2.from_as1(comment)).put()
|
||||||
|
|
||||||
resp = self.client.get('/render?id=abc')
|
resp = self.client.get('/render?id=abc')
|
||||||
|
@ -96,21 +96,21 @@ class RenderTest(testutil.TestCase):
|
||||||
ignore_blanks=True)
|
ignore_blanks=True)
|
||||||
|
|
||||||
def test_render_deleted_object(self):
|
def test_render_deleted_object(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='abc', as2={'content': 'foo'}, deleted=True).put()
|
Object(id='abc', as2={'content': 'foo'}, deleted=True).put()
|
||||||
|
|
||||||
resp = self.client.get('/render?id=abc')
|
resp = self.client.get('/render?id=abc')
|
||||||
self.assertEqual(410, resp.status_code)
|
self.assertEqual(410, resp.status_code)
|
||||||
|
|
||||||
def test_render_delete_activity(self):
|
def test_render_delete_activity(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='abc', as2=as2.from_as1(DELETE_OF_ID)).put()
|
Object(id='abc', as2=as2.from_as1(DELETE_OF_ID)).put()
|
||||||
|
|
||||||
resp = self.client.get('/render?id=abc')
|
resp = self.client.get('/render?id=abc')
|
||||||
self.assertEqual(410, resp.status_code)
|
self.assertEqual(410, resp.status_code)
|
||||||
|
|
||||||
def test_render_update_inner_obj_exists_redirect(self):
|
def test_render_update_inner_obj_exists_redirect(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
# UPDATE's object field is a full object
|
# UPDATE's object field is a full object
|
||||||
Object(id='abc', as2=as2.from_as1(UPDATE)).put()
|
Object(id='abc', as2=as2.from_as1(UPDATE)).put()
|
||||||
Object(id=UPDATE['object']['id'], as2={'content': 'foo'}).put()
|
Object(id=UPDATE['object']['id'], as2={'content': 'foo'}).put()
|
||||||
|
@ -121,7 +121,7 @@ class RenderTest(testutil.TestCase):
|
||||||
resp.headers['Location'])
|
resp.headers['Location'])
|
||||||
|
|
||||||
def test_render_delete_inner_obj_exists_redirect(self):
|
def test_render_delete_inner_obj_exists_redirect(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
# DELETE_OF_ID's object field is a bare string id
|
# DELETE_OF_ID's object field is a bare string id
|
||||||
Object(id='abc', as2=as2.from_as1(DELETE_OF_ID)).put()
|
Object(id='abc', as2=as2.from_as1(DELETE_OF_ID)).put()
|
||||||
Object(id=DELETE_OF_ID['object'], as2={'content': 'foo'}).put()
|
Object(id=DELETE_OF_ID['object'], as2={'content': 'foo'}).put()
|
||||||
|
@ -132,7 +132,7 @@ class RenderTest(testutil.TestCase):
|
||||||
resp.headers['Location'])
|
resp.headers['Location'])
|
||||||
|
|
||||||
def test_render_update_no_inner_obj_serve_as_is(self):
|
def test_render_update_no_inner_obj_serve_as_is(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
# UPDATE's object field is a full object
|
# UPDATE's object field is a full object
|
||||||
Object(id='abc', as2=as2.from_as1(UPDATE)).put()
|
Object(id='abc', as2=as2.from_as1(UPDATE)).put()
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ A ☕ reply
|
||||||
""", resp.get_data(as_text=True), ignore_blanks=True)
|
""", resp.get_data(as_text=True), ignore_blanks=True)
|
||||||
|
|
||||||
def test_render_update_inner_obj_too_minimal_serve_as_is(self):
|
def test_render_update_inner_obj_too_minimal_serve_as_is(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
# UPDATE's object field is a full object
|
# UPDATE's object field is a full object
|
||||||
Object(id='abc', as2=as2.from_as1(UPDATE)).put()
|
Object(id='abc', as2=as2.from_as1(UPDATE)).put()
|
||||||
Object(id=UPDATE['object']['id'], as2={'id': 'foo'}).put()
|
Object(id=UPDATE['object']['id'], as2={'id': 'foo'}).put()
|
||||||
|
|
|
@ -585,7 +585,7 @@ class WebmentionTest(testutil.TestCase):
|
||||||
'content': ['other'],
|
'content': ['other'],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='https://user.com/reply', status='complete', mf2=mf2).put()
|
Object(id='https://user.com/reply', status='complete', mf2=mf2).put()
|
||||||
|
|
||||||
mock_get.side_effect = self.activitypub_gets
|
mock_get.side_effect = self.activitypub_gets
|
||||||
|
@ -604,7 +604,7 @@ class WebmentionTest(testutil.TestCase):
|
||||||
|
|
||||||
def test_redo_repost_isnt_update(self, mock_get, mock_post):
|
def test_redo_repost_isnt_update(self, mock_get, mock_post):
|
||||||
"""Like and Announce shouldn't use Update, they should just resend as is."""
|
"""Like and Announce shouldn't use Update, they should just resend as is."""
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='https://user.com/repost', mf2={}, status='complete').put()
|
Object(id='https://user.com/repost', mf2={}, status='complete').put()
|
||||||
|
|
||||||
mock_get.side_effect = [REPOST, self.toot_as2, self.actor]
|
mock_get.side_effect = [REPOST, self.toot_as2, self.actor]
|
||||||
|
@ -620,7 +620,7 @@ class WebmentionTest(testutil.TestCase):
|
||||||
|
|
||||||
def test_skip_update_if_content_unchanged(self, mock_get, mock_post):
|
def test_skip_update_if_content_unchanged(self, mock_get, mock_post):
|
||||||
"""https://github.com/snarfed/bridgy-fed/issues/78"""
|
"""https://github.com/snarfed/bridgy-fed/issues/78"""
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='https://user.com/reply', mf2=self.reply_mf2).put()
|
Object(id='https://user.com/reply', mf2=self.reply_mf2).put()
|
||||||
|
|
||||||
mock_get.side_effect = self.activitypub_gets
|
mock_get.side_effect = self.activitypub_gets
|
||||||
|
@ -888,7 +888,7 @@ class WebmentionTest(testutil.TestCase):
|
||||||
mock_get.side_effect = [self.note, self.actor]
|
mock_get.side_effect = [self.note, self.actor]
|
||||||
mock_post.return_value = requests_response('abc xyz')
|
mock_post.return_value = requests_response('abc xyz')
|
||||||
|
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
mf2 = copy.deepcopy(self.note_mf2)
|
mf2 = copy.deepcopy(self.note_mf2)
|
||||||
mf2['properties']['content'] = 'different'
|
mf2['properties']['content'] = 'different'
|
||||||
Object(id='https://user.com/post', domains=['user.com'], mf2=mf2).put()
|
Object(id='https://user.com/post', domains=['user.com'], mf2=mf2).put()
|
||||||
|
@ -1203,7 +1203,7 @@ class WebmentionTest(testutil.TestCase):
|
||||||
mock_get.return_value = requests_response('"unused"', status=410,
|
mock_get.return_value = requests_response('"unused"', status=410,
|
||||||
url='http://final/delete')
|
url='http://final/delete')
|
||||||
|
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='https://user.com/post#bridgy-fed-create',
|
Object(id='https://user.com/post#bridgy-fed-create',
|
||||||
mf2=self.note_mf2, status='in progress')
|
mf2=self.note_mf2, status='in progress')
|
||||||
|
|
||||||
|
@ -1344,7 +1344,6 @@ class WebmentionUtilTest(testutil.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.request_context = app.test_request_context('/')
|
|
||||||
self.request_context.__enter__()
|
self.request_context.__enter__()
|
||||||
g.user = self.make_user('user.com')
|
g.user = self.make_user('user.com')
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ class XrpcFeedTest(testutil.TestCase):
|
||||||
|
|
||||||
def test_getAuthorFeed(self):
|
def test_getAuthorFeed(self):
|
||||||
post_as2 = as2.from_as1(POST_AS)
|
post_as2 = as2.from_as1(POST_AS)
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='a', domains=['user.com'], labels=['user'], as2=post_as2).put()
|
Object(id='a', domains=['user.com'], labels=['user'], as2=post_as2).put()
|
||||||
Object(id='b', domains=['user.com'], labels=['user'],
|
Object(id='b', domains=['user.com'], labels=['user'],
|
||||||
as2=as2.from_as1(REPLY_AS)).put()
|
as2=as2.from_as1(REPLY_AS)).put()
|
||||||
|
@ -120,7 +120,7 @@ class XrpcFeedTest(testutil.TestCase):
|
||||||
self.assert_equals({'feed': []}, resp.json)
|
self.assert_equals({'feed': []}, resp.json)
|
||||||
|
|
||||||
def test_getPostThread(self):
|
def test_getPostThread(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='http://a/post', domains=['user.com'], labels=['user'],
|
Object(id='http://a/post', domains=['user.com'], labels=['user'],
|
||||||
as2=as2.from_as1(POST_THREAD_AS)).put()
|
as2=as2.from_as1(POST_THREAD_AS)).put()
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ class XrpcFeedTest(testutil.TestCase):
|
||||||
self.assertEqual(400, resp.status_code, resp.get_data(as_text=True))
|
self.assertEqual(400, resp.status_code, resp.get_data(as_text=True))
|
||||||
|
|
||||||
def test_getRepostedBy(self):
|
def test_getRepostedBy(self):
|
||||||
with app.test_request_context('/'):
|
with self.request_context:
|
||||||
Object(id='repost/1', domains=['user.com'], as2=as2.from_as1({
|
Object(id='repost/1', domains=['user.com'], as2=as2.from_as1({
|
||||||
**REPOST_AS,
|
**REPOST_AS,
|
||||||
'object': 'http://a/post',
|
'object': 'http://a/post',
|
||||||
|
|
|
@ -24,7 +24,7 @@ import requests
|
||||||
|
|
||||||
# load all Flask handlers
|
# load all Flask handlers
|
||||||
import app
|
import app
|
||||||
from flask_app import app, cache
|
from flask_app import app, cache, init_globals
|
||||||
import activitypub, common
|
import activitypub, common
|
||||||
from models import Object, PROTOCOLS, Target, User
|
from models import Object, PROTOCOLS, Target, User
|
||||||
import protocol
|
import protocol
|
||||||
|
@ -104,7 +104,14 @@ class TestCase(unittest.TestCase, testutil.Asserts):
|
||||||
|
|
||||||
util.now = lambda **kwargs: testutil.NOW
|
util.now = lambda **kwargs: testutil.NOW
|
||||||
|
|
||||||
|
self.app_context = app.app_context()
|
||||||
|
self.app_context.push()
|
||||||
|
init_globals()
|
||||||
|
|
||||||
|
self.request_context = app.test_request_context('/')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
self.app_context.pop()
|
||||||
self.ndb_context.__exit__(None, None, None)
|
self.ndb_context.__exit__(None, None, None)
|
||||||
self.client.__exit__(None, None, None)
|
self.client.__exit__(None, None, None)
|
||||||
super().tearDown()
|
super().tearDown()
|
||||||
|
@ -121,9 +128,8 @@ class TestCase(unittest.TestCase, testutil.Asserts):
|
||||||
user.put()
|
user.put()
|
||||||
return user
|
return user
|
||||||
|
|
||||||
@staticmethod
|
def add_objects(self):
|
||||||
def add_objects():
|
with self.request_context:
|
||||||
with app.test_request_context('/'):
|
|
||||||
# post
|
# post
|
||||||
Object(id='a', domains=['user.com'], labels=['feed', 'notification'],
|
Object(id='a', domains=['user.com'], labels=['feed', 'notification'],
|
||||||
as2=as2.from_as1(NOTE)).put()
|
as2=as2.from_as1(NOTE)).put()
|
||||||
|
|
|
@ -66,7 +66,8 @@ class Webmention(Protocol):
|
||||||
gateway: passed through to :func:`webutil.util.fetch_mf2`
|
gateway: passed through to :func:`webutil.util.fetch_mf2`
|
||||||
"""
|
"""
|
||||||
url = obj.key.id()
|
url = obj.key.id()
|
||||||
is_homepage = g.user and g.user.is_homepage(url)
|
is_homepage = ((g.user and g.user.is_homepage(url)) or
|
||||||
|
(g.external_user and g.external_user == url))
|
||||||
require_backlink = common.host_url().rstrip('/') if not is_homepage else None
|
require_backlink = common.host_url().rstrip('/') if not is_homepage else None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
Ładowanie…
Reference in New Issue