コード例 #1
0
    def test_activitypub_create_reply(self, mock_get, mock_post):
        mock_get.side_effect = self.activitypub_gets
        mock_post.return_value = requests_response('abc xyz', status=203)

        got = application.get_response('/webmention',
                                       method='POST',
                                       body=urlencode({
                                           'source':
                                           'http://a/reply',
                                           'target':
                                           'https://fed.brid.gy/',
                                       }).encode())
        self.assertEqual(203, got.status_int)

        mock_get.assert_has_calls((
            self.req('http://a/reply'),
            self.req('http://orig/post', headers=CONNEG_HEADERS_AS2_HTML),
            self.req('http://orig/author', headers=CONNEG_HEADERS_AS2_HTML),
        ))

        args, kwargs = mock_post.call_args
        self.assertEqual(('https://foo.com/inbox', ), args)
        self.assertEqual(self.as2_create, kwargs['json'])

        headers = kwargs['headers']
        self.assertEqual(CONTENT_TYPE_AS2, headers['Content-Type'])

        rsa_key = kwargs['auth'].header_signer._rsa._key
        self.assertEqual(self.key.private_pem(), rsa_key.exportKey())

        resp = Response.get_by_id('http://a/reply http://orig/as2')
        self.assertEqual('out', resp.direction)
        self.assertEqual('activitypub', resp.protocol)
        self.assertEqual('complete', resp.status)
        self.assertEqual(self.reply_mf2, json_loads(resp.source_mf2))
コード例 #2
0
    def get(self):
        source = util.get_required_param(self, 'source')
        target = util.get_required_param(self, 'target')

        id = '%s %s' % (source, target)
        resp = Response.get_by_id(id)
        if not resp:
            self.abort(404, 'No stored response for %s' % id)

        if resp.source_mf2:
            as1 = microformats2.json_to_object(json.loads(resp.source_mf2))
        elif resp.source_as2:
            as1 = as2.to_as1(json.loads(resp.source_as2))
        elif resp.source_atom:
            as1 = atom.atom_to_activity(resp.source_atom)
        else:
            self.abort(404, 'Stored response for %s has no data' % id)

        # add HTML meta redirect to source page. should trigger for end users in
        # browsers but not for webmention receivers (hopefully).
        html = microformats2.activities_to_html([as1])
        utf8 = '<meta charset="utf-8">'
        refresh = '<meta http-equiv="refresh" content="0;url=%s">' % source
        html = html.replace(utf8, utf8 + '\n' + refresh)

        self.response.write(html)
コード例 #3
0
ファイル: test_salmon.py プロジェクト: mdheller/bridgy-fed
    def test_like(self, mock_urlopen, mock_head, mock_get, mock_post):
        atom_like = """\
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns='http://www.w3.org/2005/Atom'
       xmlns:activity='http://activitystrea.ms/spec/1.0/'>
  <uri>https://my/like</uri>
  <author>
    <name>Alice</name>
    <uri>[email protected]</uri>
  </author>
  <activity:verb>http://activitystrea.ms/schema/1.0/like</activity:verb>
  <activity:object>http://orig/post</activity:object>
  <updated>%s</updated>
</entry>""" % datetime.datetime.now().isoformat('T')
        self.send_slap(mock_urlopen, mock_head, mock_get, mock_post, atom_like)

        # check webmention post
        mock_post.assert_called_once_with(
            'http://orig/webmention',
            data={
                'source':
                'http://localhost/render?source=https%3A%2F%2Fmy%2Flike&target=http%3A%2F%2Forig%2Fpost',
                'target': 'http://orig/post',
            },
            allow_redirects=False,
            headers=self.expected_headers,
            verify=False)

        # check stored response
        resp = Response.get_by_id('https://my/like http://orig/post')
        self.assertEqual('in', resp.direction)
        self.assertEqual('ostatus', resp.protocol)
        self.assertEqual('complete', resp.status)
        self.assertEqual(atom_like, resp.source_atom)
コード例 #4
0
    def test_activitypub_follow(self, mock_get, mock_post):
        mock_get.side_effect = [self.follow, self.actor]
        mock_post.return_value = requests_response('abc xyz')

        got = app.get_response('/webmention',
                               method='POST',
                               body=urllib.urlencode({
                                   'source':
                                   'http://a/follow',
                                   'target':
                                   'https://fed.brid.gy/',
                               }))
        self.assertEquals(200, got.status_int)

        mock_get.assert_has_calls((
            self.req('http://a/follow'),
            self.req('http://followee', headers=CONNEG_HEADERS_AS2_HTML),
        ))

        args, kwargs = mock_post.call_args
        self.assertEqual(('https://foo.com/inbox', ), args)
        self.assertEqual(self.follow_as2, kwargs['json'])

        headers = kwargs['headers']
        self.assertEqual(CONTENT_TYPE_AS2, headers['Content-Type'])

        rsa_key = kwargs['auth'].header_signer._rsa._key
        self.assertEqual(self.key.private_pem(), rsa_key.exportKey())

        resp = Response.get_by_id('http://a/follow http://followee')
        self.assertEqual('out', resp.direction)
        self.assertEqual('activitypub', resp.protocol)
        self.assertEqual('complete', resp.status)
        self.assertEqual(self.follow_mf2, json.loads(resp.source_mf2))
コード例 #5
0
    def test_reply(self, mock_urlopen, mock_head, mock_get, mock_post):
        atom_reply = """\
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns='http://www.w3.org/2005/Atom'>
  <id>https://my/reply</id>
  <uri>https://my/reply</uri>
  <author>
    <name>Alice</name>
    <uri>[email protected]</uri>
  </author>
  <thr:in-reply-to xmlns:thr="http://purl.org/syndication/thread/1.0">
    http://orig/post
  </thr:in-reply-to>
  <content>I hereby reply.</content>
  <title>My Reply</title>
  <updated>%s</updated>
</entry>""" % datetime.datetime.now().isoformat('T')
        self.send_slap(mock_urlopen, mock_head, mock_get, mock_post, atom_reply)

        # check webmention post
        mock_post.assert_called_once_with(
            'http://orig/webmention',
            data={'source': 'https://my/reply', 'target': 'http://orig/post'},
            allow_redirects=False, timeout=15, stream=True,
            headers=self.expected_headers)

        # check stored response
        resp = Response.get_by_id('https://my/reply http://orig/post')
        self.assertEqual('in', resp.direction)
        self.assertEqual('ostatus', resp.protocol)
        self.assertEqual('complete', resp.status)
        self.assertEqual(atom_reply, resp.source_atom)
コード例 #6
0
    def _test_inbox_mention(self, as2, mock_head, mock_get, mock_post):
        mock_head.return_value = requests_response(url='http://target')
        mock_get.return_value = requests_response(
            '<html><head><link rel="webmention" href="/webmention"></html>')
        mock_post.return_value = requests_response()

        with self.client:
            got = self.client.post('/foo.com/inbox', json=as2)
            self.assertEqual(200, got.status_code, got.get_data(as_text=True))
            mock_get.assert_called_once_with(
                'http://target/', headers=common.HEADERS, timeout=15, stream=True)

            expected_headers = copy.deepcopy(common.HEADERS)
            expected_headers['Accept'] = '*/*'
            mock_post.assert_called_once_with(
                'http://target/webmention',
                data={
                    'source': 'http://localhost/render?source=http%3A%2F%2Fthis%2Fmention&target=http%3A%2F%2Ftarget%2F',
                    'target': 'http://target/',
                },
                allow_redirects=False, timeout=15, stream=True,
                headers=expected_headers)

            resp = Response.get_by_id('http://this/mention http://target/')
            self.assertEqual('in', resp.direction)
            self.assertEqual('activitypub', resp.protocol)
            self.assertEqual('complete', resp.status)
            self.assertEqual(common.redirect_unwrap(as2), json_loads(resp.source_as2))
コード例 #7
0
ファイル: test_webmention.py プロジェクト: snarfed/bridgy-fed
    def test_salmon_like(self, mock_get, mock_post):
        mock_get.side_effect = [self.like, self.orig_html_atom, self.orig_atom]

        got = self.client.post('/webmention',
                               data={
                                   'source': 'http://a/like',
                                   'target': 'http://orig/post',
                               })
        self.assertEqual(200, got.status_code)

        mock_get.assert_has_calls((
            self.req('http://a/like'),
            self.req('http://orig/post', headers=CONNEG_HEADERS_AS2_HTML),
            self.req('http://orig/atom'),
        ))

        data = self.verify_salmon(mock_post)
        parsed = feedparser.parse(data)
        entry = parsed.entries[0]

        self.assertEqual('http://a/like', entry['id'])
        self.assertIn(
            {
                'rel': 'alternate',
                'href': 'http://a/like',
                'type': 'text/html',
            }, entry['links'])
        self.assertEqual('http://orig/post', entry['activity_object'])

        resp = Response.get_by_id('http://a/like http://orig/post')
        self.assertEqual('out', resp.direction)
        self.assertEqual('ostatus', resp.protocol)
        self.assertEqual('complete', resp.status)
        self.assertEqual(self.like_mf2, json_loads(resp.source_mf2))
コード例 #8
0
ファイル: test_webmention.py プロジェクト: snarfed/bridgy-fed
    def test_activitypub_create_repost(self, mock_get, mock_post):
        mock_get.side_effect = [self.repost, self.orig_as2, self.actor]
        mock_post.return_value = requests_response('abc xyz')

        got = self.client.post('/webmention',
                               data={
                                   'source': 'http://a/repost',
                                   'target': 'https://fed.brid.gy/',
                               })
        self.assertEqual(200, got.status_code)

        mock_get.assert_has_calls((
            self.req('http://a/repost'),
            self.req('http://orig/post', headers=CONNEG_HEADERS_AS2_HTML),
            self.req('http://orig/author', headers=CONNEG_HEADERS_AS2_HTML),
        ))

        args, kwargs = mock_post.call_args
        self.assertEqual(('https://foo.com/inbox', ), args)
        self.assertEqual(self.repost_as2, json_loads(kwargs['data']))

        headers = kwargs['headers']
        self.assertEqual(CONTENT_TYPE_AS2, headers['Content-Type'])

        rsa_key = kwargs['auth'].header_signer._rsa._key
        self.assertEqual(self.key.private_pem(), rsa_key.exportKey())

        resp = Response.get_by_id('http://a/repost http://orig/as2')
        self.assertEqual('out', resp.direction)
        self.assertEqual('activitypub', resp.protocol)
        self.assertEqual('complete', resp.status)
        self.assertEqual(self.repost_mf2, json_loads(resp.source_mf2))
コード例 #9
0
    def test_inbox_like(self, mock_head, mock_get, mock_post):
        mock_head.return_value = requests_response(url='http://orig/post')
        mock_get.side_effect = [
            # source actor
            requests_response(LIKE_WITH_ACTOR['actor'], headers={'Content-Type': common.CONTENT_TYPE_AS2}),
            # target post webmention discovery
            requests_response(
                '<html><head><link rel="webmention" href="/webmention"></html>'),
        ]
        mock_post.return_value = requests_response()

        got = self.client.post('/foo.com/inbox', json=LIKE)
        self.assertEqual(200, got.status_code)

        as2_headers = copy.deepcopy(common.HEADERS)
        as2_headers.update(common.CONNEG_HEADERS_AS2_HTML)
        mock_get.assert_has_calls((
            call('http://orig/actor', headers=as2_headers, stream=True, timeout=15),
            call('http://orig/post', headers=common.HEADERS, stream=True, timeout=15),
        ))

        args, kwargs = mock_post.call_args
        self.assertEqual(('http://orig/webmention',), args)
        self.assertEqual({
            # TODO
            'source': 'http://localhost/render?source=http%3A%2F%2Fthis%2Flike__ok&target=http%3A%2F%2Forig%2Fpost',
            'target': 'http://orig/post',
        }, kwargs['data'])

        resp = Response.get_by_id('http://this/like__ok http://orig/post')
        self.assertEqual('in', resp.direction)
        self.assertEqual('activitypub', resp.protocol)
        self.assertEqual('complete', resp.status)
        self.assertEqual(LIKE_WITH_ACTOR, json_loads(resp.source_as2))
コード例 #10
0
def render():
    """Fetches a stored Response and renders it as HTML."""
    source = flask_util.get_required_param('source')
    target = flask_util.get_required_param('target')

    id = f'{source} {target}'
    resp = Response.get_by_id(id)
    if not resp:
        error(f'No stored response for {id}', status=404)

    if resp.source_mf2:
        as1 = microformats2.json_to_object(json_loads(resp.source_mf2))
    elif resp.source_as2:
        as1 = as2.to_as1(json_loads(resp.source_as2))
    elif resp.source_atom:
        as1 = atom.atom_to_activity(resp.source_atom)
    else:
        error(f'Stored response for {id} has no data', status=404)

    # add HTML meta redirect to source page. should trigger for end users in
    # browsers but not for webmention receivers (hopefully).
    html = microformats2.activities_to_html([as1])
    utf8 = '<meta charset="utf-8">'
    refresh = f'<meta http-equiv="refresh" content="0;url={source}">'
    return html.replace(utf8, utf8 + '\n' + refresh)
コード例 #11
0
    def _test_inbox_mention(self, as2, mock_head, mock_get, mock_post):
        mock_head.return_value = requests_response(url='http://target')
        mock_get.return_value = requests_response(
            '<html><head><link rel="webmention" href="/webmention"></html>')
        mock_post.return_value = requests_response()

        got = app.get_response('/foo.com/inbox',
                               method='POST',
                               body=json.dumps(as2))
        self.assertEquals(200, got.status_int, got.body)
        mock_get.assert_called_once_with('http://target/',
                                         headers=common.HEADERS,
                                         verify=False)

        expected_headers = copy.deepcopy(common.HEADERS)
        expected_headers['Accept'] = '*/*'
        mock_post.assert_called_once_with(
            'http://target/webmention',
            data={
                'source':
                'http://localhost/render?source=http%3A%2F%2Fthis%2Fmention&target=http%3A%2F%2Ftarget%2F',
                'target': 'http://target/',
            },
            allow_redirects=False,
            headers=expected_headers,
            verify=False)

        resp = Response.get_by_id('http://this/mention http://target/')
        self.assertEqual('in', resp.direction)
        self.assertEqual('activitypub', resp.protocol)
        self.assertEqual('complete', resp.status)
        self.assertEqual(common.redirect_unwrap(as2),
                         json.loads(resp.source_as2))
コード例 #12
0
    def test_activitypub_create_post(self, mock_get, mock_post):
        mock_get.side_effect = [self.create, self.actor]
        mock_post.return_value = requests_response('abc xyz')

        Follower.get_or_create('orig', 'https://mastodon/aaa')
        Follower.get_or_create('orig',
                               'https://mastodon/bbb',
                               last_follow=json.dumps({
                                   'actor': {
                                       'publicInbox': 'https://public/inbox',
                                       'inbox': 'https://unused',
                                   }
                               }))
        Follower.get_or_create('orig',
                               'https://mastodon/ccc',
                               last_follow=json.dumps({
                                   'actor': {
                                       'endpoints': {
                                           'sharedInbox':
                                           'https://shared/inbox',
                                       },
                                   }
                               }))
        Follower.get_or_create('orig',
                               'https://mastodon/ddd',
                               last_follow=json.dumps(
                                   {'actor': {
                                       'inbox': 'https://inbox',
                                   }}))
        self.datastore_stub.Flush()

        got = app.get_response('/webmention',
                               method='POST',
                               body=urllib.urlencode({
                                   'source':
                                   'http://orig/post',
                                   'target':
                                   'https://fed.brid.gy/',
                               }))
        self.assertEquals(200, got.status_int)

        mock_get.assert_has_calls((self.req('http://orig/post'), ))

        inboxes = ('https://public/inbox', 'https://shared/inbox',
                   'https://inbox')
        for call, inbox in zip(mock_post.call_args_list, inboxes):
            self.assertEquals((inbox, ), call[0])
            self.assertEquals(self.create_as2, call[1]['json'])

        for inbox in inboxes:
            resp = Response.get_by_id('http://orig/post %s' % inbox)
            self.assertEqual('out', resp.direction, inbox)
            self.assertEqual('activitypub', resp.protocol, inbox)
            self.assertEqual('complete', resp.status, inbox)
            self.assertEqual(self.create_mf2, json.loads(resp.source_mf2),
                             inbox)
コード例 #13
0
    def test_inbox_follow_accept(self, mock_head, mock_get, mock_post):
        mock_head.return_value = requests_response(url='https://realize.be/')
        mock_get.side_effect = [
            # source actor
            requests_response(FOLLOW_WITH_ACTOR['actor'],
                              content_type=common.CONTENT_TYPE_AS2),
            # target post webmention discovery
            requests_response(
                '<html><head><link rel="webmention" href="/webmention"></html>'
            ),
        ]
        mock_post.return_value = requests_response()

        got = application.get_response(
            '/foo.com/inbox',
            method='POST',
            body=json_dumps(FOLLOW_WRAPPED).encode())
        self.assertEqual(200, got.status_int)

        as2_headers = copy.deepcopy(common.HEADERS)
        as2_headers.update(common.CONNEG_HEADERS_AS2_HTML)
        mock_get.assert_has_calls((call(FOLLOW['actor'],
                                        headers=as2_headers,
                                        stream=True,
                                        timeout=15), ))

        # check AP Accept
        self.assertEqual(2, len(mock_post.call_args_list))
        args, kwargs = mock_post.call_args_list[0]
        self.assertEqual(('http://follower/inbox', ), args)
        self.assertEqual(ACCEPT, kwargs['json'])

        # check webmention
        args, kwargs = mock_post.call_args_list[1]
        self.assertEqual(('https://realize.be/webmention', ), args)
        self.assertEqual(
            {
                'source':
                'http://localhost/render?source=https%3A%2F%2Fmastodon.social%2F6d1a&target=https%3A%2F%2Frealize.be%2F',
                'target': 'https://realize.be/',
            }, kwargs['data'])

        resp = Response.get_by_id(
            'https://mastodon.social/6d1a https://realize.be/')
        self.assertEqual('in', resp.direction)
        self.assertEqual('activitypub', resp.protocol)
        self.assertEqual('complete', resp.status)
        self.assertEqual(FOLLOW_WITH_ACTOR, json_loads(resp.source_as2))

        # check that we stored a Follower object
        follower = Follower.get_by_id('realize.be %s' % (FOLLOW['actor']))
        self.assertEqual('active', follower.status)
        self.assertEqual(FOLLOW_WRAPPED_WITH_ACTOR,
                         json_loads(follower.last_follow))
コード例 #14
0
    def test_salmon_reply(self, mock_get, mock_post):
        mock_get.side_effect = [
            self.reply, self.not_fediverse, self.orig_html_atom, self.orig_atom
        ]

        got = application.get_response('/webmention',
                                       method='POST',
                                       body=urlencode({
                                           'source':
                                           'http://a/reply',
                                           'target':
                                           'http://orig/post',
                                       }).encode())
        self.assertEqual(200, got.status_int)

        mock_get.assert_has_calls((
            self.req('http://a/reply'),
            self.req('http://not/fediverse', headers=CONNEG_HEADERS_AS2_HTML),
            self.req('http://orig/post', headers=CONNEG_HEADERS_AS2_HTML),
            self.req('http://orig/atom'),
        ))

        data = self.verify_salmon(mock_post)
        parsed = feedparser.parse(data)
        entry = parsed.entries[0]

        self.assertEqual('http://a/reply', entry['id'])
        self.assertIn(
            {
                'rel': 'alternate',
                'href': 'http://a/reply',
                'type': 'text/html',
            }, entry['links'])
        self.assertEqual(
            {
                'type': 'text/html',
                'href': 'http://orig/post',
                'ref': 'tag:fed.brid.gy,2017-08-22:orig-post',
            }, entry['thr_in-reply-to'])
        self.assertEqual(
            """\
<a class="u-in-reply-to" href="http://not/fediverse"></a><br></br>
<a class="u-in-reply-to" href="http://orig/post">foo ☕ bar</a><br></br>
<a href="http://localhost/"></a>""", entry.content[0]['value'])

        resp = Response.get_by_id('http://a/reply http://orig/post')
        self.assertEqual('out', resp.direction)
        self.assertEqual('ostatus', resp.protocol)
        self.assertEqual('complete', resp.status)
        self.assertEqual(self.reply_mf2, json_loads(resp.source_mf2))
コード例 #15
0
    def test_inbox_no_webmention_endpoint(self, mock_head, mock_get, mock_post):
        mock_get.side_effect = [
            # source actor
            requests_response(LIKE_WITH_ACTOR['actor'],
                              headers={'Content-Type': common.CONTENT_TYPE_AS2}),
            # target post webmention discovery
            requests_response('<html><body>foo</body></html>'),
        ]

        got = self.client.post('/foo.com/inbox', json=LIKE)
        self.assertEqual(200, got.status_code)

        resp = Response.get_by_id('http://this/like__ok http://orig/post')
        self.assertEqual('in', resp.direction)
        self.assertEqual('activitypub', resp.protocol)
        self.assertEqual('ignored', resp.status)
コード例 #16
0
    def get(self):
        source = util.get_required_param(self, 'source')
        target = util.get_required_param(self, 'target')

        id = '%s %s' % (source, target)
        resp = Response.get_by_id(id)
        if not resp:
            self.abort(404, 'No stored response for %s' % id)

        if resp.source_mf2:
            as1 = microformats2.json_to_object(json.loads(resp.source_mf2))
        elif resp.source_as2:
            as1 = as2.to_as1(json.loads(resp.source_as2))
        elif resp.source_atom:
            as1 = atom.atom_to_activity(resp.source_atom)
        else:
            self.abort(404, 'Stored response for %s has no data' % id)

        self.response.write(microformats2.activities_to_html([as1]))
コード例 #17
0
    def test_salmon_no_target_atom(self, mock_get, mock_post):
        orig_no_atom = requests_response(
            """\
<html>
<body>foo</body>
</html>""", 'http://orig/url')
        mock_get.side_effect = [self.reply, orig_no_atom]

        got = app.get_response('/webmention',
                               method='POST',
                               body=urllib.urlencode({
                                   'source':
                                   'http://a/reply',
                                   'target':
                                   'http://orig/post',
                               }))
        self.assertEquals(400, got.status_int)
        self.assertIn('Target post http://orig/url has no Atom link', got.body)

        self.assertIsNone(
            Response.get_by_id('http://a/reply http://orig/post'))
コード例 #18
0
ファイル: test_webmention.py プロジェクト: snarfed/bridgy-fed
    def test_salmon_no_target_atom(self, mock_get, mock_post):
        orig_no_atom = requests_response(
            """\
<html>
<body>foo</body>
</html>""", 'http://orig/url')
        mock_get.side_effect = [self.reply, self.not_fediverse, orig_no_atom]

        got = self.client.post('/webmention',
                               data={
                                   'source': 'http://a/reply',
                                   'target': 'http://orig/post',
                               })
        self.assertEqual(400, got.status_code)
        self.assertIn('Target post http://orig/url has no Atom link',
                      got.get_data(as_text=True))

        resp = Response.get_by_id('http://a/reply http://orig/url')
        self.assertEqual('out', resp.direction)
        self.assertEqual('ostatus', resp.protocol)
        self.assertEqual('error', resp.status)
コード例 #19
0
    def test_activitypub_error_no_salmon_fallback(self, mock_get, mock_post):
        mock_get.side_effect = [self.follow, self.actor]
        mock_post.return_value = requests_response('abc xyz',
                                                   status=405,
                                                   url='https://foo.com/inbox')

        got = application.get_response('/webmention',
                                       method='POST',
                                       body=urlencode({
                                           'source':
                                           'http://a/follow',
                                           'target':
                                           'https://fed.brid.gy/',
                                       }).encode())
        self.assertEqual(502, got.status_int, got.text)
        self.assertEqual(
            '405 Client Error: None for url: https://foo.com/inbox ; abc xyz',
            got.text)

        mock_get.assert_has_calls((
            self.req('http://a/follow'),
            self.req('http://followee/', headers=CONNEG_HEADERS_AS2_HTML),
        ))

        args, kwargs = mock_post.call_args
        self.assertEqual(('https://foo.com/inbox', ), args)
        self.assertEqual(self.follow_as2, json_loads(kwargs['data']))

        headers = kwargs['headers']
        self.assertEqual(CONTENT_TYPE_AS2, headers['Content-Type'])

        rsa_key = kwargs['auth'].header_signer._rsa._key
        self.assertEqual(self.key.private_pem(), rsa_key.exportKey())

        resp = Response.get_by_id('http://a/follow http://followee/')
        self.assertEqual('out', resp.direction)
        self.assertEqual('activitypub', resp.protocol)
        self.assertEqual('error', resp.status)
        self.assertEqual(self.follow_mf2, json_loads(resp.source_mf2))
コード例 #20
0
    def test_inbox_reply(self, mock_get, mock_post):
        mock_get.return_value = requests_response(
            '<html><head><link rel="webmention" href="/webmention"></html>')
        mock_post.return_value = requests_response()

        as2_note = {
            '@context': 'https://www.w3.org/ns/activitystreams',
            'type': 'Note',
            'content': 'A ☕ reply',
            'url': 'http://this/reply',
            'inReplyTo': 'http://orig/post',
            'cc': ['https://www.w3.org/ns/activitystreams#Public'],
        }
        got = app.get_response('/foo.com/inbox',
                               method='POST',
                               body=json.dumps(as2_note))
        self.assertEquals(200, got.status_int, got.body)
        mock_get.assert_called_once_with('http://orig/post',
                                         headers=common.HEADERS,
                                         verify=False)

        expected_headers = copy.deepcopy(common.HEADERS)
        expected_headers['Accept'] = '*/*'
        mock_post.assert_called_once_with('http://orig/webmention',
                                          data={
                                              'source': 'http://this/reply',
                                              'target': 'http://orig/post',
                                          },
                                          allow_redirects=False,
                                          headers=expected_headers,
                                          verify=False)

        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)
        self.assertEqual(as2_note, json.loads(resp.source_as2))
コード例 #21
0
    def test_inbox_like_proxy_url(self, mock_get, mock_post):
        actor = {
            '@context': 'https://www.w3.org/ns/activitystreams',
            'id': 'http://orig/actor',
            'type': 'Person',
            'name': 'Ms. Actor',
            'preferredUsername': '******',
            'image': {
                'type': 'Image',
                'url': 'http://orig/pic.jpg'
            },
        }
        mock_get.side_effect = [
            # source actor
            requests_response(
                actor, headers={'Content-Type': common.CONTENT_TYPE_AS2}),
            # target post webmention discovery
            requests_response(
                '<html><head><link rel="webmention" href="/webmention"></html>'
            ),
        ]
        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 = {
            '@context': 'https://www.w3.org/ns/activitystreams',
            'id': 'http://this/like#ok',
            'type': 'Like',
            'object': 'http://orig/post',
            'actor': 'http://orig/actor',
        }

        got = app.get_response('/foo.com/inbox',
                               method='POST',
                               body=json.dumps(as2_like))
        self.assertEquals(200, got.status_int)

        as2_headers = copy.deepcopy(common.HEADERS)
        as2_headers.update(common.CONNEG_HEADERS_AS2_HTML)
        mock_get.assert_has_calls((
            call('http://orig/actor', headers=as2_headers, timeout=15),
            call('http://orig/post', headers=common.HEADERS, verify=False),
        ))

        args, kwargs = mock_post.call_args
        self.assertEquals(('http://orig/webmention', ), args)
        self.assertEquals(
            {
                # TODO
                'source':
                'http://localhost/render?source=http%3A%2F%2Fthis%2Flike__ok&target=http%3A%2F%2Forig%2Fpost',
                'target': 'http://orig/post',
            },
            kwargs['data'])

        resp = Response.get_by_id('http://this/like__ok http://orig/post')
        self.assertEqual('in', resp.direction)
        self.assertEqual('activitypub', resp.protocol)
        self.assertEqual('complete', resp.status)
        as2_like['actor'] = actor
        self.assertEqual(as2_like, json.loads(resp.source_as2))
コード例 #22
0
ファイル: test_webmention.py プロジェクト: snarfed/bridgy-fed
    def test_activitypub_create_post(self, mock_get, mock_post):
        mock_get.side_effect = [self.create, self.actor]
        mock_post.return_value = requests_response('abc xyz')

        Follower.get_or_create('orig', 'https://mastodon/aaa')
        Follower.get_or_create('orig',
                               'https://mastodon/bbb',
                               last_follow=json_dumps({
                                   'actor': {
                                       'publicInbox': 'https://public/inbox',
                                       'inbox': 'https://unused',
                                   }
                               }))
        Follower.get_or_create('orig',
                               'https://mastodon/ccc',
                               last_follow=json_dumps({
                                   'actor': {
                                       'endpoints': {
                                           'sharedInbox':
                                           'https://shared/inbox',
                                       },
                                   }
                               }))
        Follower.get_or_create('orig',
                               'https://mastodon/ddd',
                               last_follow=json_dumps(
                                   {'actor': {
                                       'inbox': 'https://inbox',
                                   }}))
        Follower.get_or_create('orig',
                               'https://mastodon/eee',
                               status='inactive',
                               last_follow=json_dumps(
                                   {'actor': {
                                       'inbox': 'https://unused/2',
                                   }}))
        Follower.get_or_create(
            'orig',
            'https://mastodon/fff',
            last_follow=json_dumps({
                'actor': {
                    # dupe of eee; should be de-duped
                    'inbox': 'https://inbox',
                }
            }))

        got = self.client.post('/webmention',
                               data={
                                   'source': 'http://orig/post',
                                   'target': 'https://fed.brid.gy/',
                               })
        self.assertEqual(200, got.status_code)

        mock_get.assert_has_calls((self.req('http://orig/post'), ))

        inboxes = ('https://inbox', 'https://public/inbox',
                   'https://shared/inbox')
        self.assertEqual(len(inboxes), len(mock_post.call_args_list))
        for call, inbox in zip(mock_post.call_args_list, inboxes):
            self.assertEqual((inbox, ), call[0])
            self.assertEqual(self.create_as2, json_loads(call[1]['data']))

        for inbox in inboxes:
            resp = Response.get_by_id('http://orig/post %s' % inbox)
            self.assertEqual('out', resp.direction, inbox)
            self.assertEqual('activitypub', resp.protocol, inbox)
            self.assertEqual('complete', resp.status, inbox)
            self.assertEqual(self.create_mf2, json_loads(resp.source_mf2),
                             inbox)