diff --git a/zerver/lib/push_notifications.py b/zerver/lib/push_notifications.py index 9b1ce6205d..1f0a3048a6 100644 --- a/zerver/lib/push_notifications.py +++ b/zerver/lib/push_notifications.py @@ -2,7 +2,7 @@ from __future__ import absolute_import import random import requests -from typing import Any, Dict, List, Optional, SupportsInt, Text +from typing import Any, Dict, List, Optional, SupportsInt, Text, Union from version import ZULIP_VERSION from zerver.models import PushDeviceToken, Message, Recipient, UserProfile, \ @@ -341,15 +341,21 @@ def handle_push_notification(user_profile_id, missed_message): if umessage.flags.read: return - android_devices = [device for device in - PushDeviceToken.objects.filter(user=user_profile, - kind=PushDeviceToken.GCM)] - apple_devices = list(PushDeviceToken.objects.filter(user=user_profile, - kind=PushDeviceToken.APNS)) - apns_payload = get_apns_payload(message) gcm_payload = get_gcm_payload(user_profile, message) + if uses_notification_bouncer(): + send_notifications_to_bouncer(user_profile_id, + apns_payload, + gcm_payload) + return + + android_devices = list(PushDeviceToken.objects.filter(user=user_profile, + kind=PushDeviceToken.GCM)) + + apple_devices = list(PushDeviceToken.objects.filter(user=user_profile, + kind=PushDeviceToken.APNS)) + if apple_devices or android_devices: # TODO: set badge count in a better way if apple_devices: @@ -362,6 +368,15 @@ def handle_push_notification(user_profile_id, missed_message): except UserMessage.DoesNotExist: logging.error("Could not find UserMessage with message_id %s" % (missed_message['message_id'],)) +def send_notifications_to_bouncer(user_profile_id, apns_payload, gcm_payload): + # type: (int, Dict[str, Any], Dict[str, Any]) -> None + post_data = { + 'user_id': user_profile_id, + 'apns_payload': apns_payload, + 'gcm_payload': gcm_payload, + } + send_json_to_push_bouncer('POST', 'notify', post_data) + def add_push_device_token(user_profile, token_str, kind, ios_app_id=None): # type: (UserProfile, str, int, Optional[str]) -> None @@ -417,21 +432,33 @@ def remove_push_device_token(user_profile, token_str, kind): except PushDeviceToken.DoesNotExist: raise JsonableError(_("Token does not exist")) - -def send_to_push_bouncer(method, endpoint, post_data): +def send_json_to_push_bouncer(method, endpoint, post_data): # type: (str, str, Dict[str, Any]) -> None + send_to_push_bouncer( + method, + endpoint, + ujson.dumps(post_data), + extra_headers={"Content-type": "application/json"}, + ) + +def send_to_push_bouncer(method, endpoint, post_data, extra_headers=None): + # type: (str, str, Union[Text, Dict[str, Any]], Optional[Dict[str, Any]]) -> None url = urllib.parse.urljoin(settings.PUSH_NOTIFICATION_BOUNCER_URL, '/api/v1/remotes/push/' + endpoint) api_auth = requests.auth.HTTPBasicAuth(settings.ZULIP_ORG_ID, settings.ZULIP_ORG_KEY) + headers = {"User-agent": "ZulipServer/%s" % (ZULIP_VERSION,)} + if extra_headers is not None: + headers.update(extra_headers) + res = requests.request(method, url, - data=ujson.dumps(post_data), + data=post_data, auth=api_auth, timeout=30, verify=True, - headers={"User-agent": "ZulipServer/%s" % (ZULIP_VERSION,)}) + headers=headers) # TODO: Think more carefully about how this error hanlding should work. if res.status_code >= 500: diff --git a/zilencer/urls.py b/zilencer/urls.py index e2f847efbd..2e4caddd6f 100644 --- a/zilencer/urls.py +++ b/zilencer/urls.py @@ -16,6 +16,8 @@ v1_api_and_json_patterns = [ {'POST': 'zilencer.views.remote_server_register_push'}), url('^remotes/push/unregister$', rest_dispatch, {'POST': 'zilencer.views.remote_server_unregister_push'}), + url('^remotes/push/notify$', rest_dispatch, + {'POST': 'zilencer.views.remote_server_notify_push'}), ] urlpatterns = [ diff --git a/zilencer/views.py b/zilencer/views.py index 9c23b5a608..a01f405c2e 100644 --- a/zilencer/views.py +++ b/zilencer/views.py @@ -71,3 +71,12 @@ def remote_server_unregister_push(request, entity, token=REQ(), return json_error(_("Token does not exist")) return json_success() + +@has_request_variables +def remote_server_notify_push(request, # type: HttpRequest + entity, # type: Union[UserProfile, RemoteZulipServer] + payload=REQ(argument_type='body') # type: Dict[str, Any] + ): + # type: (...) -> HttpResponse + validate_entity(entity) + return json_success()