def setup_locals(self): self.alice = create_local_person("alice") self.bob = create_local_person("bob") self.carol = create_local_person("carol") self._real_inbox_post = bowler_views.InboxView.post self.remotes = {} self.received_post = set() def mock_post(*args, **kwargs): """ Wrapper for InboxView.post(), which flags that the local view has received a copy of the message. Adds the name of the user to self.received_post. If the message was sent to the local shared inbox, adds "(shared)". """ logger.info("Received local post") self.received_post.add(kwargs.get("username") or "(shared)") logger.info("%s %s %s", self.received_post, kwargs, kwargs.get("username", "(shared")) result = self._real_inbox_post(*args, **kwargs) return result bowler_views.InboxView.post = mock_post
def test_like(self): sender = create_local_person('sender') recipient = create_local_person('recipient') status = create_local_status(posted_by=sender) self.assertFalse( sender.has_liked(status), ) object_json = { '@context': 'https://www.w3.org/ns/activitystreams', 'id': 'foo', 'type': 'Like', 'actor': sender.url, 'object': status.url, } like = create( fields=object_json, ) self.assertTrue( sender.has_liked(status), msg = 'creates a favourite from sender to status', )
def test_when_sender_is_followed_by_local_users(self): from kepi.trilby_api.models import Follow, Person local_user = create_local_person() remote_alice = fetch(REMOTE_ALICE, expected_type=Person) following = Follow( follower=local_user, following=remote_alice, ) following.save() object_form = { 'id': 'https://example.com/some-note', 'type': 'Note', 'content': 'Lorem ipsum', } status = self._send_create_for_object(object_form, sender=remote_alice) self.assertIsNotNone( status, msg='it creates status', ) self.assertEqual( status.text, 'Lorem ipsum', msg='it creates status text', )
def setUp(self): settings.KEPI['LOCAL_OBJECT_HOSTNAME'] = 'testserver' self.alice = create_local_person('alice') self.client = Client() self.alice_url = uri_to_url(settings.KEPI['USER_LINK'] % { 'username': '******', })
def _send(self, message, recipient = None, recipientKeys = None, sender = None, senderKeys = None, path = INBOX_PATH, ): if recipient is None: recipient = create_local_person( name = 'alice', ) if senderKeys is None: senderKeys = json.load(open('kepi/bowler_pub/tests/keys/keys-0002.json', 'r')) if sender is None: sender = create_remote_person( remote_url = BOB_ID, name = 'bob', publicKey = senderKeys['public'], auto_fetch = True, ) self._sender = sender if not isinstance(message, dict): # This is used for things like checking # whether non-JSON content is handled correctly. content = message fields = {} else: # "message" is a dict content = None fields = message.copy() if 'id' not in fields: fields['id'] = BOB_ID+'#foo' if 'actor' not in fields: fields['actor'] = BOB_ID response = post_test_message( path = path, host = INBOX_HOST, secret = senderKeys['private'], content = content, fields = fields, ) logger.debug("Response code: %s", response.status_code) if response.status_code!=200: logger.debug("Response body: %s", response.content) return response
def test_tombstone(self): queen_anne = create_local_person('queen_anne') c = BowlerClient() response = c.get('/users/queen_anne') self.assertEqual(response.status_code, 200) self.assertDictContainsSubset( { 'name': 'queen_anne', 'id': 'https://testserver/users/queen_anne', 'type': 'Person', }, _response_to_dict(response), ) queen_anne.gone = True queen_anne.save() response = c.get('/users/queen_anne') self.assertEqual(response.status_code, 410) self.assertDictContainsSubset( { 'id': 'https://testserver/users/queen_anne', 'type': 'Tombstone', 'former_type': 'Person', }, _response_to_dict(response), )
def setUp(self): keys = json.load(open('kepi/bowler_pub/tests/keys/keys-0001.json', 'r')) create_local_person( name='alice', publicKey=keys['public'], privateKey=keys['private'], ) self._alice_keys = keys settings.ALLOWED_HOSTS = [ 'altair.example.com', 'testserver', ] settings.KEPI['LOCAL_OBJECT_HOSTNAME'] = 'testserver'
def setUp(self): settings.KEPI['LOCAL_OBJECT_HOSTNAME'] = 'testserver' self._fred = create_local_person(name='fred', ) self._remote_alice = bowler_tests.create_remote_person( remote_url=REMOTE_ALICE, name='alice', auto_fetch=True, )
def test_single_bowler_pub_view(self): alice = create_local_person('alice', note = ALICE_SUMMARY, ) c = BowlerClient() response = c.get('/users/alice') self.assertEqual(response.status_code, 200) result = _response_to_dict(response) self.assertDictContainsSubset( { 'name': 'alice', 'id': 'https://testserver/users/alice', 'type': 'Person', 'attachment': [], 'endpoints': { 'sharedInbox': 'https://testserver/sharedInbox', }, 'featured': 'https://testserver/users/alice/featured', 'followers': 'https://testserver/users/alice/followers', 'following': 'https://testserver/users/alice/following', 'icon': { 'mediaType': 'image/jpeg', 'type': 'Image', 'url': 'https://testserver/static/defaults/avatar_1.jpg', }, 'id': 'https://testserver/users/alice', 'image': { 'mediaType': 'image/jpeg', 'type': 'Image', 'url': 'https://testserver/static/defaults/header.jpg' }, 'inbox': 'https://testserver/users/alice/inbox', 'manuallyApprovesFollowers': True, 'name': 'alice', 'outbox': 'https://testserver/users/alice/outbox', 'preferredUsername': '******', 'publicKey': {'id': 'https://testserver/users/alice#main-key', 'owner': 'https://testserver/users/alice', 'publicKey': '-----BEGIN PUBLIC KEY-----\n' 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIUCqW/lyJ9eWkqvE7wpmHacu9\n' 'XOOSWZsx/+B2MM/xQYpUUIMZ3cyI3yMSOa3MS14wMBWdxlWNIMF7gVKHO6L9Ppns\n' 'BfTLbe/QMcssQ5rHv9oAMy/hWHGyaES3vbxzqT2qMxI5bIJRpOJfDlTpAY5AVqrn\n' '8sYx/1XA9YJOKFkQIQIDAQAB\n' '-----END PUBLIC KEY-----'}, 'summary': ALICE_SUMMARY_HTML, 'tag': [], 'type': 'Person', 'url': 'https://testserver/users/alice', }, result, )
def test_local_lookup(self): from kepi.trilby_api.models import Follow keys = json.load(open('kepi/bowler_pub/tests/keys/keys-0001.json', 'r')) alice = create_local_person( name='alice', publicKey=keys['public'], ) bob = create_local_person(name='bob', ) body, headers = test_message_body_and_headers( fields={ 'id': ACTIVITY_ID, 'type': "Follow", 'actor': LOCAL_ALICE, 'object': LOCAL_BOB, }, secret=keys['private'], ) create_remote_person( LOCAL_ALICE, 'Alice', load_default_keys_from='kepi/bowler_pub/tests/keys/keys-0001.json', ) validate(path=INBOX_PATH, headers=headers, body=body) self.assertTrue( Follow.objects.filter( follower=alice, following=bob, ).exists(), msg="Message passed validation", )
def test_when_sender_has_no_relevance_to_local_activity(self): local_user = create_local_person() object_form = { 'id': 'https://example.com/status/987', 'attributedTo': REMOTE_ALICE, 'type': 'note', 'content': 'lorem ipsum', } status = self._send_create_for_object(object_form, sender=REMOTE_ALICE) self.assertIsNone( status, msg='it does not create a status', )
def test_remote_user_gone(self): keys = json.load(open('kepi/bowler_pub/tests/keys/keys-0001.json', 'r')) fetched = { 'fred': False, } def on_fetch(): fetched['fred'] = True alice = create_local_person(name='alice', ) mock_remote_object( remote_url=REMOTE_FRED, content="They went away", status=410, on_fetch=on_fetch, ) body, headers = test_message_body_and_headers( fields={ 'id': ACTIVITY_ID, 'type': "Follow", 'actor': REMOTE_FRED, 'object': LOCAL_ALICE, }, secret=keys['private'], ) validate(path=INBOX_PATH, headers=headers, body=body) self.assertEqual(len( trilby_models.Follow.objects.filter(following=alice, )), 0, msg="The message did not validate") freds = trilby_models.RemotePerson.objects.filter( remote_url=REMOTE_FRED, ) self.assertEqual(len(freds), 0, msg="Fred's record was not stored locally") self.assertTrue(fetched['fred'], msg="Fred's record was fetched from his server")
def test_remote_user_spoofed(self): keys1 = json.load( open('kepi/bowler_pub/tests/keys/keys-0001.json', 'r')) keys2 = json.load( open('kepi/bowler_pub/tests/keys/keys-0002.json', 'r')) fetched = { 'fred': False, } def on_fetch(): fetched['fred'] = True alice = create_local_person(name='alice', ) create_remote_person( remote_url=REMOTE_FRED, name='Fred', publicKey=keys2['public'], on_fetch=on_fetch, ) body, headers = test_message_body_and_headers( fields={ 'id': ACTIVITY_ID, 'type': "Follow", 'actor': REMOTE_FRED, 'object': LOCAL_ALICE, }, secret=keys1['private'], ) logger.info('Test message headers: %s', headers) logger.info('Test message body: %s', body) validate(path=INBOX_PATH, headers=headers, body=body) self.assertEqual(len( trilby_models.Follow.objects.filter(following=alice, )), 0, msg="The message did not validate") self.assertTrue(fetched['fred'], msg="Fred's record was fetched from his server")
def test_remote_user_known(self): keys = json.load(open('kepi/bowler_pub/tests/keys/keys-0001.json', 'r')) fetched = { 'fred': False, } def on_fetch(): fetched['fred'] = True alice = create_local_person(name='alice', ) create_remote_person( remote_url=REMOTE_FRED, name='Fred', publicKey=keys['public'], on_fetch=on_fetch, ) body, headers = test_message_body_and_headers( fields={ 'id': ACTIVITY_ID, 'type': "Follow", 'actor': REMOTE_FRED, 'object': LOCAL_ALICE, }, secret=keys['private'], ) validate(path=INBOX_PATH, headers=headers, body=body) self.assertEqual(len( trilby_models.Follow.objects.filter(following=alice, )), 1, msg="The message validated successfully") fred = trilby_models.RemotePerson.objects.get(remote_url=REMOTE_FRED, ) self.assertTrue(fetched['fred'], msg="Fred's record was fetched from his server")
def test_with_sombrero(self): """ Tests whether creating a local status causes a message to be sent to remote followers of the creator. This is a regression test for issue 42: https://gitlab.com/marnanel/kepi/-/issues/42 """ self.alice = create_local_person("alice") self.bob = create_remote_person( remote_url='https://example.org/people/bob', name='bob', auto_fetch=True, ) self.seen_message = False def seen(): logger.info("Message received.") self.seen_message = True mock_remote_object( remote_url='https://example.org/people/bob/inbox', content='Thank you', status=200, as_post=True, on_fetch=seen, ) Follow(following=self.alice, follower=self.bob).save() create_local_status( posted_by=self.alice, content="I'll tell you the tale of the sweet nightingale.", send_signal=True, ) self.assertTrue(self.seen_message, msg="The remote server received the message.")
def test_shared_inbox(self): recipient = create_local_person( name = 'alice', ) self._send( message = { 'type': 'Create', 'object': OBJECT_FORM, 'to': OBJECT_FORM['to'], 'cc': OBJECT_FORM['cc'], }, recipient = recipient, path = INBOX_PATH, ) items = Status.objects.filter( account = self._sender, ) self.assertEqual( len(items), 1)
def test_featured(self): alice = create_local_person('alice') status = create_local_status( content = 'Hello world', posted_by = alice, ) c = BowlerClient() response = c.get('/users/alice/featured') self.assertEqual(response.status_code, 200) result = _response_to_dict(response) self.assertDictContainsSubset( { 'id': 'http://testserver/users/alice/featured', 'totalItems': 0, 'type': 'OrderedCollection', }, result, ) alice.featured = status alice.save() response = c.get('/users/alice/featured') self.assertEqual(response.status_code, 200) result = _response_to_dict(response) self.assertDictContainsSubset( { 'id': 'http://testserver/users/alice/featured', 'totalItems': 1, 'type': 'OrderedCollection', }, result, )
def test_when_sender_ccs_a_local_user(self): local_user = create_local_person() object_form = { 'id': 'https://example.com/status/987', 'attributedTo': REMOTE_ALICE, 'type': 'Note', 'content': 'lorem ipsum', 'cc': local_user.id, } status = self._send_create_for_object(object_form) self.assertIsNotNone( status, msg='it creates status', ) self.assertEqual( status.text, 'lorem ipsum', msg='it creates status text', )
def setUp(self): self._alice = create_local_person(name='alice', ) settings.KEPI['LOCAL_OBJECT_HOSTNAME'] = 'testserver'
def setUp(self): settings.KEPI['LOCAL_OBJECT_HOSTNAME'] = 'testserver' self._local_fred = create_local_person( name = 'fred', auto_follow = False, )