mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	And it works! A couple of things still to do: * When a device token is no longer active, we'll get HTTP status 410. We should then remove the token from the database so we don't keep trying to push to it. This is fairly urgent. * The library we're using has a nice asynchronous API, but this version doesn't use it. This is OK now, but async will be essential at scale.
		
			
				
	
	
		
			109 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from __future__ import absolute_import
 | 
						|
 | 
						|
from django.utils.translation import ugettext as _
 | 
						|
from django.utils import timezone
 | 
						|
from django.http import HttpResponse, HttpRequest
 | 
						|
 | 
						|
from zilencer.models import Deployment, RemotePushDeviceToken, RemoteZulipServer
 | 
						|
 | 
						|
from zerver.decorator import has_request_variables, REQ
 | 
						|
from zerver.lib.error_notify import do_report_error
 | 
						|
from zerver.lib.push_notifications import send_android_push_notification, \
 | 
						|
    send_apple_push_notification
 | 
						|
from zerver.lib.request import JsonableError
 | 
						|
from zerver.lib.response import json_error, json_success
 | 
						|
from zerver.lib.validator import check_dict, check_int
 | 
						|
from zerver.models import UserProfile, PushDeviceToken, Realm
 | 
						|
from zerver.views.push_notifications import validate_token
 | 
						|
 | 
						|
from typing import Any, Dict, Optional, Union, Text, cast
 | 
						|
 | 
						|
def validate_entity(entity):
 | 
						|
    # type: (Union[UserProfile, RemoteZulipServer]) -> None
 | 
						|
    if not isinstance(entity, RemoteZulipServer):
 | 
						|
        raise JsonableError(_("Must validate with valid Zulip server API key"))
 | 
						|
 | 
						|
def validate_bouncer_token_request(entity, token, kind):
 | 
						|
    # type: (Union[UserProfile, RemoteZulipServer], bytes, int) -> None
 | 
						|
    if kind not in [RemotePushDeviceToken.APNS, RemotePushDeviceToken.GCM]:
 | 
						|
        raise JsonableError(_("Invalid token type"))
 | 
						|
    validate_entity(entity)
 | 
						|
    validate_token(token, kind)
 | 
						|
 | 
						|
@has_request_variables
 | 
						|
def report_error(request, deployment, type=REQ(), report=REQ(validator=check_dict([]))):
 | 
						|
    # type: (HttpRequest, Deployment, Text, Dict[str, Any]) -> HttpResponse
 | 
						|
    return do_report_error(deployment.name, type, report)
 | 
						|
 | 
						|
@has_request_variables
 | 
						|
def remote_server_register_push(request, entity, user_id=REQ(),
 | 
						|
                                token=REQ(), token_kind=REQ(validator=check_int), ios_app_id=None):
 | 
						|
    # type: (HttpRequest, Union[UserProfile, RemoteZulipServer], int, bytes, int, Optional[Text]) -> HttpResponse
 | 
						|
    validate_bouncer_token_request(entity, token, token_kind)
 | 
						|
    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(),
 | 
						|
                                  token_kind=REQ(validator=check_int), ios_app_id=None):
 | 
						|
    # type: (HttpRequest, Union[UserProfile, RemoteZulipServer], bytes, int, Optional[Text]) -> HttpResponse
 | 
						|
    validate_bouncer_token_request(entity, token, token_kind)
 | 
						|
    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()
 | 
						|
 | 
						|
@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)
 | 
						|
    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:
 | 
						|
        send_android_push_notification(android_devices, gcm_payload, remote=True)
 | 
						|
 | 
						|
    if apple_devices:
 | 
						|
        send_apple_push_notification(user_id, apple_devices, apns_payload)
 | 
						|
 | 
						|
    return json_success()
 |