settings: Add require_e2ee_push_notifications realm setting.

This commit adds a realm setting:
"Require end-to-end encryption for push notification content".

This commit just involves backend & UI changes to add the setting,
the impact of this setting is in the next commit.

Fixes part of #35370.
This commit is contained in:
Prakhar Pratyush
2025-07-24 18:50:54 +05:30
committed by Tim Abbott
parent d46b1a0ac9
commit fc6cd9a966
11 changed files with 116 additions and 1 deletions

View File

@@ -20,6 +20,12 @@ format used by the Zulip server that they are interacting with.
## Changes in Zulip 11.0
**Feature level 409**
* `PATCH /realm`, [`POST /register`](/api/register-queue),
[`GET /events`](/api/get-events): Added a new
`require_e2ee_push_notifications` realm setting.
**Feature level 407**
* [`GET /users/me/subscriptions`](/api/get-subscriptions),

View File

@@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
# new level means in api_docs/changelog.md, as well as "**Changes**"
# entries in the endpoint's documentation in `zulip.yaml`.
API_FEATURE_LEVEL = 408
API_FEATURE_LEVEL = 409
# Bump the minor PROVISION_VERSION to indicate that folks should provision
# only when going from an old version of the code to a newer version. Bump

View File

@@ -41,6 +41,9 @@ const admin_settings_label = {
}),
realm_inline_url_embed_preview: $t({defaultMessage: "Show previews of linked websites"}),
realm_send_welcome_emails: $t({defaultMessage: "Send emails introducing Zulip to new users"}),
realm_require_e2ee_push_notifications: $t({
defaultMessage: "Require end-to-end encryption for push notification content",
}),
realm_message_content_allowed_in_email_notifications: $t({
defaultMessage: "Allow message content in message notification emails",
}),
@@ -194,6 +197,7 @@ export function build_page(): void {
realm_topics_policy_values: settings_config.get_realm_topics_policy_values(),
empty_string_topic_display_name: util.get_final_topic_display_name(""),
realm_send_welcome_emails: realm.realm_send_welcome_emails,
realm_require_e2ee_push_notifications: realm.realm_require_e2ee_push_notifications,
realm_message_content_allowed_in_email_notifications:
realm.realm_message_content_allowed_in_email_notifications,
realm_enable_spectator_access: realm.realm_enable_spectator_access,

View File

@@ -289,6 +289,7 @@ export function dispatch_normal_event(event) {
require_unique_names: noop,
send_welcome_emails: noop,
topics_policy: noop,
require_e2ee_push_notifications: noop,
message_content_allowed_in_email_notifications: noop,
enable_spectator_access: noop,
signup_announcements_stream_id: noop,

View File

@@ -426,6 +426,7 @@ export const realm_schema = z.object({
realm_presence_disabled: z.boolean(),
realm_push_notifications_enabled: z.boolean(),
realm_push_notifications_enabled_end_timestamp: z.nullable(z.number()),
realm_require_e2ee_push_notifications: z.boolean(),
realm_require_unique_names: z.boolean(),
realm_send_welcome_emails: z.boolean(),
realm_signup_announcements_stream_id: z.number(),

View File

@@ -70,6 +70,13 @@
{{> settings_save_discard_widget section_name="notifications-security" }}
</div>
<div class="inline-block organization-settings-parent">
{{> settings_checkbox
setting_name="realm_require_e2ee_push_notifications"
prefix="id_"
is_checked=realm_require_e2ee_push_notifications
label=admin_settings_label.realm_require_e2ee_push_notifications
help_link="/help/mobile-notifications"}}
{{> settings_checkbox
setting_name="realm_message_content_allowed_in_email_notifications"
prefix="id_"

View File

@@ -0,0 +1,38 @@
# Generated by Django 5.2.4 on 2025-07-28 18:58
from django.conf import settings
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.migrations.state import StateApps
def update_require_e2ee_push_notifications(
apps: StateApps, schema_editor: BaseDatabaseSchemaEditor
) -> None:
Realm = apps.get_model("zerver", "Realm")
# We use 'getattr' with a default value to allow this migration
# to run in development environment when PUSH_NOTIFICATION_REDACT_CONTENT
# setting is removed in the future.
require_e2ee = getattr(settings, "PUSH_NOTIFICATION_REDACT_CONTENT", False)
if require_e2ee:
Realm.objects.update(require_e2ee_push_notifications=require_e2ee)
class Migration(migrations.Migration):
dependencies = [
("zerver", "0742_usermessage_zerver_usermessage_is_private_unread_message_id"),
]
operations = [
migrations.AddField(
model_name="realm",
name="require_e2ee_push_notifications",
field=models.BooleanField(db_default=False, default=False),
),
migrations.RunPython(
update_require_e2ee_push_notifications,
elidable=True,
reverse_code=migrations.RunPython.noop,
),
]

View File

@@ -191,6 +191,7 @@ class Realm(models.Model):
# cease to be the case.
push_notifications_enabled = models.BooleanField(default=False, db_index=True)
push_notifications_enabled_end_timestamp = models.DateTimeField(default=None, null=True)
require_e2ee_push_notifications = models.BooleanField(default=False, db_default=False)
date_created = models.DateTimeField(default=timezone_now)
scheduled_deletion_date = models.DateTimeField(default=None, db_index=True, null=True)
@@ -726,6 +727,7 @@ class Realm(models.Model):
name=str,
name_changes_disabled=bool,
push_notifications_enabled=bool,
require_e2ee_push_notifications=bool,
require_unique_names=bool,
send_welcome_emails=bool,
topics_policy=RealmTopicsPolicyEnum,

View File

@@ -5402,6 +5402,32 @@ paths:
indicated timestamp is near.
**Changes**: New in Zulip 8.0 (feature level 231).
require_e2ee_push_notifications:
type: boolean
description: |
Whether this realm is configured to disallow sending mobile
push notifications with message content through the legacy
mobile push notifications APIs. The new API uses end-to-end
encryption to protect message content and metadata from
being accessible to the push bouncer service, APNs, and
FCM. Clients that support the new E2EE API will use it
automatically regardless of this setting.
If `true`, mobile push notifications sent to clients that
lack support for E2EE push notifications will always have
"New message" as their content. Note that these legacy
mobile notifications will still contain metadata, which may
include the message's ID, the sender's name, email address,
and avatar.
In a future release, once the official mobile apps have
implemented fully validated their E2EE protocol support,
this setting will become strict, and disable the legacy
protocol entirely.
**Changes**: New in Zulip 11.0 (feature level 409). Previously,
this behavior was available only via the
`PUSH_NOTIFICATION_REDACT_CONTENT` global server setting.
require_unique_names:
type: boolean
description: |
@@ -18953,6 +18979,34 @@ paths:
Present if `realm` is present in `fetch_event_types`.
The name of the organization, used in login pages etc.
realm_require_e2ee_push_notifications:
type: boolean
description: |
Present if `realm` is present in `fetch_event_types`.
Whether this realm is configured to disallow sending mobile
push notifications with message content through the legacy
mobile push notifications APIs. The new API uses end-to-end
encryption to protect message content and metadata from
being accessible to the push bouncer service, APNs, and
FCM. Clients that support the new E2EE API will use it
automatically regardless of this setting.
If `true`, mobile push notifications sent to clients that
lack support for E2EE push notifications will always have
"New message" as their content. Note that these legacy
mobile notifications will still contain metadata, which may
include the message's ID, the sender's name, email address,
and avatar.
In a future release, once the official mobile apps have
implemented fully validated their E2EE protocol support,
this setting will become strict, and disable the legacy
protocol entirely.
**Changes**: New in Zulip 11.0 (feature level 409). Previously,
this behavior was available only via the
`PUSH_NOTIFICATION_REDACT_CONTENT` global server setting.
realm_require_unique_names:
type: boolean
description: |

View File

@@ -208,6 +208,7 @@ class HomeTest(ZulipTestCase):
"realm_presence_disabled",
"realm_push_notifications_enabled",
"realm_push_notifications_enabled_end_timestamp",
"realm_require_e2ee_push_notifications",
"realm_require_unique_names",
"realm_send_welcome_emails",
"realm_signup_announcements_stream_id",

View File

@@ -178,6 +178,7 @@ def update_realm(
name_changes_disabled: Json[bool] | None = None,
new_stream_announcements_stream_id: Json[int] | None = None,
org_type: Json[OrgTypeEnum] | None = None,
require_e2ee_push_notifications: Json[bool] | None = None,
require_unique_names: Json[bool] | None = None,
send_welcome_emails: Json[bool] | None = None,
signup_announcements_stream_id: Json[int] | None = None,