2017-08-13 07:12:16 +00:00
|
|
|
# coding=utf-8
|
|
|
|
"""Unit tests for activitypub.py.
|
2017-08-13 21:49:35 +00:00
|
|
|
|
|
|
|
TODO: test error handling
|
2017-08-13 07:12:16 +00:00
|
|
|
"""
|
2017-08-19 19:36:36 +00:00
|
|
|
from __future__ import unicode_literals
|
2017-08-23 15:14:51 +00:00
|
|
|
import copy
|
2017-08-13 07:12:16 +00:00
|
|
|
import json
|
2017-08-13 21:49:35 +00:00
|
|
|
import urllib
|
2017-08-13 07:12:16 +00:00
|
|
|
|
2017-10-13 06:14:46 +00:00
|
|
|
from mock import call, patch
|
2017-08-23 15:14:51 +00:00
|
|
|
from oauth_dropins.webutil import util
|
2017-08-24 14:41:46 +00:00
|
|
|
from oauth_dropins.webutil.testutil import requests_response
|
2017-08-13 07:12:16 +00:00
|
|
|
import requests
|
|
|
|
|
|
|
|
import activitypub
|
2017-08-13 21:49:35 +00:00
|
|
|
from activitypub import app
|
2017-08-15 06:07:24 +00:00
|
|
|
import common
|
2017-10-10 00:29:50 +00:00
|
|
|
from models import MagicKey, Response
|
2017-10-01 14:09:22 +00:00
|
|
|
import testutil
|
2017-08-13 07:12:16 +00:00
|
|
|
|
|
|
|
|
2017-10-13 06:14:46 +00:00
|
|
|
@patch('requests.post')
|
|
|
|
@patch('requests.get')
|
2017-10-01 14:09:22 +00:00
|
|
|
class ActivityPubTest(testutil.TestCase):
|
2017-08-13 07:12:16 +00:00
|
|
|
|
2017-08-13 21:49:35 +00:00
|
|
|
def test_actor_handler(self, mock_get, _):
|
2017-08-24 14:41:46 +00:00
|
|
|
mock_get.return_value = requests_response("""
|
2017-08-13 07:12:16 +00:00
|
|
|
<body>
|
2017-10-24 04:49:43 +00:00
|
|
|
<a class="h-card u-url" rel="me" href="/about-me">Mrs. ☕ Foo</a>
|
2017-08-13 07:12:16 +00:00
|
|
|
</body>
|
2017-08-24 14:41:46 +00:00
|
|
|
""", url='https://foo.com/')
|
2017-08-13 07:12:16 +00:00
|
|
|
|
2017-08-13 21:49:35 +00:00
|
|
|
got = app.get_response('/foo.com')
|
2017-08-23 15:14:51 +00:00
|
|
|
mock_get.assert_called_once_with('http://foo.com/', headers=common.HEADERS,
|
|
|
|
timeout=util.HTTP_TIMEOUT)
|
2017-08-13 07:12:16 +00:00
|
|
|
self.assertEquals(200, got.status_int)
|
2017-10-20 14:13:04 +00:00
|
|
|
self.assertEquals(common.CONTENT_TYPE_AS2, got.headers['Content-Type'])
|
2017-08-13 07:12:16 +00:00
|
|
|
self.assertEquals({
|
2017-09-28 14:25:21 +00:00
|
|
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
|
|
|
'type' : 'Person',
|
2017-10-13 06:16:32 +00:00
|
|
|
'name': 'Mrs. ☕ Foo',
|
2017-10-26 15:07:29 +00:00
|
|
|
'preferredUsername': 'foo.com',
|
2017-10-24 04:49:43 +00:00
|
|
|
'id': 'http://localhost/foo.com',
|
2017-08-13 07:12:16 +00:00
|
|
|
'url': 'https://foo.com/about-me',
|
|
|
|
'inbox': 'http://localhost/foo.com/inbox',
|
2017-10-01 14:09:22 +00:00
|
|
|
'publicKey': {
|
2017-10-10 00:29:50 +00:00
|
|
|
'publicKeyPem': MagicKey.get_by_id('foo.com').public_pem(),
|
2017-10-01 14:09:22 +00:00
|
|
|
},
|
2017-08-13 07:12:16 +00:00
|
|
|
}, json.loads(got.body))
|
2017-08-13 21:49:35 +00:00
|
|
|
|
2017-08-19 20:31:06 +00:00
|
|
|
def test_actor_handler_no_hcard(self, mock_get, _):
|
2017-08-24 14:41:46 +00:00
|
|
|
mock_get.return_value = requests_response("""
|
2017-08-19 20:31:06 +00:00
|
|
|
<body>
|
|
|
|
<div class="h-entry">
|
|
|
|
<p class="e-content">foo bar</p>
|
|
|
|
</div>
|
|
|
|
</body>
|
2017-08-24 14:41:46 +00:00
|
|
|
""")
|
2017-08-19 20:31:06 +00:00
|
|
|
|
|
|
|
got = app.get_response('/foo.com')
|
2017-08-23 15:14:51 +00:00
|
|
|
mock_get.assert_called_once_with('http://foo.com/', headers=common.HEADERS,
|
|
|
|
timeout=util.HTTP_TIMEOUT)
|
2017-08-19 20:31:06 +00:00
|
|
|
self.assertEquals(400, got.status_int)
|
|
|
|
self.assertIn('representative h-card', got.body)
|
|
|
|
|
2017-08-13 21:49:35 +00:00
|
|
|
def test_inbox_reply(self, mock_get, mock_post):
|
2017-08-24 14:41:46 +00:00
|
|
|
mock_get.return_value = requests_response(
|
|
|
|
'<html><head><link rel="webmention" href="/webmention"></html>')
|
|
|
|
mock_post.return_value = requests_response()
|
2017-08-13 21:49:35 +00:00
|
|
|
|
2017-10-10 02:11:40 +00:00
|
|
|
as2_note = {
|
2017-08-13 21:49:35 +00:00
|
|
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
|
|
|
'type': 'Note',
|
2017-09-12 14:31:18 +00:00
|
|
|
'content': 'A ☕ reply',
|
2017-08-13 21:49:35 +00:00
|
|
|
'url': 'http://this/reply',
|
|
|
|
'inReplyTo': 'http://orig/post',
|
|
|
|
'cc': ['https://www.w3.org/ns/activitystreams#Public'],
|
2017-10-10 02:11:40 +00:00
|
|
|
}
|
|
|
|
got = app.get_response('/foo.com/inbox', method='POST',
|
|
|
|
body=json.dumps(as2_note))
|
2017-10-11 05:42:19 +00:00
|
|
|
self.assertEquals(200, got.status_int, got.body)
|
2017-08-19 19:29:10 +00:00
|
|
|
mock_get.assert_called_once_with(
|
|
|
|
'http://orig/post', headers=common.HEADERS, verify=False)
|
2017-08-13 21:49:35 +00:00
|
|
|
|
2017-08-23 15:14:51 +00:00
|
|
|
expected_headers = copy.deepcopy(common.HEADERS)
|
|
|
|
expected_headers['Accept'] = '*/*'
|
2017-08-13 21:49:35 +00:00
|
|
|
mock_post.assert_called_once_with(
|
|
|
|
'http://orig/webmention',
|
|
|
|
data={
|
|
|
|
'source': 'http://this/reply',
|
|
|
|
'target': 'http://orig/post',
|
|
|
|
},
|
|
|
|
allow_redirects=False,
|
2017-08-23 15:14:51 +00:00
|
|
|
headers=expected_headers,
|
2017-08-13 21:49:35 +00:00
|
|
|
verify=False)
|
2017-10-04 14:07:22 +00:00
|
|
|
|
2017-10-10 00:29:50 +00:00
|
|
|
resp = Response.get_by_id('http://this/reply http://orig/post')
|
|
|
|
self.assertEqual('in', resp.direction)
|
|
|
|
self.assertEqual('activitypub', resp.protocol)
|
|
|
|
self.assertEqual('complete', resp.status)
|
2017-10-10 02:11:40 +00:00
|
|
|
self.assertEqual(as2_note, json.loads(resp.source_as2))
|
2017-10-10 00:29:50 +00:00
|
|
|
|
2017-10-11 05:42:19 +00:00
|
|
|
def test_inbox_like_proxy_url(self, mock_get, mock_post):
|
2017-10-13 06:14:46 +00:00
|
|
|
actor = {
|
|
|
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
|
|
|
'id': 'http://orig/actor',
|
|
|
|
'type': 'Person',
|
|
|
|
'name': 'Ms. Actor',
|
|
|
|
'preferredUsername': 'msactor',
|
|
|
|
'image': {'type': 'Image', 'url': 'http://orig/pic.jpg'},
|
|
|
|
}
|
|
|
|
mock_get.side_effect = [
|
|
|
|
# source actor
|
2017-10-20 14:13:04 +00:00
|
|
|
requests_response(actor, headers={'Content-Type': common.CONTENT_TYPE_AS2}),
|
2017-10-13 06:14:46 +00:00
|
|
|
# target post webmention discovery
|
|
|
|
requests_response(
|
|
|
|
'<html><head><link rel="webmention" href="/webmention"></html>'),
|
|
|
|
]
|
2017-10-11 05:42:19 +00:00
|
|
|
mock_post.return_value = requests_response()
|
|
|
|
|
|
|
|
# based on example Mastodon like:
|
|
|
|
# https://github.com/snarfed/bridgy-fed/issues/4#issuecomment-334212362
|
|
|
|
# (reposts are very similar)
|
|
|
|
as2_like = {
|
2017-10-04 14:07:22 +00:00
|
|
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
2017-10-12 04:12:39 +00:00
|
|
|
'id': 'http://this/like#ok',
|
2017-10-04 14:07:22 +00:00
|
|
|
'type': 'Like',
|
|
|
|
'object': 'http://orig/post',
|
2017-10-13 06:14:46 +00:00
|
|
|
'actor': 'http://orig/actor',
|
2017-10-11 05:42:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
got = app.get_response('/foo.com/inbox', method='POST',
|
|
|
|
body=json.dumps(as2_like))
|
|
|
|
self.assertEquals(200, got.status_int)
|
2017-10-13 06:14:46 +00:00
|
|
|
|
|
|
|
as2_headers = copy.deepcopy(common.HEADERS)
|
2017-10-20 14:13:04 +00:00
|
|
|
as2_headers.update(common.CONNEG_HEADERS_AS2_HTML)
|
2017-10-13 06:14:46 +00:00
|
|
|
mock_get.assert_has_calls((
|
|
|
|
call('http://orig/actor', headers=as2_headers, timeout=15),
|
|
|
|
call('http://orig/post', headers=common.HEADERS, verify=False),
|
|
|
|
))
|
2017-10-10 00:29:50 +00:00
|
|
|
|
2017-10-11 05:42:19 +00:00
|
|
|
args, kwargs = mock_post.call_args
|
|
|
|
self.assertEquals(('http://orig/webmention',), args)
|
|
|
|
self.assertEquals({
|
|
|
|
# TODO
|
2017-10-12 04:12:39 +00:00
|
|
|
'source': 'http://localhost/render?source=http%3A%2F%2Fthis%2Flike__ok&target=http%3A%2F%2Forig%2Fpost',
|
2017-10-11 05:42:19 +00:00
|
|
|
'target': 'http://orig/post',
|
|
|
|
}, kwargs['data'])
|
|
|
|
|
2017-10-12 04:12:39 +00:00
|
|
|
resp = Response.get_by_id('http://this/like__ok http://orig/post')
|
2017-10-11 05:42:19 +00:00
|
|
|
self.assertEqual('in', resp.direction)
|
|
|
|
self.assertEqual('activitypub', resp.protocol)
|
|
|
|
self.assertEqual('complete', resp.status)
|
2017-10-13 06:14:46 +00:00
|
|
|
as2_like['actor'] = actor
|
2017-10-11 05:42:19 +00:00
|
|
|
self.assertEqual(as2_like, json.loads(resp.source_as2))
|
2017-10-17 05:21:13 +00:00
|
|
|
|
|
|
|
def test_inbox_unsupported_type(self, mock_get, mock_post):
|
|
|
|
got = app.get_response('/foo.com/inbox', method='POST', body=json.dumps({
|
|
|
|
'@context': ['https://www.w3.org/ns/activitystreams'],
|
|
|
|
'id': 'https://xoxo.zone/users/aaronpk#follows/40',
|
|
|
|
'type': 'Follow',
|
|
|
|
'actor': 'https://xoxo.zone/users/aaronpk',
|
|
|
|
'object': 'http://snarfed.org/',
|
|
|
|
}))
|
|
|
|
self.assertEquals(501, got.status_int)
|