events: Fix updating user email on changing email_address_visibility.

When email_address_visibility is changed and either the old value
or the updated value is EMAIL_ADDRESS_VISIBILITY_EVERYONE then
email field of all users is updated and we also send the corresponding
event to clients. But apply_event code did not update the data on
receiving the event, so this commit fixes the code to correctly
handle the event in apply_event.

(We also use this event when just changing a user's email address).

This commit also adds the tests and openapi schema for the event.
This commit is contained in:
Sahil Batra 2021-10-04 22:22:57 +05:30 committed by Tim Abbott
parent 402968ccf3
commit eedd832ca9
4 changed files with 46 additions and 2 deletions

View File

@ -1130,6 +1130,12 @@ realm_user_person_types = dict(
("delivery_email", str), ("delivery_email", str),
], ],
), ),
email=DictType(
required_keys=[
("user_id", int),
("new_email", str),
],
),
full_name=DictType( full_name=DictType(
required_keys=[ required_keys=[
# vertical formatting # vertical formatting

View File

@ -787,6 +787,9 @@ def apply_event(
if field in person and field in state: if field in person and field in state:
state[field] = person[field] state[field] = person[field]
if "new_email" in person:
state["email"] = person["new_email"]
# In the unlikely event that the current user # In the unlikely event that the current user
# just changed to/from being an admin, we need # just changed to/from being an admin, we need
# to add/remove the data on all bots in the # to add/remove the data on all bots in the
@ -832,6 +835,8 @@ def apply_event(
p["profile_data"][str(custom_field_id)] = { p["profile_data"][str(custom_field_id)] = {
"value": custom_field_new_value, "value": custom_field_new_value,
} }
if "new_email" in person:
p["email"] = person["new_email"]
else: else:
raise AssertionError("Unexpected event type {type}/{op}".format(**event)) raise AssertionError("Unexpected event type {type}/{op}".format(**event))
elif event["type"] == "realm_bot": elif event["type"] == "realm_bot":

View File

@ -549,6 +549,24 @@ paths:
This user-generated HTML content should be rendered This user-generated HTML content should be rendered
using the same CSS and client-side security protections using the same CSS and client-side security protections
as are used for message content. as are used for message content.
- type: object
additionalProperties: False
description: |
When the Zulip display email address of a user changes,
either due to the user's email address changing, or
due to changes in the organization's
[email address visibility][help-email-visibility].
[help-email-visibility]: /help/restrict-visibility-of-email-addresses).
properties:
user_id:
type: integer
description: |
The ID of the user affected by this change.
new_email:
type: string
description: |
The new email of the user.
additionalProperties: false additionalProperties: false
example: example:
{ {

View File

@ -2133,7 +2133,7 @@ class RealmPropertyActionTest(BaseAction):
private_message_policy=Realm.PRIVATE_MESSAGE_POLICY_TYPES, private_message_policy=Realm.PRIVATE_MESSAGE_POLICY_TYPES,
user_group_edit_policy=Realm.COMMON_POLICY_TYPES, user_group_edit_policy=Realm.COMMON_POLICY_TYPES,
wildcard_mention_policy=Realm.WILDCARD_MENTION_POLICY_TYPES, wildcard_mention_policy=Realm.WILDCARD_MENTION_POLICY_TYPES,
email_address_visibility=[Realm.EMAIL_ADDRESS_VISIBILITY_ADMINS], email_address_visibility=Realm.EMAIL_ADDRESS_VISIBILITY_TYPES,
bot_creation_policy=Realm.BOT_CREATION_POLICY_TYPES, bot_creation_policy=Realm.BOT_CREATION_POLICY_TYPES,
video_chat_provider=[ video_chat_provider=[
Realm.VIDEO_CHAT_PROVIDERS["jitsi_meet"]["id"], Realm.VIDEO_CHAT_PROVIDERS["jitsi_meet"]["id"],
@ -2170,14 +2170,23 @@ class RealmPropertyActionTest(BaseAction):
for count, val in enumerate(vals[1:]): for count, val in enumerate(vals[1:]):
now = timezone_now() now = timezone_now()
state_change_expected = True state_change_expected = True
old_value = vals[count]
num_events = 1
if name == "email_address_visibility" and Realm.EMAIL_ADDRESS_VISIBILITY_EVERYONE in [
old_value,
val,
]:
# email update event is sent for each user.
num_events = 11
events = self.verify_action( events = self.verify_action(
lambda: do_set_realm_property( lambda: do_set_realm_property(
self.user_profile.realm, name, val, acting_user=self.user_profile self.user_profile.realm, name, val, acting_user=self.user_profile
), ),
state_change_expected=state_change_expected, state_change_expected=state_change_expected,
num_events=num_events,
) )
old_value = vals[count]
self.assertEqual( self.assertEqual(
RealmAuditLog.objects.filter( RealmAuditLog.objects.filter(
realm=self.user_profile.realm, realm=self.user_profile.realm,
@ -2196,6 +2205,12 @@ class RealmPropertyActionTest(BaseAction):
) )
check_realm_update("events[0]", events[0], name) check_realm_update("events[0]", events[0], name)
if name == "email_address_visibility" and Realm.EMAIL_ADDRESS_VISIBILITY_EVERYONE in [
old_value,
val,
]:
check_realm_user_update("events[1]", events[1], "email")
def test_change_realm_property(self) -> None: def test_change_realm_property(self) -> None:
for prop in Realm.property_types: for prop in Realm.property_types:
with self.settings(SEND_DIGEST_EMAILS=True): with self.settings(SEND_DIGEST_EMAILS=True):