mirror of https://github.com/zulip/zulip.git
models: Add push_notifications_enabled & corresponding end_timestamp.
Add two fields to Realm model: *push_notifications_enabled *push_notifications_enabled_end_timestamp Co-authored-by: Prakhar Pratyush <prakhar@zulip.com>
This commit is contained in:
parent
6aa911a9b2
commit
f6c7eaf1e5
|
@ -20,6 +20,19 @@ format used by the Zulip server that they are interacting with.
|
|||
|
||||
## Changes in Zulip 8.0
|
||||
|
||||
**Feature level 231**
|
||||
|
||||
* [`POST /register`](/api/register-queue):
|
||||
`realm_push_notifications_enabled` now represents more accurately
|
||||
whether push notifications are actually enabled via the mobile push
|
||||
notifications service. Added
|
||||
`realm_push_notifications_enabled_end_timestamp` field to realm
|
||||
data.
|
||||
|
||||
* [`GET /events`](/api/get-events): A `realm` update event is now sent
|
||||
whenever `push_notifications_enabled` or
|
||||
`push_notifications_enabled_end_timestamp` changes.
|
||||
|
||||
**Feature level 230**
|
||||
|
||||
* [`GET /events`](/api/get-events): Added `has_trigger` field in
|
||||
|
|
|
@ -33,7 +33,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
|
|||
# Changes should be accompanied by documentation explaining what the
|
||||
# new level means in api_docs/changelog.md, as well as "**Changes**"
|
||||
# entries in the endpoint's documentation in `zulip.yaml`.
|
||||
API_FEATURE_LEVEL = 230
|
||||
API_FEATURE_LEVEL = 231
|
||||
|
||||
# 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
|
||||
|
|
|
@ -229,6 +229,7 @@ export function dispatch_normal_event(event) {
|
|||
notifications_stream_id: stream_ui_updates.update_announce_stream_option,
|
||||
org_type: noop,
|
||||
private_message_policy: noop,
|
||||
push_notifications_enabled: noop,
|
||||
send_welcome_emails: noop,
|
||||
message_content_allowed_in_email_notifications: noop,
|
||||
enable_spectator_access: noop,
|
||||
|
|
|
@ -14,6 +14,7 @@ from zerver.actions.realm_settings import (
|
|||
do_deactivate_realm,
|
||||
)
|
||||
from zerver.lib.bulk_create import create_users
|
||||
from zerver.lib.push_notifications import sends_notifications_directly
|
||||
from zerver.lib.remote_server import enqueue_register_realm_with_push_bouncer_if_needed
|
||||
from zerver.lib.server_initialization import create_internal_realm, server_initialized
|
||||
from zerver.lib.streams import ensure_stream, get_signups_stream
|
||||
|
@ -215,6 +216,9 @@ def do_create_realm(
|
|||
kwargs["enable_read_receipts"] = (
|
||||
invite_required is None or invite_required is True or emails_restricted_to_domains
|
||||
)
|
||||
# Initialize this property correctly in the case that no network activity
|
||||
# is required to do so correctly.
|
||||
kwargs["push_notifications_enabled"] = sends_notifications_directly()
|
||||
|
||||
with transaction.atomic():
|
||||
realm = Realm(string_id=string_id, name=name, **kwargs)
|
||||
|
|
|
@ -16,6 +16,7 @@ from zerver.lib.message import parse_message_time_limit_setting, update_first_vi
|
|||
from zerver.lib.retention import move_messages_to_archive
|
||||
from zerver.lib.send_email import FromAddress, send_email_to_admins
|
||||
from zerver.lib.sessions import delete_user_sessions
|
||||
from zerver.lib.timestamp import datetime_to_timestamp, timestamp_to_datetime
|
||||
from zerver.lib.upload import delete_message_attachments
|
||||
from zerver.lib.user_counts import realm_user_count_by_role
|
||||
from zerver.models import (
|
||||
|
@ -102,6 +103,50 @@ def do_set_realm_property(
|
|||
update_users_in_full_members_system_group(realm, acting_user=acting_user)
|
||||
|
||||
|
||||
def do_set_push_notifications_enabled_end_timestamp(
|
||||
realm: Realm, value: Optional[int], *, acting_user: Optional[UserProfile]
|
||||
) -> None:
|
||||
# Variant of do_set_realm_property with a bit of extra complexity
|
||||
# for the fact that we store a datetime object in the database but
|
||||
# use an integer format timestamp in the API.
|
||||
name = "push_notifications_enabled_end_timestamp"
|
||||
old_timestamp = None
|
||||
old_datetime = getattr(realm, name)
|
||||
if old_datetime is not None:
|
||||
old_timestamp = datetime_to_timestamp(old_datetime)
|
||||
|
||||
if old_timestamp == value:
|
||||
return
|
||||
|
||||
with transaction.atomic():
|
||||
new_datetime = None
|
||||
if value is not None:
|
||||
new_datetime = timestamp_to_datetime(value)
|
||||
setattr(realm, name, new_datetime)
|
||||
realm.save(update_fields=[name])
|
||||
|
||||
event_time = timezone_now()
|
||||
RealmAuditLog.objects.create(
|
||||
realm=realm,
|
||||
event_type=RealmAuditLog.REALM_PROPERTY_CHANGED,
|
||||
event_time=event_time,
|
||||
acting_user=acting_user,
|
||||
extra_data={
|
||||
RealmAuditLog.OLD_VALUE: old_timestamp,
|
||||
RealmAuditLog.NEW_VALUE: value,
|
||||
"property": name,
|
||||
},
|
||||
)
|
||||
|
||||
event = dict(
|
||||
type="realm",
|
||||
op="update",
|
||||
property=name,
|
||||
value=value,
|
||||
)
|
||||
send_event(realm, event, active_user_ids(realm.id))
|
||||
|
||||
|
||||
@transaction.atomic(durable=True)
|
||||
def do_change_realm_permission_group_setting(
|
||||
realm: Realm, setting_name: str, user_group: UserGroup, *, acting_user: Optional[UserProfile]
|
||||
|
|
|
@ -39,7 +39,6 @@ from zerver.lib.muted_users import get_user_mutes
|
|||
from zerver.lib.narrow import check_narrow_for_events, read_stop_words
|
||||
from zerver.lib.narrow_helpers import NarrowTerm
|
||||
from zerver.lib.presence import get_presence_for_user, get_presences_for_realm
|
||||
from zerver.lib.push_notifications import push_notifications_configured
|
||||
from zerver.lib.realm_icon import realm_icon_url
|
||||
from zerver.lib.realm_logo import get_realm_logo_source, get_realm_logo_url
|
||||
from zerver.lib.scheduled_messages import get_undelivered_scheduled_messages
|
||||
|
@ -329,6 +328,13 @@ def fetch_initial_state_data(
|
|||
state["zulip_plan_is_not_limited"] = realm.plan_type != Realm.PLAN_TYPE_LIMITED
|
||||
state["upgrade_text_for_wide_organization_logo"] = str(Realm.UPGRADE_TEXT_STANDARD)
|
||||
|
||||
if realm.push_notifications_enabled_end_timestamp is not None:
|
||||
state["realm_push_notifications_enabled_end_timestamp"] = datetime_to_timestamp(
|
||||
realm.push_notifications_enabled_end_timestamp
|
||||
)
|
||||
else:
|
||||
state["realm_push_notifications_enabled_end_timestamp"] = None
|
||||
|
||||
state["password_min_length"] = settings.PASSWORD_MIN_LENGTH
|
||||
state["password_min_guesses"] = settings.PASSWORD_MIN_GUESSES
|
||||
state["server_inline_image_preview"] = settings.INLINE_IMAGE_PREVIEW
|
||||
|
@ -345,8 +351,7 @@ def fetch_initial_state_data(
|
|||
"event_queue_longpoll_timeout_seconds"
|
||||
] = settings.EVENT_QUEUE_LONGPOLL_TIMEOUT_SECONDS
|
||||
|
||||
# TODO: Should these have the realm prefix replaced with server_?
|
||||
state["realm_push_notifications_enabled"] = push_notifications_configured()
|
||||
# TODO: This probably belongs on the server object.
|
||||
state["realm_default_external_accounts"] = get_default_external_accounts()
|
||||
|
||||
server_default_jitsi_server_url = (
|
||||
|
|
|
@ -27,6 +27,7 @@ from zerver.lib.export import DATE_FIELDS, Field, Path, Record, TableData, Table
|
|||
from zerver.lib.markdown import markdown_convert
|
||||
from zerver.lib.markdown import version as markdown_version
|
||||
from zerver.lib.message import get_last_message_id
|
||||
from zerver.lib.push_notifications import sends_notifications_directly
|
||||
from zerver.lib.remote_server import enqueue_register_realm_with_push_bouncer_if_needed
|
||||
from zerver.lib.server_initialization import create_internal_realm, server_initialized
|
||||
from zerver.lib.streams import render_stream_description
|
||||
|
@ -974,6 +975,9 @@ def do_import_realm(import_dir: Path, subdomain: str, processes: int = 1) -> Rea
|
|||
realm_properties = dict(**data["zerver_realm"][0])
|
||||
realm_properties["deactivated"] = True
|
||||
|
||||
# Initialize whether we expect push notifications to work.
|
||||
realm_properties["push_notifications_enabled"] = sends_notifications_directly()
|
||||
|
||||
with transaction.atomic(durable=True):
|
||||
realm = Realm(**realm_properties)
|
||||
if "zerver_usergroup" not in data:
|
||||
|
|
|
@ -33,12 +33,20 @@ from django.utils.translation import override as override_language
|
|||
from typing_extensions import TypeAlias, override
|
||||
|
||||
from analytics.lib.counts import COUNT_STATS, do_increment_logging_stat
|
||||
from zerver.actions.realm_settings import (
|
||||
do_set_push_notifications_enabled_end_timestamp,
|
||||
do_set_realm_property,
|
||||
)
|
||||
from zerver.lib.avatar import absolute_avatar_url
|
||||
from zerver.lib.emoji_utils import hex_codepoint_to_emoji
|
||||
from zerver.lib.exceptions import ErrorCode, JsonableError
|
||||
from zerver.lib.message import access_message, huddle_users
|
||||
from zerver.lib.outgoing_http import OutgoingSession
|
||||
from zerver.lib.remote_server import send_json_to_push_bouncer, send_to_push_bouncer
|
||||
from zerver.lib.remote_server import (
|
||||
send_json_to_push_bouncer,
|
||||
send_realms_only_to_push_bouncer,
|
||||
send_to_push_bouncer,
|
||||
)
|
||||
from zerver.lib.soft_deactivation import soft_reactivate_if_personal_notification
|
||||
from zerver.lib.tex import change_katex_to_raw_latex
|
||||
from zerver.lib.timestamp import datetime_to_timestamp
|
||||
|
@ -48,6 +56,7 @@ from zerver.models import (
|
|||
Message,
|
||||
NotificationTriggers,
|
||||
PushDeviceToken,
|
||||
Realm,
|
||||
Recipient,
|
||||
Stream,
|
||||
UserGroup,
|
||||
|
@ -565,6 +574,10 @@ def uses_notification_bouncer() -> bool:
|
|||
return settings.PUSH_NOTIFICATION_BOUNCER_URL is not None
|
||||
|
||||
|
||||
def sends_notifications_directly() -> bool:
|
||||
return has_apns_credentials() and has_gcm_credentials() and not uses_notification_bouncer()
|
||||
|
||||
|
||||
def send_notifications_to_bouncer(
|
||||
user_profile: UserProfile,
|
||||
apns_payload: Dict[str, Any],
|
||||
|
@ -736,15 +749,70 @@ def push_notifications_configured() -> bool:
|
|||
|
||||
|
||||
def initialize_push_notifications() -> None:
|
||||
if not push_notifications_configured():
|
||||
if settings.DEVELOPMENT and not settings.TEST_SUITE: # nocoverage
|
||||
# Avoid unnecessary spam on development environment startup
|
||||
"""Called during startup of the push notifications worker to check
|
||||
whether we expect mobile push notifications to work on this server
|
||||
and update state accordingly.
|
||||
"""
|
||||
|
||||
if sends_notifications_directly():
|
||||
# This server sends push notifications directly. Make sure we
|
||||
# are set to report to clients that push notifications are
|
||||
# enabled.
|
||||
for realm in Realm.objects.filter(push_notifications_enabled=False):
|
||||
do_set_realm_property(realm, "push_notifications_enabled", True, acting_user=None)
|
||||
do_set_push_notifications_enabled_end_timestamp(realm, None, acting_user=None)
|
||||
return
|
||||
|
||||
if not push_notifications_configured():
|
||||
for realm in Realm.objects.filter(push_notifications_enabled=True):
|
||||
do_set_realm_property(realm, "push_notifications_enabled", False, acting_user=None)
|
||||
do_set_push_notifications_enabled_end_timestamp(realm, None, acting_user=None)
|
||||
if settings.DEVELOPMENT and not settings.TEST_SUITE:
|
||||
# Avoid unnecessary spam on development environment startup
|
||||
return # nocoverage
|
||||
logger.warning(
|
||||
"Mobile push notifications are not configured.\n "
|
||||
"See https://zulip.readthedocs.io/en/latest/"
|
||||
"production/mobile-push-notifications.html"
|
||||
)
|
||||
return
|
||||
|
||||
if uses_notification_bouncer():
|
||||
# If we're using the notification bouncer, check if we can
|
||||
# actually send push notifications.
|
||||
|
||||
try:
|
||||
realms = send_realms_only_to_push_bouncer()
|
||||
except Exception:
|
||||
# An exception was thrown trying to ask the bouncer service whether we can send
|
||||
# push notifications or not. There may be certain transient failures that we could
|
||||
# ignore here, but the default explanation is that there is something wrong either
|
||||
# with our credentials being corrupted or our ability to reach the bouncer service
|
||||
# over the network, so we immediately move to reporting push notifications as likely not working,
|
||||
# as whatever failed here is likely to also fail when trying to send a push notification.
|
||||
for realm in Realm.objects.filter(push_notifications_enabled=True):
|
||||
do_set_realm_property(realm, "push_notifications_enabled", False, acting_user=None)
|
||||
do_set_push_notifications_enabled_end_timestamp(realm, None, acting_user=None)
|
||||
logger.exception("Exception while sending realms only data to push bouncer")
|
||||
return
|
||||
|
||||
for realm_uuid, data in realms.items():
|
||||
realm = Realm.objects.get(uuid=realm_uuid)
|
||||
do_set_realm_property(
|
||||
realm, "push_notifications_enabled", data["can_push"], acting_user=None
|
||||
)
|
||||
do_set_push_notifications_enabled_end_timestamp(
|
||||
realm, data["expected_end_timestamp"], acting_user=None
|
||||
)
|
||||
return
|
||||
|
||||
logger.warning( # nocoverage
|
||||
"Mobile push notifications are not fully configured.\n "
|
||||
"See https://zulip.readthedocs.io/en/latest/production/mobile-push-notifications.html"
|
||||
)
|
||||
for realm in Realm.objects.filter(push_notifications_enabled=True): # nocoverage
|
||||
do_set_realm_property(realm, "push_notifications_enabled", False, acting_user=None)
|
||||
do_set_push_notifications_enabled_end_timestamp(realm, None, acting_user=None)
|
||||
|
||||
|
||||
def get_mobile_push_content(rendered_content: str) -> str:
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# Generated by Django 4.2.7 on 2023-11-28 14:04
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("zerver", "0491_alter_realmuserdefault_web_home_view_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="realm",
|
||||
name="push_notifications_enabled",
|
||||
field=models.BooleanField(db_index=True, default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="realm",
|
||||
name="push_notifications_enabled_end_timestamp",
|
||||
field=models.DateTimeField(default=None, null=True),
|
||||
),
|
||||
]
|
|
@ -344,6 +344,11 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
|
|||
# bouncer.
|
||||
uuid = models.UUIDField(default=uuid4, unique=True)
|
||||
uuid_owner_secret = models.TextField(default=generate_realm_uuid_owner_secret)
|
||||
# Whether push notifications are working for this realm, and
|
||||
# whether there is a specific date at which we expect that to
|
||||
# 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)
|
||||
|
||||
date_created = models.DateTimeField(default=timezone_now)
|
||||
demo_organization_scheduled_deletion_date = models.DateTimeField(default=None, null=True)
|
||||
|
@ -829,6 +834,7 @@ class Realm(models.Model): # type: ignore[django-manager-missing] # django-stub
|
|||
name=str,
|
||||
name_changes_disabled=bool,
|
||||
private_message_policy=int,
|
||||
push_notifications_enabled=bool,
|
||||
send_welcome_emails=bool,
|
||||
user_group_edit_policy=int,
|
||||
video_chat_provider=int,
|
||||
|
|
|
@ -4581,6 +4581,27 @@ paths:
|
|||
system group.
|
||||
|
||||
**Changes**: New in Zulip 8.0 (feature level 225).
|
||||
push_notifications_enabled:
|
||||
type: boolean
|
||||
description: |
|
||||
Whether push notifications are enabled for this organization. Typically
|
||||
`true` for Zulip Cloud and self-hosted realms that have a valid
|
||||
registration for the [Mobile push notifications
|
||||
service](https://zulip.readthedocs.io/en/latest/production/mobile-push-notifications.html),
|
||||
and `false` for self-hosted servers that do not.
|
||||
|
||||
**Changes**: New in Zulip 8.0 (feature level 231).
|
||||
Previously, this value was never updated via events.
|
||||
push_notifications_enabled_end_timestamp:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: |
|
||||
If the server expects the realm's push notifications access to end at a
|
||||
definite time in the future, the time at which this is expected to happen.
|
||||
Mobile clients should use this field to display warnings to users when the
|
||||
indicated timestamp is near.
|
||||
|
||||
**Changes**: New in Zulip 8.0 (feature level 231).
|
||||
additionalProperties: false
|
||||
example:
|
||||
{
|
||||
|
@ -14425,8 +14446,26 @@ paths:
|
|||
Present if `realm` is present in `fetch_event_types`.
|
||||
|
||||
Whether push notifications are enabled for this organization. Typically
|
||||
`false` for self-hosted servers that have not configured the
|
||||
[Mobile push notifications service](https://zulip.readthedocs.io/en/latest/production/mobile-push-notifications.html).
|
||||
`true` for Zulip Cloud and self-hosted realms that have a valid
|
||||
registration for the [Mobile push notifications
|
||||
service](https://zulip.readthedocs.io/en/latest/production/mobile-push-notifications.html),
|
||||
and `false` for self-hosted servers that do not.
|
||||
|
||||
**Changes**: Before Zulip 8.0 (feature level 231), this incorrectly was
|
||||
`true` for servers that were partly configured to use the Mobile Push
|
||||
Notifications Service but not properly registered.
|
||||
realm_push_notifications_enabled_end_timestamp:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: |
|
||||
Present if `realm` is present in `fetch_event_types`.
|
||||
|
||||
If the server expects the realm's push notifications access to end at a
|
||||
definite time in the future, the time at which this is expected to happen.
|
||||
Mobile clients should use this field to display warnings to users when the
|
||||
indicated timestamp is near.
|
||||
|
||||
**Changes**: New in Zulip 8.0 (feature level 231).
|
||||
realm_upload_quota_mib:
|
||||
type: integer
|
||||
nullable: true
|
||||
|
|
|
@ -76,6 +76,7 @@ from zerver.actions.realm_settings import (
|
|||
do_change_realm_permission_group_setting,
|
||||
do_change_realm_plan_type,
|
||||
do_deactivate_realm,
|
||||
do_set_push_notifications_enabled_end_timestamp,
|
||||
do_set_realm_authentication_methods,
|
||||
do_set_realm_notifications_stream,
|
||||
do_set_realm_property,
|
||||
|
@ -216,7 +217,7 @@ from zerver.lib.test_helpers import (
|
|||
reset_email_visibility_to_everyone_in_zulip_realm,
|
||||
stdout_suppressed,
|
||||
)
|
||||
from zerver.lib.timestamp import convert_to_UTC
|
||||
from zerver.lib.timestamp import convert_to_UTC, datetime_to_timestamp
|
||||
from zerver.lib.topic import TOPIC_NAME
|
||||
from zerver.lib.types import ProfileDataElementUpdateDict
|
||||
from zerver.models import (
|
||||
|
@ -3660,6 +3661,58 @@ class RealmPropertyActionTest(BaseAction):
|
|||
continue
|
||||
self.do_set_realm_user_default_setting_test(prop)
|
||||
|
||||
def test_do_set_push_notifications_enabled_end_timestamp(self) -> None:
|
||||
realm = self.user_profile.realm
|
||||
|
||||
# Default value of 'push_notifications_enabled_end_timestamp' is None.
|
||||
# Verify that no event is sent when the new value is the same as existing value.
|
||||
new_timestamp = None
|
||||
self.verify_action(
|
||||
lambda: do_set_push_notifications_enabled_end_timestamp(
|
||||
realm=realm,
|
||||
value=new_timestamp,
|
||||
acting_user=None,
|
||||
),
|
||||
state_change_expected=False,
|
||||
num_events=0,
|
||||
)
|
||||
|
||||
old_datetime = timezone_now() - datetime.timedelta(days=3)
|
||||
old_timestamp = datetime_to_timestamp(old_datetime)
|
||||
now = timezone_now()
|
||||
timestamp_now = datetime_to_timestamp(now)
|
||||
|
||||
realm.push_notifications_enabled_end_timestamp = old_datetime
|
||||
realm.save(update_fields=["push_notifications_enabled_end_timestamp"])
|
||||
|
||||
event = self.verify_action(
|
||||
lambda: do_set_push_notifications_enabled_end_timestamp(
|
||||
realm=realm,
|
||||
value=timestamp_now,
|
||||
acting_user=None,
|
||||
),
|
||||
state_change_expected=True,
|
||||
num_events=1,
|
||||
)[0]
|
||||
self.assertEqual(event["type"], "realm")
|
||||
self.assertEqual(event["op"], "update")
|
||||
self.assertEqual(event["property"], "push_notifications_enabled_end_timestamp")
|
||||
self.assertEqual(event["value"], timestamp_now)
|
||||
|
||||
self.assertEqual(
|
||||
RealmAuditLog.objects.filter(
|
||||
realm=realm,
|
||||
event_type=RealmAuditLog.REALM_PROPERTY_CHANGED,
|
||||
acting_user=None,
|
||||
extra_data={
|
||||
RealmAuditLog.OLD_VALUE: old_timestamp,
|
||||
RealmAuditLog.NEW_VALUE: timestamp_now,
|
||||
"property": "push_notifications_enabled_end_timestamp",
|
||||
},
|
||||
).count(),
|
||||
1,
|
||||
)
|
||||
|
||||
|
||||
class UserDisplayActionTest(BaseAction):
|
||||
def do_change_user_settings_test(self, setting_name: str) -> None:
|
||||
|
|
|
@ -24,6 +24,7 @@ from zerver.lib.home import (
|
|||
from zerver.lib.soft_deactivation import do_soft_deactivate_users
|
||||
from zerver.lib.test_classes import ZulipTestCase
|
||||
from zerver.lib.test_helpers import get_user_messages, queries_captured
|
||||
from zerver.lib.timestamp import datetime_to_timestamp
|
||||
from zerver.models import (
|
||||
DefaultStream,
|
||||
Draft,
|
||||
|
@ -178,6 +179,7 @@ class HomeTest(ZulipTestCase):
|
|||
"realm_presence_disabled",
|
||||
"realm_private_message_policy",
|
||||
"realm_push_notifications_enabled",
|
||||
"realm_push_notifications_enabled_end_timestamp",
|
||||
"realm_send_welcome_emails",
|
||||
"realm_signup_notifications_stream_id",
|
||||
"realm_upload_quota_mib",
|
||||
|
@ -1278,3 +1280,17 @@ class HomeTest(ZulipTestCase):
|
|||
# +2 for what's already in the test DB.
|
||||
for draft in page_params["drafts"]:
|
||||
self.assertNotEqual(draft["timestamp"], base_time)
|
||||
|
||||
def test_realm_push_notifications_enabled_end_timestamp(self) -> None:
|
||||
self.login("hamlet")
|
||||
realm = get_realm("zulip")
|
||||
end_timestamp = timezone_now() + datetime.timedelta(days=1)
|
||||
realm.push_notifications_enabled_end_timestamp = end_timestamp
|
||||
realm.save()
|
||||
|
||||
result = self._get_home_page(stream="Denmark")
|
||||
page_params = self._get_page_params(result)
|
||||
self.assertEqual(
|
||||
page_params["realm_push_notifications_enabled_end_timestamp"],
|
||||
datetime_to_timestamp(end_timestamp),
|
||||
)
|
||||
|
|
|
@ -737,6 +737,65 @@ class PushBouncerNotificationTest(BouncerTestCase):
|
|||
result = self.uuid_post(self.server_uuid, endpoint, payload)
|
||||
self.assert_json_error(result, "Invalid APNS token")
|
||||
|
||||
def test_initialize_push_notifications(self) -> None:
|
||||
realm = get_realm("zulip")
|
||||
realm.push_notifications_enabled = False
|
||||
realm.save()
|
||||
|
||||
from zerver.lib.push_notifications import initialize_push_notifications
|
||||
|
||||
with mock.patch(
|
||||
"zerver.lib.push_notifications.sends_notifications_directly", return_value=True
|
||||
):
|
||||
initialize_push_notifications()
|
||||
|
||||
realm = get_realm("zulip")
|
||||
self.assertTrue(realm.push_notifications_enabled)
|
||||
|
||||
with mock.patch(
|
||||
"zerver.lib.push_notifications.push_notifications_configured", return_value=False
|
||||
), self.assertLogs("zerver.lib.push_notifications", level="WARNING") as warn_log:
|
||||
initialize_push_notifications()
|
||||
|
||||
not_configured_warn_log = (
|
||||
"WARNING:zerver.lib.push_notifications:"
|
||||
"Mobile push notifications are not configured.\n "
|
||||
"See https://zulip.readthedocs.io/en/latest/production/mobile-push-notifications.html"
|
||||
)
|
||||
realm = get_realm("zulip")
|
||||
self.assertFalse(realm.push_notifications_enabled)
|
||||
self.assertEqual(
|
||||
warn_log.output[0],
|
||||
not_configured_warn_log,
|
||||
)
|
||||
|
||||
with mock.patch(
|
||||
"zerver.lib.push_notifications.uses_notification_bouncer", return_value=True
|
||||
):
|
||||
realms_response = {realm.uuid: {"can_push": True, "expected_end_timestamp": None}}
|
||||
with mock.patch(
|
||||
"zerver.lib.push_notifications.send_realms_only_to_push_bouncer",
|
||||
return_value=realms_response,
|
||||
):
|
||||
initialize_push_notifications()
|
||||
|
||||
realm = get_realm("zulip")
|
||||
self.assertTrue(realm.push_notifications_enabled)
|
||||
self.assertEqual(realm.push_notifications_enabled_end_timestamp, None)
|
||||
|
||||
with mock.patch(
|
||||
"zerver.lib.push_notifications.send_realms_only_to_push_bouncer",
|
||||
side_effect=Exception,
|
||||
), self.assertLogs("zerver.lib.push_notifications", level="ERROR") as exception_log:
|
||||
initialize_push_notifications()
|
||||
|
||||
realm = get_realm("zulip")
|
||||
self.assertFalse(realm.push_notifications_enabled)
|
||||
self.assertIn(
|
||||
"ERROR:zerver.lib.push_notifications:Exception while sending realms only data to push bouncer",
|
||||
exception_log.output[0],
|
||||
)
|
||||
|
||||
@override_settings(PUSH_NOTIFICATION_BOUNCER_URL="https://push.zulip.org.example.com")
|
||||
@responses.activate
|
||||
def test_register_token_realm_uuid_belongs_to_different_server(self) -> None:
|
||||
|
|
|
@ -1360,6 +1360,8 @@ class RealmAPITest(ZulipTestCase):
|
|||
|
||||
def test_update_realm_properties(self) -> None:
|
||||
for prop in Realm.property_types:
|
||||
# push_notifications_enabled is maintained by the server, not via the API.
|
||||
if prop != "push_notifications_enabled":
|
||||
with self.subTest(property=prop):
|
||||
self.do_test_realm_update_api(prop)
|
||||
|
||||
|
|
|
@ -105,6 +105,8 @@ def update_realm(
|
|||
authentication_methods: Optional[Dict[str, Any]] = REQ(
|
||||
json_validator=check_dict([]), default=None
|
||||
),
|
||||
# Note: push_notifications_enabled and push_notifications_enabled_end_timestamp
|
||||
# are not offered here as it is maintained by the server, not via the API.
|
||||
notifications_stream_id: Optional[int] = REQ(json_validator=check_int, default=None),
|
||||
signup_notifications_stream_id: Optional[int] = REQ(json_validator=check_int, default=None),
|
||||
message_retention_days_raw: Optional[Union[int, str]] = REQ(
|
||||
|
|
Loading…
Reference in New Issue