zerver: Add feature for notification at rename of a stream.

Feature of sending notification to the stream using notification bot
is added. user_profile is also passed to do_rename_stream for using
the name of user who renamed the stream in notification.
Notification is sent to the stream using
internal_send_stream_message in do_rename_stream.

Fixes #11034.
This commit is contained in:
sahil839
2019-01-05 03:47:38 -08:00
committed by Tim Abbott
parent 3f0bae8c38
commit 4dcccf32f8
5 changed files with 83 additions and 12 deletions

View File

@@ -3256,7 +3256,10 @@ def do_change_stream_announcement_only(stream: Stream, is_announcement_only: boo
stream.is_announcement_only = is_announcement_only stream.is_announcement_only = is_announcement_only
stream.save(update_fields=['is_announcement_only']) stream.save(update_fields=['is_announcement_only'])
def do_rename_stream(stream: Stream, new_name: str, log: bool=True) -> Dict[str, str]: def do_rename_stream(stream: Stream,
new_name: str,
user_profile: UserProfile,
log: bool=True) -> Dict[str, str]:
old_name = stream.name old_name = stream.name
stream.name = new_name stream.name = new_name
stream.save(update_fields=["name"]) stream.save(update_fields=["name"])
@@ -3307,7 +3310,14 @@ def do_rename_stream(stream: Stream, new_name: str, log: bool=True) -> Dict[str,
name=old_name, name=old_name,
) )
send_event(stream.realm, event, can_access_stream_user_ids(stream)) send_event(stream.realm, event, can_access_stream_user_ids(stream))
sender = get_system_bot(settings.NOTIFICATION_BOT)
internal_send_stream_message(
stream.realm,
sender,
new_name,
"welcome",
"@**%s** renamed stream **%s** to **%s**" % (user_profile.full_name, old_name, new_name)
)
# Even though the token doesn't change, the web client needs to update the # Even though the token doesn't change, the web client needs to update the
# email forwarding address to display the correctly-escaped new name. # email forwarding address to display the correctly-escaped new name.
return {"email_address": new_email} return {"email_address": new_email}

View File

@@ -24,4 +24,4 @@ class Command(ZulipBaseCommand):
new_name = options['new_name'] new_name = options['new_name']
stream = get_stream(old_name, realm) stream = get_stream(old_name, realm)
do_rename_stream(stream, new_name) do_rename_stream(stream, new_name, self.user_profile)

View File

@@ -2094,10 +2094,9 @@ class EventsRegisterTest(ZulipTestCase):
stream = self.make_stream('old_name') stream = self.make_stream('old_name')
new_name = u'stream with a brand new name' new_name = u'stream with a brand new name'
self.subscribe(self.user_profile, stream.name) self.subscribe(self.user_profile, stream.name)
notification = '<p><span class="user-mention" data-user-id="4">@King Hamlet</span> renamed stream <strong>old_name</strong> to <strong>stream with a brand new name</strong></p>'
action = lambda: do_rename_stream(stream, new_name) action = lambda: do_rename_stream(stream, new_name, self.user_profile)
events = self.do_test(action, num_events=2) events = self.do_test(action, num_events=3)
schema_checker = self.check_events_dict([ schema_checker = self.check_events_dict([
('type', equals('stream')), ('type', equals('stream')),
('op', equals('update')), ('op', equals('update')),
@@ -2118,6 +2117,39 @@ class EventsRegisterTest(ZulipTestCase):
]) ])
error = schema_checker('events[1]', events[1]) error = schema_checker('events[1]', events[1])
self.assert_on_error(error) self.assert_on_error(error)
schema_checker = check_dict([
('stream_email_notify', equals(False)),
('flags', check_list(check_string)),
('email_notified', equals(True)),
('type', equals('message')),
('message', check_dict([
('timestamp', check_int),
('content', equals(notification)),
('content_type', equals('text/html')),
('sender_email', equals('notification-bot@zulip.com')),
('sender_id', check_int),
('sender_short_name', equals('notification-bot')),
('display_recipient', equals(new_name)),
('id', check_int),
('stream_id', check_int),
('sender_realm_str', check_string),
('sender_full_name', equals('Notification Bot')),
('is_me_message', equals(False)),
('type', equals('stream')),
('submessages', check_list(check_string)),
(TOPIC_LINKS, check_list(check_url)),
('avatar_url', check_url),
('reactions', check_list(None)),
('client', equals('Internal')),
(TOPIC_NAME, equals('welcome')),
('recipient_id', check_int)
])),
('id', check_int),
('push_notified', equals(True)),
('stream_push_notify', equals(False)),
])
error = schema_checker('events[2]', events[2])
self.assert_on_error(error)
def test_deactivate_stream_neversubscribed(self) -> None: def test_deactivate_stream_neversubscribed(self) -> None:
stream = self.make_stream('old_name') stream = self.make_stream('old_name')

View File

@@ -64,6 +64,7 @@ from zerver.lib.actions import (
do_remove_default_stream_group, do_remove_default_stream_group,
do_change_default_stream_group_description, do_change_default_stream_group_description,
do_change_default_stream_group_name, do_change_default_stream_group_name,
do_rename_stream,
lookup_default_stream_groups, lookup_default_stream_groups,
can_access_stream_user_ids, can_access_stream_user_ids,
validate_user_access_to_subscribers_helper, validate_user_access_to_subscribers_helper,
@@ -464,14 +465,22 @@ class StreamAdminTest(ZulipTestCase):
result = self.client_patch('/json/streams/%d' % (stream_id,), result = self.client_patch('/json/streams/%d' % (stream_id,),
{'new_name': ujson.dumps('whatever')}) {'new_name': ujson.dumps('whatever')})
self.assert_json_success(result) self.assert_json_success(result)
# Should be a name event and an email address event # Should be a name event, an email address event and a notification event
self.assert_length(events, 2) self.assert_length(events, 3)
notified_user_ids = set(events[-1]['users']) notified_user_ids = set(events[0]['users'])
self.assertIn(user_profile.id, notified_user_ids) self.assertIn(user_profile.id, notified_user_ids)
self.assertIn(cordelia.id, notified_user_ids) self.assertIn(cordelia.id, notified_user_ids)
self.assertNotIn(prospero.id, notified_user_ids) self.assertNotIn(prospero.id, notified_user_ids)
notified_with_bot_users = events[-1]['users']
notified_with_bot_user_ids = []
notified_with_bot_user_ids.append(notified_with_bot_users[0]['id'])
notified_with_bot_user_ids.append(notified_with_bot_users[1]['id'])
self.assertIn(user_profile.id, notified_with_bot_user_ids)
self.assertIn(cordelia.id, notified_with_bot_user_ids)
self.assertNotIn(prospero.id, notified_with_bot_user_ids)
def test_rename_stream(self) -> None: def test_rename_stream(self) -> None:
user_profile = self.example_user('hamlet') user_profile = self.example_user('hamlet')
email = user_profile.email email = user_profile.email
@@ -501,7 +510,6 @@ class StreamAdminTest(ZulipTestCase):
result = self.client_patch('/json/streams/%d' % (stream_id,), result = self.client_patch('/json/streams/%d' % (stream_id,),
{'new_name': ujson.dumps('stream_name2')}) {'new_name': ujson.dumps('stream_name2')})
self.assert_json_success(result) self.assert_json_success(result)
event = events[1]['event'] event = events[1]['event']
self.assertEqual(event, dict( self.assertEqual(event, dict(
op='update', op='update',
@@ -599,6 +607,27 @@ class StreamAdminTest(ZulipTestCase):
{'new_name': ujson.dumps('stream_name2')}) {'new_name': ujson.dumps('stream_name2')})
self.assert_json_error(result, 'Must be an organization administrator') self.assert_json_error(result, 'Must be an organization administrator')
def test_notify_on_stream_rename(self) -> None:
user_profile = self.example_user('hamlet')
self.login(user_profile.email)
self.make_stream('stream_name1')
stream = self.subscribe(user_profile, 'stream_name1')
do_change_is_admin(user_profile, True)
result = self.client_patch('/json/streams/%d' % (stream.id,),
{'new_name': ujson.dumps('stream_name2')})
self.assert_json_success(result)
# Inspect the notification message sent
message = self.get_last_message()
actual_stream = Stream.objects.get(id=message.recipient.type_id)
message_content = '@**King Hamlet** renamed stream **stream_name1** to **stream_name2**'
self.assertEqual(message.sender.realm, user_profile.realm)
self.assertEqual(actual_stream.name, 'stream_name2')
self.assertEqual(message.recipient.type, Recipient.STREAM)
self.assertEqual(message.content, message_content)
self.assertEqual(message.sender.email, 'notification-bot@zulip.com')
def test_realm_admin_can_update_unsub_private_stream(self) -> None: def test_realm_admin_can_update_unsub_private_stream(self) -> None:
iago = self.example_user('iago') iago = self.example_user('iago')
self.login(iago.email) self.login(iago.email)

View File

@@ -167,7 +167,7 @@ def update_stream_backend(
# Check that the stream name is available (unless we are # Check that the stream name is available (unless we are
# are only changing the casing of the stream name). # are only changing the casing of the stream name).
check_stream_name_available(user_profile.realm, new_name) check_stream_name_available(user_profile.realm, new_name)
do_rename_stream(stream, new_name) do_rename_stream(stream, new_name, user_profile)
if is_announcement_only is not None: if is_announcement_only is not None:
do_change_stream_announcement_only(stream, is_announcement_only) do_change_stream_announcement_only(stream, is_announcement_only)