From eedd832ca9a544f24a63f5eca4aa0777e966f8ce Mon Sep 17 00:00:00 2001 From: Sahil Batra Date: Mon, 4 Oct 2021 22:22:57 +0530 Subject: [PATCH] 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. --- zerver/lib/event_schema.py | 6 ++++++ zerver/lib/events.py | 5 +++++ zerver/openapi/zulip.yaml | 18 ++++++++++++++++++ zerver/tests/test_events.py | 19 +++++++++++++++++-- 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/zerver/lib/event_schema.py b/zerver/lib/event_schema.py index 892ddee390..84fd284084 100644 --- a/zerver/lib/event_schema.py +++ b/zerver/lib/event_schema.py @@ -1130,6 +1130,12 @@ realm_user_person_types = dict( ("delivery_email", str), ], ), + email=DictType( + required_keys=[ + ("user_id", int), + ("new_email", str), + ], + ), full_name=DictType( required_keys=[ # vertical formatting diff --git a/zerver/lib/events.py b/zerver/lib/events.py index 678f209591..004ee3a38a 100644 --- a/zerver/lib/events.py +++ b/zerver/lib/events.py @@ -787,6 +787,9 @@ def apply_event( if field in person and field in state: state[field] = person[field] + if "new_email" in person: + state["email"] = person["new_email"] + # In the unlikely event that the current user # just changed to/from being an admin, we need # to add/remove the data on all bots in the @@ -832,6 +835,8 @@ def apply_event( p["profile_data"][str(custom_field_id)] = { "value": custom_field_new_value, } + if "new_email" in person: + p["email"] = person["new_email"] else: raise AssertionError("Unexpected event type {type}/{op}".format(**event)) elif event["type"] == "realm_bot": diff --git a/zerver/openapi/zulip.yaml b/zerver/openapi/zulip.yaml index 3ea8929cee..5414a79443 100644 --- a/zerver/openapi/zulip.yaml +++ b/zerver/openapi/zulip.yaml @@ -549,6 +549,24 @@ paths: This user-generated HTML content should be rendered using the same CSS and client-side security protections 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 example: { diff --git a/zerver/tests/test_events.py b/zerver/tests/test_events.py index d45f65a9fd..dff7a7a96c 100644 --- a/zerver/tests/test_events.py +++ b/zerver/tests/test_events.py @@ -2133,7 +2133,7 @@ class RealmPropertyActionTest(BaseAction): private_message_policy=Realm.PRIVATE_MESSAGE_POLICY_TYPES, user_group_edit_policy=Realm.COMMON_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, video_chat_provider=[ Realm.VIDEO_CHAT_PROVIDERS["jitsi_meet"]["id"], @@ -2170,14 +2170,23 @@ class RealmPropertyActionTest(BaseAction): for count, val in enumerate(vals[1:]): now = timezone_now() 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( lambda: do_set_realm_property( self.user_profile.realm, name, val, acting_user=self.user_profile ), state_change_expected=state_change_expected, + num_events=num_events, ) - old_value = vals[count] self.assertEqual( RealmAuditLog.objects.filter( realm=self.user_profile.realm, @@ -2196,6 +2205,12 @@ class RealmPropertyActionTest(BaseAction): ) 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: for prop in Realm.property_types: with self.settings(SEND_DIGEST_EMAILS=True):