push notifs: Add a diagnostic in API of whether push notifs enabled.

When the answer is False, this will allow the mobile app to show a
warning that push notifications will not work and the server admin
should set them up.

Based partly on Kunal's PR #7810.  Provides the necessary backend API
for zulip/zulip-mobile#1507.
This commit is contained in:
Greg Price
2018-02-12 14:34:59 -08:00
parent cc1d64edf8
commit ecbc72b857
4 changed files with 28 additions and 0 deletions

View File

@@ -69,6 +69,10 @@ def get_apns_client() -> APNsClient:
_apns_client_initialized = True _apns_client_initialized = True
return _apns_client return _apns_client
def apns_enabled() -> bool:
client = get_apns_client()
return client is not None
def modernize_apns_payload(data: Dict[str, Any]) -> Dict[str, Any]: def modernize_apns_payload(data: Dict[str, Any]) -> Dict[str, Any]:
'''Take a payload in an unknown Zulip version's format, and return in current format.''' '''Take a payload in an unknown Zulip version's format, and return in current format.'''
# TODO this isn't super robust as is -- if a buggy remote server # TODO this isn't super robust as is -- if a buggy remote server
@@ -148,6 +152,9 @@ if settings.ANDROID_GCM_API_KEY: # nocoverage
else: else:
gcm = None gcm = None
def gcm_enabled() -> bool: # nocoverage
return gcm is not None
def send_android_push_notification_to_user(user_profile: UserProfile, data: Dict[str, Any]) -> None: def send_android_push_notification_to_user(user_profile: UserProfile, data: Dict[str, Any]) -> None:
devices = list(PushDeviceToken.objects.filter(user=user_profile, devices = list(PushDeviceToken.objects.filter(user=user_profile,
kind=PushDeviceToken.GCM)) kind=PushDeviceToken.GCM))
@@ -387,6 +394,22 @@ def remove_push_device_token(user_profile: UserProfile, token_str: bytes, kind:
# Push notifications in general # Push notifications in general
# #
def push_notifications_enabled() -> bool:
'''True just if this server has configured a way to send push notifications.'''
if (uses_notification_bouncer()
and settings.ZULIP_ORG_KEY is not None
and settings.ZULIP_ORG_ID is not None): # nocoverage
# We have the needed configuration to send push notifications through
# the bouncer. Better yet would be to confirm that this config actually
# works -- e.g., that we have ever successfully sent to the bouncer --
# but this is a good start.
return True
if apns_enabled() and gcm_enabled(): # nocoverage
# We have the needed configuration to send through APNs and GCM directly
# (i.e., we are the bouncer, presumably.) Again, assume it actually works.
return True
return False
def get_alert_from_message(message: Message) -> Text: def get_alert_from_message(message: Message) -> Text:
""" """
Determine what alert string to display based on the missed messages. Determine what alert string to display based on the missed messages.

View File

@@ -1326,6 +1326,7 @@ class FetchAuthBackends(ZulipTestCase):
('require_email_format_usernames', check_bool), ('require_email_format_usernames', check_bool),
('realm_uri', check_string), ('realm_uri', check_string),
('zulip_version', check_string), ('zulip_version', check_string),
('push_notifications_enabled', check_bool),
('msg', check_string), ('msg', check_string),
('result', check_string), ('result', check_string),
] + extra_fields) ] + extra_fields)

View File

@@ -566,6 +566,8 @@ class TestAPNs(PushNotificationTest):
self.user_profile.id, devices, payload_data) self.user_profile.id, devices, payload_data)
def test_get_apns_client(self) -> None: def test_get_apns_client(self) -> None:
import zerver.lib.push_notifications
zerver.lib.push_notifications._apns_client_initialized = False
with self.settings(APNS_CERT_FILE='/foo.pem'), \ with self.settings(APNS_CERT_FILE='/foo.pem'), \
mock.patch('zerver.lib.push_notifications.APNsClient') as mock_client: mock.patch('zerver.lib.push_notifications.APNsClient') as mock_client:
client = get_apns_client() client = get_apns_client()

View File

@@ -25,6 +25,7 @@ from zerver.context_processors import zulip_default_context, get_realm_from_requ
from zerver.forms import HomepageForm, OurAuthenticationForm, \ from zerver.forms import HomepageForm, OurAuthenticationForm, \
WRONG_SUBDOMAIN_ERROR, ZulipPasswordResetForm WRONG_SUBDOMAIN_ERROR, ZulipPasswordResetForm
from zerver.lib.mobile_auth_otp import is_valid_otp, otp_encrypt_api_key from zerver.lib.mobile_auth_otp import is_valid_otp, otp_encrypt_api_key
from zerver.lib.push_notifications import push_notifications_enabled
from zerver.lib.request import REQ, has_request_variables, JsonableError from zerver.lib.request import REQ, has_request_variables, JsonableError
from zerver.lib.response import json_success, json_error from zerver.lib.response import json_success, json_error
from zerver.lib.subdomains import get_subdomain, is_subdomain_root_or_alias from zerver.lib.subdomains import get_subdomain, is_subdomain_root_or_alias
@@ -713,6 +714,7 @@ def api_get_server_settings(request: HttpRequest) -> HttpResponse:
result = dict( result = dict(
authentication_methods=get_auth_backends_data(request), authentication_methods=get_auth_backends_data(request),
zulip_version=ZULIP_VERSION, zulip_version=ZULIP_VERSION,
push_notifications_enabled=push_notifications_enabled(),
) )
context = zulip_default_context(request) context = zulip_default_context(request)
# IMPORTANT NOTE: # IMPORTANT NOTE: