from django.utils.timezone import now as timezone_now from zerver.lib.actions import do_change_stream_invite_only, get_client from zerver.lib.test_classes import ZulipTestCase from zerver.models import Message, UserMessage, get_realm, get_stream class TopicHistoryTest(ZulipTestCase): def test_topics_history_zephyr_mirror(self) -> None: user_profile = self.mit_user('sipbtest') stream_name = 'new_stream' # Send a message to this new stream from another user self.subscribe(self.mit_user("starnine"), stream_name) stream = get_stream(stream_name, user_profile.realm) self.send_stream_message(self.mit_user("starnine"), stream_name, topic_name="secret topic") # Now subscribe this MIT user to the new stream and verify # that the new topic is not accessible self.login_user(user_profile) self.subscribe(user_profile, stream_name) endpoint = f'/json/users/me/{stream.id}/topics' result = self.client_get(endpoint, {}, subdomain="zephyr") self.assert_json_success(result) history = result.json()['topics'] self.assertEqual(history, []) def test_topics_history(self) -> None: # verified: int(UserMessage.flags.read) == 1 user_profile = self.example_user('iago') self.login_user(user_profile) stream_name = 'Verona' stream = get_stream(stream_name, user_profile.realm) recipient = stream.recipient def create_test_message(topic: str) -> int: # TODO: Clean this up to send messages the normal way. hamlet = self.example_user('hamlet') message = Message( sender=hamlet, recipient=recipient, content='whatever', date_sent=timezone_now(), sending_client=get_client('whatever'), ) message.set_topic_name(topic) message.save() UserMessage.objects.create( user_profile=user_profile, message=message, flags=0, ) return message.id # our most recent topics are topic0, topic1, topic2 # Create old messages with strange spellings. create_test_message('topic2') create_test_message('toPIc1') create_test_message('toPIc0') create_test_message('topic2') create_test_message('topic2') create_test_message('Topic2') # Create new messages topic2_msg_id = create_test_message('topic2') create_test_message('topic1') create_test_message('topic1') topic1_msg_id = create_test_message('topic1') topic0_msg_id = create_test_message('topic0') endpoint = f'/json/users/me/{stream.id}/topics' result = self.client_get(endpoint, {}) self.assert_json_success(result) history = result.json()['topics'] # We only look at the most recent three topics, because # the prior fixture data may be unreliable. history = history[:3] self.assertEqual([topic['name'] for topic in history], [ 'topic0', 'topic1', 'topic2', ]) self.assertEqual([topic['max_id'] for topic in history], [ topic0_msg_id, topic1_msg_id, topic2_msg_id, ]) # Now try as cordelia, who we imagine as a totally new user in # that she doesn't have UserMessage rows. We should see the # same results for a public stream. self.login('cordelia') result = self.client_get(endpoint, {}) self.assert_json_success(result) history = result.json()['topics'] # We only look at the most recent three topics, because # the prior fixture data may be unreliable. history = history[:3] self.assertEqual([topic['name'] for topic in history], [ 'topic0', 'topic1', 'topic2', ]) self.assertIn('topic0', [topic['name'] for topic in history]) self.assertEqual([topic['max_id'] for topic in history], [ topic0_msg_id, topic1_msg_id, topic2_msg_id, ]) # Now make stream private, but subscribe cordelia do_change_stream_invite_only(stream, True) self.subscribe(self.example_user("cordelia"), stream.name) result = self.client_get(endpoint, {}) self.assert_json_success(result) history = result.json()['topics'] history = history[:3] # Cordelia doesn't have these recent history items when we # wasn't subscribed in her results. self.assertNotIn('topic0', [topic['name'] for topic in history]) self.assertNotIn('topic1', [topic['name'] for topic in history]) self.assertNotIn('topic2', [topic['name'] for topic in history]) def test_bad_stream_id(self) -> None: self.login('iago') # non-sensible stream id endpoint = '/json/users/me/9999999999/topics' result = self.client_get(endpoint, {}) self.assert_json_error(result, 'Invalid stream id') # out of realm bad_stream = self.make_stream( 'mit_stream', realm=get_realm('zephyr'), ) endpoint = f'/json/users/me/{bad_stream.id}/topics' result = self.client_get(endpoint, {}) self.assert_json_error(result, 'Invalid stream id') # private stream to which I am not subscribed private_stream = self.make_stream( 'private_stream', invite_only=True, ) endpoint = f'/json/users/me/{private_stream.id}/topics' result = self.client_get(endpoint, {}) self.assert_json_error(result, 'Invalid stream id') def test_get_topics_web_public_stream_web_public_request(self) -> None: stream = self.make_stream('web-public-steram', is_web_public=True) for i in range(3): self.send_stream_message(self.example_user('iago'), stream.name, topic_name='topic' + str(i)) endpoint = f'/json/users/me/{stream.id}/topics' result = self.client_get(endpoint) self.assert_json_success(result) history = result.json()['topics'] self.assertEqual([topic['name'] for topic in history], [ 'topic2', 'topic1', 'topic0', ]) def test_get_topics_non_web_public_stream_web_public_request(self) -> None: stream = get_stream('Verona', self.example_user('iago').realm) endpoint = f'/json/users/me/{stream.id}/topics' result = self.client_get(endpoint) self.assert_json_error(result, 'Invalid stream id', 400) def test_get_topics_non_existant_stream_web_public_request(self) -> None: non_existant_stream_id = 10000000000000000000000 endpoint = f'/json/users/me/{non_existant_stream_id}/topics' result = self.client_get(endpoint) self.assert_json_error(result, 'Invalid stream id', 400) class TopicDeleteTest(ZulipTestCase): def test_topic_delete(self) -> None: initial_last_msg_id = self.get_last_message().id stream_name = 'new_stream' topic_name = 'new topic 2' # NON-ADMIN USER user_profile = self.example_user('hamlet') self.subscribe(user_profile, stream_name) # Send message stream = get_stream(stream_name, user_profile.realm) self.send_stream_message(user_profile, stream_name, topic_name=topic_name) last_msg_id = self.send_stream_message(user_profile, stream_name, topic_name=topic_name) # Deleting the topic self.login_user(user_profile) endpoint = '/json/streams/' + str(stream.id) + '/delete_topic' result = self.client_post(endpoint, { "topic_name": topic_name, }) self.assert_json_error(result, "Must be an organization administrator") self.assertEqual(self.get_last_message().id, last_msg_id) # Make stream private with limited history do_change_stream_invite_only(stream, invite_only=True, history_public_to_subscribers=False) # ADMIN USER subscribed now user_profile = self.example_user('iago') self.subscribe(user_profile, stream_name) self.login_user(user_profile) new_last_msg_id = self.send_stream_message(user_profile, stream_name, topic_name=topic_name) # Now admin deletes all messages in topic -- which should only # delete new_last_msg_id, i.e. the one sent since they joined. self.assertEqual(self.get_last_message().id, new_last_msg_id) result = self.client_post(endpoint, { "topic_name": topic_name, }) self.assert_json_success(result) self.assertEqual(self.get_last_message().id, last_msg_id) # Try to delete all messages in the topic again. There are no messages accessible # to the administrator, so this should do nothing. result = self.client_post(endpoint, { "topic_name": topic_name, }) self.assert_json_success(result) self.assertEqual(self.get_last_message().id, last_msg_id) # Make the stream's history public to subscribers do_change_stream_invite_only(stream, invite_only=True, history_public_to_subscribers=True) # Delete the topic should now remove all messages result = self.client_post(endpoint, { "topic_name": topic_name, }) self.assert_json_success(result) self.assertEqual(self.get_last_message().id, initial_last_msg_id) # Delete again, to test the edge case of deleting an empty topic. result = self.client_post(endpoint, { "topic_name": topic_name, }) self.assert_json_success(result) self.assertEqual(self.get_last_message().id, initial_last_msg_id)