2016-05-25 15:02:02 +02:00
|
|
|
|
|
|
|
from django.utils.translation import ugettext as _
|
2016-10-27 23:55:31 +02:00
|
|
|
from django.utils import timezone
|
2016-06-05 04:10:13 +02:00
|
|
|
from django.http import HttpResponse, HttpRequest
|
2013-10-17 22:55:09 +02:00
|
|
|
|
2016-10-27 23:55:31 +02:00
|
|
|
from zilencer.models import Deployment, RemotePushDeviceToken, RemoteZulipServer
|
2016-06-05 04:10:13 +02:00
|
|
|
|
2014-02-14 16:50:42 +01:00
|
|
|
from zerver.decorator import has_request_variables, REQ
|
2017-01-24 07:37:46 +01:00
|
|
|
from zerver.lib.error_notify import do_report_error
|
2016-10-27 23:55:31 +02:00
|
|
|
from zerver.lib.push_notifications import send_android_push_notification, \
|
|
|
|
send_apple_push_notification
|
2017-05-08 14:25:40 +02:00
|
|
|
from zerver.lib.request import JsonableError
|
2016-10-27 23:55:31 +02:00
|
|
|
from zerver.lib.response import json_error, json_success
|
2017-07-07 18:29:45 +02:00
|
|
|
from zerver.lib.validator import check_dict, check_int
|
2016-10-27 23:55:31 +02:00
|
|
|
from zerver.models import UserProfile, PushDeviceToken, Realm
|
2017-07-07 18:23:36 +02:00
|
|
|
from zerver.views.push_notifications import validate_token
|
2016-06-24 02:26:09 +02:00
|
|
|
|
2016-10-27 23:55:31 +02:00
|
|
|
from typing import Any, Dict, Optional, Union, Text, cast
|
2013-10-17 22:55:09 +02:00
|
|
|
|
2017-05-08 14:25:40 +02:00
|
|
|
def validate_entity(entity):
|
|
|
|
# type: (Union[UserProfile, RemoteZulipServer]) -> None
|
|
|
|
if not isinstance(entity, RemoteZulipServer):
|
|
|
|
raise JsonableError(_("Must validate with valid Zulip server API key"))
|
|
|
|
|
2017-07-07 18:23:36 +02:00
|
|
|
def validate_bouncer_token_request(entity, token, kind):
|
2017-07-07 19:54:37 +02:00
|
|
|
# type: (Union[UserProfile, RemoteZulipServer], bytes, int) -> None
|
2017-07-07 18:29:45 +02:00
|
|
|
if kind not in [RemotePushDeviceToken.APNS, RemotePushDeviceToken.GCM]:
|
|
|
|
raise JsonableError(_("Invalid token type"))
|
2017-05-08 14:25:40 +02:00
|
|
|
validate_entity(entity)
|
2017-07-07 18:23:36 +02:00
|
|
|
validate_token(token, kind)
|
2017-05-08 14:25:40 +02:00
|
|
|
|
2013-11-13 19:12:22 +01:00
|
|
|
@has_request_variables
|
2016-05-31 16:29:39 +02:00
|
|
|
def report_error(request, deployment, type=REQ(), report=REQ(validator=check_dict([]))):
|
2016-12-08 05:06:51 +01:00
|
|
|
# type: (HttpRequest, Deployment, Text, Dict[str, Any]) -> HttpResponse
|
2016-08-11 21:44:09 +02:00
|
|
|
return do_report_error(deployment.name, type, report)
|
2016-10-27 23:55:31 +02:00
|
|
|
|
|
|
|
@has_request_variables
|
|
|
|
def remote_server_register_push(request, entity, user_id=REQ(),
|
2017-07-07 18:29:45 +02:00
|
|
|
token=REQ(), token_kind=REQ(validator=check_int), ios_app_id=None):
|
2017-07-07 19:54:37 +02:00
|
|
|
# type: (HttpRequest, Union[UserProfile, RemoteZulipServer], int, bytes, int, Optional[Text]) -> HttpResponse
|
2017-07-07 18:23:36 +02:00
|
|
|
validate_bouncer_token_request(entity, token, token_kind)
|
2016-10-27 23:55:31 +02:00
|
|
|
server = cast(RemoteZulipServer, entity)
|
|
|
|
|
|
|
|
# If a user logged out on a device and failed to unregister,
|
|
|
|
# we should delete any other user associations for this token
|
|
|
|
# & RemoteServer pair
|
|
|
|
RemotePushDeviceToken.objects.filter(
|
|
|
|
token=token, kind=token_kind, server=server).exclude(user_id=user_id).delete()
|
|
|
|
|
|
|
|
# Save or update
|
|
|
|
remote_token, created = RemotePushDeviceToken.objects.update_or_create(
|
|
|
|
user_id=user_id,
|
|
|
|
server=server,
|
|
|
|
kind=token_kind,
|
|
|
|
token=token,
|
|
|
|
defaults=dict(
|
|
|
|
ios_app_id=ios_app_id,
|
|
|
|
last_updated=timezone.now()))
|
|
|
|
|
|
|
|
return json_success()
|
|
|
|
|
|
|
|
@has_request_variables
|
|
|
|
def remote_server_unregister_push(request, entity, token=REQ(),
|
2017-07-07 18:29:45 +02:00
|
|
|
token_kind=REQ(validator=check_int), ios_app_id=None):
|
2017-07-07 19:54:37 +02:00
|
|
|
# type: (HttpRequest, Union[UserProfile, RemoteZulipServer], bytes, int, Optional[Text]) -> HttpResponse
|
2017-07-07 18:23:36 +02:00
|
|
|
validate_bouncer_token_request(entity, token, token_kind)
|
2016-10-27 23:55:31 +02:00
|
|
|
server = cast(RemoteZulipServer, entity)
|
|
|
|
deleted = RemotePushDeviceToken.objects.filter(token=token,
|
|
|
|
kind=token_kind,
|
|
|
|
server=server).delete()
|
|
|
|
if deleted[0] == 0:
|
|
|
|
return json_error(_("Token does not exist"))
|
|
|
|
|
|
|
|
return json_success()
|
2017-05-08 13:48:16 +02:00
|
|
|
|
|
|
|
@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)
|
2017-05-09 10:31:47 +02:00
|
|
|
server = cast(RemoteZulipServer, entity)
|
|
|
|
|
|
|
|
user_id = payload['user_id']
|
|
|
|
gcm_payload = payload['gcm_payload']
|
|
|
|
apns_payload = payload['apns_payload']
|
|
|
|
|
|
|
|
android_devices = list(RemotePushDeviceToken.objects.filter(
|
|
|
|
user_id=user_id,
|
|
|
|
kind=RemotePushDeviceToken.GCM,
|
|
|
|
server=server
|
|
|
|
))
|
|
|
|
|
|
|
|
apple_devices = list(RemotePushDeviceToken.objects.filter(
|
|
|
|
user_id=user_id,
|
|
|
|
kind=RemotePushDeviceToken.APNS,
|
|
|
|
server=server
|
|
|
|
))
|
|
|
|
|
|
|
|
if android_devices:
|
2017-05-16 21:15:45 +02:00
|
|
|
send_android_push_notification(android_devices, gcm_payload, remote=True)
|
2017-05-09 10:31:47 +02:00
|
|
|
|
|
|
|
if apple_devices:
|
2017-08-19 01:38:11 +02:00
|
|
|
send_apple_push_notification(user_id, apple_devices, apns_payload)
|
2017-05-09 10:31:47 +02:00
|
|
|
|
2017-05-08 13:48:16 +02:00
|
|
|
return json_success()
|