Esempio n. 1
0
def remote_server_notify_push(request: HttpRequest, entity: Union[UserProfile, RemoteZulipServer],
                              payload: Dict[str, Any]=REQ(argument_type='body')) -> 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, remote=True)

    return json_success()
Esempio n. 2
0
def remote_server_notify_push(
    request: HttpRequest,
    entity: Union[UserProfile, RemoteZulipServer],
    payload: Dict[str, Any] = REQ(argument_type="body"),
) -> HttpResponse:
    server = validate_entity(entity)

    user_id = payload["user_id"]
    gcm_payload = payload["gcm_payload"]
    apns_payload = payload["apns_payload"]
    gcm_options = payload.get("gcm_options", {})

    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,
        )
    )

    send_android_push_notification(android_devices, gcm_payload, gcm_options, remote=True)

    send_apple_push_notification(user_id, apple_devices, apns_payload, remote=True)

    return json_success()
Esempio n. 3
0
def remote_server_notify_push(
    request: HttpRequest,
    entity: Union[UserProfile, RemoteZulipServer],
    payload: Dict[str, Any] = REQ(argument_type='body')
) -> 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()
Esempio n. 4
0
    def test_pushdevice_different(self, mock_send, mock_info):
        # type: (mock.MagicMock, mock.MagicMock) -> None
        res = mock.MagicMock()
        old_token = apn.hex_to_b64(u'1111')
        new_token = apn.hex_to_b64(u'2222')
        res.canonical = {old_token: new_token}
        res.needs_retry.return_value = False
        mock_send.return_value = res

        def get_count(hex_token):
            # type: (text_type) -> int
            token = apn.hex_to_b64(hex_token)
            return PushDeviceToken.objects.filter(
                token=token, kind=PushDeviceToken.GCM).count()

        self.assertEqual(get_count(u'1111'), 1)
        self.assertEqual(get_count(u'2222'), 1)

        data = self.get_gcm_data()
        apn.send_android_push_notification(self.user_profile, data)
        mock_info.assert_called_once_with(
            "GCM: Got canonical ref %s, dropping %s" % (new_token, old_token))

        self.assertEqual(get_count(u'1111'), 0)
        self.assertEqual(get_count(u'2222'), 1)
Esempio n. 5
0
    def test_pushdevice_not_present(self, mock_send, mock_warning):
        # type: (mock.MagicMock, mock.MagicMock) -> None
        res = mock.MagicMock()
        t1 = apn.hex_to_b64(u'1111')
        t2 = apn.hex_to_b64(u'3333')
        res.canonical = {t1: t2}
        res.needs_retry.return_value = False
        mock_send.return_value = res

        def get_count(hex_token):
            # type: (text_type) -> int
            token = apn.hex_to_b64(hex_token)
            return PushDeviceToken.objects.filter(
                token=token, kind=PushDeviceToken.GCM).count()

        self.assertEqual(get_count(u'1111'), 1)
        self.assertEqual(get_count(u'3333'), 0)

        data = self.get_gcm_data()
        apn.send_android_push_notification(self.user_profile, data)
        msg = ("GCM: Got canonical ref %s "
               "replacing %s but new ID not "
               "registered! Updating.")
        mock_warning.assert_called_once_with(msg % (t2, t1))

        self.assertEqual(get_count(u'1111'), 0)
        self.assertEqual(get_count(u'3333'), 1)
Esempio n. 6
0
 def test_gcm_is_none(self, mock_error):
     # type: (mock.MagicMock) -> None
     apn.gcm = None
     apn.send_android_push_notification(self.user_profile, {})
     mock_error.assert_called_with("Attempting to send a GCM push "
                                   "notification, but no API key was "
                                   "configured")
Esempio n. 7
0
    def test_equal(self, mock_send, mock_warning):
        # type: (mock.MagicMock, mock.MagicMock) -> None
        res = mock.MagicMock()
        res.canonical = {1: 1}
        res.needs_retry.return_value = False
        mock_send.return_value = res

        data = self.get_gcm_data()
        apn.send_android_push_notification(self.user_profile, data)
        mock_warning.assert_called_once_with("GCM: Got canonical ref but it "
                                             "already matches our ID 1!")
Esempio n. 8
0
    def test_failure(self, mock_send, mock_warn):
        # type: (mock.MagicMock, mock.MagicMock) -> None
        res = mock.MagicMock()
        token = apn.hex_to_b64(u'1111')
        res.failed = {token: 1}
        res.needs_retry.return_value = True
        mock_send.return_value = res

        data = self.get_gcm_data()
        apn.send_android_push_notification(self.user_profile, data)
        c1 = call("GCM: Delivery to %s failed: 1" % (token,))
        c2 = call("GCM: delivery needs a retry but ignoring")
        mock_warn.assert_has_calls([c1, c2], any_order=True)
Esempio n. 9
0
    def test_success(self, mock_send, mock_info, mock_warning):
        # type: (mock.MagicMock, mock.MagicMock, mock.MagicMock) -> None
        res = mock.MagicMock()
        res.success = {token: ind for ind, token in enumerate(self.gcm_tokens)}
        res.needs_retry.return_value = False
        mock_send.return_value = res

        data = self.get_gcm_data()
        apn.send_android_push_notification(self.user_profile, data)
        self.assertEqual(mock_info.call_count, 2)
        c1 = call("GCM: Sent 1111 as 0")
        c2 = call("GCM: Sent 2222 as 1")
        mock_info.assert_has_calls([c1, c2], any_order=True)
        mock_warning.assert_not_called()
Esempio n. 10
0
def remote_server_notify_push(
        request: HttpRequest,
        entity: Union[UserProfile, RemoteZulipServer],
        payload: Dict[str, Any] = REQ(argument_type="body"),
) -> HttpResponse:
    server = validate_entity(entity)

    user_id = payload["user_id"]
    gcm_payload = payload["gcm_payload"]
    apns_payload = payload["apns_payload"]
    gcm_options = payload.get("gcm_options", {})

    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,
        ))

    logger.info(
        "Sending mobile push notifications for remote user %s:%s: %s via FCM devices, %s via APNs devices",
        server.uuid,
        user_id,
        len(android_devices),
        len(apple_devices),
    )

    send_android_push_notification(user_id,
                                   android_devices,
                                   gcm_payload,
                                   gcm_options,
                                   remote=server)

    send_apple_push_notification(user_id,
                                 apple_devices,
                                 apns_payload,
                                 remote=server)

    return json_success({
        "total_android_devices": len(android_devices),
        "total_apple_devices": len(apple_devices)
    })
Esempio n. 11
0
    def test_not_registered(self, mock_send, mock_info):
        # type: (mock.MagicMock, mock.MagicMock) -> None
        res = mock.MagicMock()
        token = apn.hex_to_b64(u'1111')
        res.not_registered = [token]
        res.needs_retry.return_value = False
        mock_send.return_value = res

        def get_count(hex_token):
            # type: (text_type) -> int
            token = apn.hex_to_b64(hex_token)
            return PushDeviceToken.objects.filter(
                token=token, kind=PushDeviceToken.GCM).count()

        self.assertEqual(get_count(u'1111'), 1)

        data = self.get_gcm_data()
        apn.send_android_push_notification(self.user_profile, data)
        mock_info.assert_called_once_with("GCM: Removing %s" % (token,))
        self.assertEqual(get_count(u'1111'), 0)
Esempio n. 12
0
def remote_server_notify_push(
        request: HttpRequest,
        entity: Union[UserProfile, RemoteZulipServer],
        payload: Dict[str, Any] = REQ(argument_type="body"),
) -> HttpResponse:
    server = validate_entity(entity)

    user_id = payload["user_id"]
    gcm_payload = payload["gcm_payload"]
    apns_payload = payload["apns_payload"]
    gcm_options = payload.get("gcm_options", {})

    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,
        ))

    logger.info(
        "Sending mobile push notifications for remote user %s:%s: %s via FCM devices, %s via APNs devices",
        server.uuid,
        user_id,
        len(android_devices),
        len(apple_devices),
    )

    # Truncate incoming pushes to 200, due to APNs maximum message
    # sizes; see handle_remove_push_notification for the version of
    # this for notifications generated natively on the server.  We
    # apply this to remote-server pushes in case they predate that
    # commit.
    def truncate_payload(payload: Dict[str, Any]) -> Dict[str, Any]:
        MAX_MESSAGE_IDS = 200
        if payload and payload.get("event") == "remove" and payload.get(
                "zulip_message_ids"):
            ids = [int(id) for id in payload["zulip_message_ids"].split(",")]
            truncated_ids = list(sorted(ids))[-MAX_MESSAGE_IDS:]
            payload["zulip_message_ids"] = ",".join(
                str(id) for id in truncated_ids)
        return payload

    gcm_payload = truncate_payload(gcm_payload)
    send_android_push_notification(user_id,
                                   android_devices,
                                   gcm_payload,
                                   gcm_options,
                                   remote=server)

    if isinstance(apns_payload.get("custom"), dict) and isinstance(
            apns_payload["custom"].get("zulip"), dict):
        apns_payload["custom"]["zulip"] = truncate_payload(
            apns_payload["custom"]["zulip"])
    send_apple_push_notification(user_id,
                                 apple_devices,
                                 apns_payload,
                                 remote=server)

    return json_success(
        request,
        data={
            "total_android_devices": len(android_devices),
            "total_apple_devices": len(apple_devices),
        },
    )