Example #1
0
    def post(self):
        """Create a new token
        """
        if not self.can("create_token"):
            self.send_response(FORBIDDEN, dict(error="No permission to create token"))
            return
        data = self.json_decode(self.request.body)

        device = data.get('device', DEVICE_TYPE_IOS).lower()
        channel = data.get('channel', 'default')
        devicetoken = data.get('token', '')

        if device == DEVICE_TYPE_IOS:
            if len(devicetoken) != 64:
                self.send_response(BAD_REQUEST, dict(error='Invalid token'))
                return
            try:
                binascii.unhexlify(devicetoken)
            except Exception as ex:
                self.send_response(BAD_REQUEST, dict(error='Invalid token'))

        token = EntityBuilder.build_token(devicetoken, device, self.appname, channel)
        try:
            result = self.db.tokens.update({'device': device, 'token': devicetoken, 'appname': self.appname}, token, safe=True, upsert=True)
            # result
            # {u'updatedExisting': True, u'connectionId': 47, u'ok': 1.0, u'err': None, u'n': 1}
            if result['updatedExisting']:
                self.add_to_log('Token exists', devicetoken)
                self.send_response(OK)
            else:
                self.send_response(OK)
                self.add_to_log('Add token', devicetoken)
        except Exception as ex:
            self.add_to_log('Cannot add token', devicetoken, "warning")
            self.send_response(INTERNAL_SERVER_ERROR, dict(error=str(ex)))
Example #2
0
    def post(self):
        """Create a new token
        """
        if not self.can("create_token"):
            self.send_response(FORBIDDEN,
                               dict(error="No permission to create token"))
            return

        logging.info(self.request.body)
        data = json_decode(self.request.body)

        device = data.get("device", DEVICE_TYPE_IOS).lower()
        channel = data.get("channel", "default")
        devicetoken = data.get("token", "")

        if device == DEVICE_TYPE_IOS:
            if len(devicetoken) != 64:
                self.send_response(BAD_REQUEST, dict(error="Invalid token"))
                return
            try:
                binascii.unhexlify(devicetoken)
            except Exception as ex:
                self.send_response(BAD_REQUEST, dict(error="Invalid token"))

        token = EntityBuilder.build_token(devicetoken, device, self.appname,
                                          channel)
        try:
            result = self.db.tokens.update(
                {
                    "device": device,
                    "token": devicetoken,
                    "appname": self.appname
                },
                token,
                upsert=True,
            )
            # result
            # {u'updatedExisting': True, u'connectionId': 47, u'ok': 1.0, u'err': None, u'n': 1}
            if result["updatedExisting"]:
                self.add_to_log("Token exists", devicetoken)
                self.send_response(OK)
            else:
                self.send_response(OK)
                self.add_to_log("Add token", devicetoken)
        except Exception as ex:
            self.add_to_log("Cannot add token", devicetoken, "warning")
            self.send_response(INTERNAL_SERVER_ERROR, dict(error=str(ex)))
Example #3
0
    async def post(self):
        try:
            """ Send notifications """
            if not self.can("send_notification"):
                self.send_response(
                    FORBIDDEN,
                    dict(error="No permission to send notification"))
                return

            # if request body is json entity
            request_dict = json_decode(self.request.body)

            # application specific request_dict
            extra = request_dict.get("extra", {})
            # Hook
            if "processor" in extra:
                try:
                    proc = import_module("hooks." + extra["processor"])
                    request_dict = proc.process_pushnotification_payload(
                        request_dict)
                except Exception as ex:
                    logging.error(str(ex))
                    self.send_response(BAD_REQUEST, dict(error=str(ex)))
                    return

            if not self.token:
                self.token = request_dict.get("token", None)

            device = request_dict.get("device", DEVICE_TYPE_FCM).lower()
            channel = request_dict.get("channel", "default")
            alert = request_dict.get("alert", "")
            token = self.dao.find_token(self.token)

            if not token:
                token = EntityBuilder.build_token(self.token, device,
                                                  self.appname, channel)
                if not self.can("create_token"):
                    self.send_response(
                        BAD_REQUEST,
                        dict(
                            error=
                            "Unknow token and you have no permission to create"
                        ),
                    )
                    return
                try:
                    # TODO check permission to insert
                    self.dao.add_token(token)
                except Exception as ex:
                    logging.error(str(ex))
                    self.send_response(INTERNAL_SERVER_ERROR,
                                       dict(error=str(ex)))
                    return

            logging.info("sending notification to %s: %s" %
                         (device, self.token))
            #  if device in [DEVICE_TYPE_FCM, DEVICE_TYPE_ANDROID]:
            if device.endswith(DEVICE_TYPE_FCM):
                fcm = request_dict.get("fcm", {})
                try:
                    fcmconn = self.fcmconnections[self.app["shortname"]][0]
                    await fcmconn.process(token=self.token,
                                          alert=alert,
                                          fcm=fcm)
                except Exception as ex:
                    statuscode = ex.code
                    # reference:
                    # https://firebase.google.com/docs/reference/fcm/rest/v1/ErrorCode
                    response_json = json_decode(ex.response.body)
                    logging.error(response_json)
                    self.add_to_log(
                        "error", tornado.escape.to_unicode(ex.response.body))
                    self.send_response(statuscode,
                                       dict(error="error response from fcm"))
                    return

            elif device == DEVICE_TYPE_IOS:
                # Use splitlines trick to remove line ending (only for iOS).
                if type(alert) is not dict:
                    alert = "".join(alert.splitlines())

                # https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#//apple_ref/doc/uid/TP40008194-CH17-SW1
                apns_default = {
                    "badge": None,
                    "sound": "default",
                    "push_type": "alert"
                }
                apnspayload = request_dict.get("apns",
                                               request_dict.get("fcm", {}))
                conn = self.get_apns_conn()
                if conn:
                    try:
                        conn.process(
                            token=self.token,
                            alert=alert,
                            apns={
                                **apns_default,
                                **apnspayload
                            },
                        )
                    except Exception as ex:
                        logging.error(ex)
                        self.reattempt_push_apns(alert, apnspayload,
                                                 self.token)
                        return
                else:
                    logging.error("no active apns connection")

            elif device == DEVICE_TYPE_WNS:
                request_dict.setdefault("wns", {})
                wns = self.wnsconnections[self.app["shortname"]][0]
                wns.process(
                    token=request_dict["token"],
                    alert=alert,
                    extra=extra,
                    wns=request_dict["wns"],
                )
            else:
                logging.error("invalid device type %s" % device)
                self.send_response(BAD_REQUEST,
                                   dict(error="Invalid device type"))
                return

            logmessage = "payload: %s, access key: %s" % (
                tornado.escape.to_unicode(self.request.body),
                self.appkey,
            )
            self.add_to_log("notification", logmessage)
            self.send_response(ACCEPTED)
        except Exception as ex:
            traceback_ex = traceback.format_exc()
            logging.error("%s %s" % (traceback_ex, str(ex)))
            self.send_response(INTERNAL_SERVER_ERROR, dict(error=str(ex)))
Example #4
0
    def post(self):
        try:
            logging.info("New Push request from IP:%s" %
                         self.request.remote_ip)
            """ Send notifications """
            if not self.can("send_notification"):
                self.send_response(
                    FORBIDDEN,
                    dict(error="No permission to send notification"))
                return

        # if request body is json entity
            data = self.json_decode(self.request.body)

            data = self.validate_data(data)

            # Hook
            #if 'extra' in data:
            #	logging.info ("Extra data found")
            #        if 'processor' in data['extra']:
            #            try:
            #                proc = import_module('hooks.' + data['extra']['processor'])
            #                data = proc.process_pushnotification_payload(data)
            #            except Exception, ex:
            #                self.send_response(BAD_REQUEST, dict(error=str(ex)))

            if not self.token:
                self.token = data.get('token', None)

        # application specific data
            extra = data.get('extra', {})

            device = data.get('device', DEVICE_TYPE_IOS).lower()
            channel = data.get('channel', 'default')
            token = self.db.tokens.find_one({'token': self.token})

            if not token:
                token = EntityBuilder.build_token(self.token, device,
                                                  self.appname, channel)
                if not self.can("create_token"):
                    self.send_response(
                        BAD_REQUEST,
                        dict(
                            error=
                            "Unknow token and you have no permission to create"
                        ))
                    return
                try:
                    # TODO check permission to insert
                    self.db.tokens.insert(token, safe=True)
                except Exception as ex:
                    self.send_response(INTERNAL_SERVER_ERROR,
                                       dict(error=str(ex)))

            logmessage = 'requested by:%s, Message length: %s, Access key: %s, device token: %s' % (
                self.request.remote_ip, len(
                    data['alert']), self.appkey, self.token)
            self.add_to_log('%s notification' % self.appname, logmessage)

            if device == DEVICE_TYPE_SMS:
                data.setdefault('sms', {})
                data['sms'].setdefault('to', data.get('token', ''))
                data['sms'].setdefault('message', data.get('message', ''))
                sms = self.smsconnections[self.app['shortname']][0]
                sms.process(token=data['token'],
                            alert=data['alert'],
                            extra=extra,
                            sms=data['sms'])
                self.send_response(ACCEPTED)
            elif device == DEVICE_TYPE_IOS:
                # Use sliptlines trick to remove line ending (only for iOs).
                alert = ''.join(data['alert'].splitlines())
                data.setdefault('apns', {})
                data['apns'].setdefault('badge', data.get('badge', None))
                data['apns'].setdefault('sound', data.get('sound', None))
                data['apns'].setdefault('custom', data.get('custom', None))
                self.get_apns_conn().process(token=self.token,
                                             alert=alert,
                                             extra=extra,
                                             apns=data['apns'])
                self.send_response(ACCEPTED)
            elif device == DEVICE_TYPE_ANDROID:
                data.setdefault('gcm', {})
                try:
                    gcm = self.gcmconnections[self.app['shortname']][0]
                    data['gcm'].setdefault('soundname',
                                           data.get('sound', None))
                    logging.info('GCM API: Set soundname to %s' %
                                 data['sound'])
                    response = gcm.process(token=[self.token],
                                           alert=data['alert'],
                                           extra=extra,
                                           gcm=data['gcm'])
                    responsedata = response.json()
                    if responsedata['failure'] == 0:
                        self.send_response(ACCEPTED)
                except GCMUpdateRegIDsException as ex:
                    self.send_response(ACCEPTED)
                except GCMInvalidRegistrationException as ex:
                    self.send_response(BAD_REQUEST,
                                       dict(error=str(ex), regids=ex.regids))
                except GCMNotRegisteredException as ex:
                    self.send_response(BAD_REQUEST,
                                       dict(error=str(ex), regids=ex.regids))
                except GCMException as ex:
                    self.send_response(INTERNAL_SERVER_ERROR,
                                       dict(error=str(ex)))
            elif device == DEVICE_TYPE_WNS:
                data.setdefault('wns', {})
                wns = self.wnsconnections[self.app['shortname']][0]
                wns.process(token=data['token'],
                            alert=data['alert'],
                            extra=extra,
                            wns=data['wns'])
                self.send_response(ACCEPTED)
            elif device == DEVICE_TYPE_MPNS:
                data.setdefault('mpns', {})
                mpns = self.mpnsconnections[self.app['shortname']][0]
                mpns.process(token=data['token'],
                             alert=data['alert'],
                             extra=extra,
                             mpns=data['mpns'])
                self.send_response(ACCEPTED)
            else:
                self.send_response(BAD_REQUEST,
                                   dict(error='Invalid device type'))
        except Exception, ex:
            import traceback
            traceback.print_exc()
            self.send_response(INTERNAL_SERVER_ERROR, dict(error=str(ex)))
Example #5
0
    def post(self):
        try:
	    logging.info ("New Push request from IP:%s" % self.request.remote_ip)
            """ Send notifications """
            if not self.can("send_notification"):
                self.send_response(FORBIDDEN, dict(error="No permission to send notification"))
                return

            # if request body is json entity
            data = self.json_decode(self.request.body)

            data = self.validate_data(data)

            # Hook
            #if 'extra' in data:
	#	logging.info ("Extra data found")
        #        if 'processor' in data['extra']:
        #            try:
        #                proc = import_module('hooks.' + data['extra']['processor'])
        #                data = proc.process_pushnotification_payload(data)
        #            except Exception, ex:
        #                self.send_response(BAD_REQUEST, dict(error=str(ex)))

            if not self.token:
                self.token = data.get('token', None)

            # application specific data
            extra = data.get('extra', {})

            device = data.get('device', DEVICE_TYPE_IOS).lower()
            channel = data.get('channel', 'default')
            token = self.db.tokens.find_one({'token': self.token})

            if not token:
                token = EntityBuilder.build_token(self.token, device, self.appname, channel)
                if not self.can("create_token"):
                    self.send_response(BAD_REQUEST, dict(error="Unknow token and you have no permission to create"))
                    return
                try:
                    # TODO check permission to insert
                    self.db.tokens.insert(token, safe=True)
                except Exception as ex:
                    self.send_response(INTERNAL_SERVER_ERROR, dict(error=str(ex)))

            logmessage = 'requested by:%s, Message length: %s, Access key: %s, device token: %s' %( self.request.remote_ip, len(data['alert']), self.appkey, self.token)
            self.add_to_log('%s notification' % self.appname, logmessage)

            if device == DEVICE_TYPE_SMS:
                data.setdefault('sms', {})
                data['sms'].setdefault('to', data.get('token', ''))
                data['sms'].setdefault('message', data.get('message', ''))
                sms = self.smsconnections[self.app['shortname']][0]
                sms.process(token=data['token'], alert=data['alert'], extra=extra, sms=data['sms'])
                self.send_response(ACCEPTED)
            elif device == DEVICE_TYPE_IOS:
                # Use sliptlines trick to remove line ending (only for iOs).
                alert = ''.join(data['alert'].splitlines())
                data.setdefault('apns', {})
                data['apns'].setdefault('badge', data.get('badge', None))
                data['apns'].setdefault('sound', data.get('sound', None))
                data['apns'].setdefault('custom', data.get('custom', None))
                self.get_apns_conn().process(token=self.token, alert=alert, extra=extra, apns=data['apns'])
                self.send_response(ACCEPTED)
            elif device == DEVICE_TYPE_ANDROID:
                data.setdefault('gcm', {})
                try:
                    gcm = self.gcmconnections[self.app['shortname']][0]
                    data['gcm'].setdefault('soundname', data.get('sound', None))
		    logging.info ('GCM API: Set soundname to %s' % data['sound'])
                    response = gcm.process(token=[self.token], alert=data['alert'], extra=extra, gcm=data['gcm'])
                    responsedata = response.json()
                    if responsedata['failure'] == 0:
                        self.send_response(ACCEPTED)
                except GCMUpdateRegIDsException as ex:
                    self.send_response(ACCEPTED)
                except GCMInvalidRegistrationException as ex:
                    self.send_response(BAD_REQUEST, dict(error=str(ex), regids=ex.regids))
                except GCMNotRegisteredException as ex:
                    self.send_response(BAD_REQUEST, dict(error=str(ex), regids=ex.regids))
                except GCMException as ex:
                    self.send_response(INTERNAL_SERVER_ERROR, dict(error=str(ex)))
            elif device == DEVICE_TYPE_WNS:
                data.setdefault('wns', {})
                wns = self.wnsconnections[self.app['shortname']][0]
                wns.process(token=data['token'], alert=data['alert'], extra=extra, wns=data['wns'])
                self.send_response(ACCEPTED)
            elif device == DEVICE_TYPE_MPNS:
                data.setdefault('mpns', {})
                mpns = self.mpnsconnections[self.app['shortname']][0]
                mpns.process(token=data['token'], alert=data['alert'], extra=extra, mpns=data['mpns'])
                self.send_response(ACCEPTED)
            else:
                self.send_response(BAD_REQUEST, dict(error='Invalid device type'))
        except Exception, ex:
            import traceback
            traceback.print_exc()
            self.send_response(INTERNAL_SERVER_ERROR, dict(error=str(ex)))
Example #6
0
    def post(self):
        try:
            """ Send notifications """
            if not self.can("send_notification"):
                self.send_response(
                    FORBIDDEN, dict(error="No permission to send notification")
                )
                return

            # if request body is json entity
            requestPayload = self.json_decode(self.request.body)
            requestPayload = self.validate_payload(requestPayload)

            # Hook
            if "extra" in requestPayload:
                if "processor" in requestPayload["extra"]:
                    try:
                        proc = import_module(
                            "hooks." + requestPayload["extra"]["processor"]
                        )
                        requestPayload = proc.process_pushnotification_payload(
                            requestPayload
                        )
                    except Exception as ex:
                        self.send_response(BAD_REQUEST, dict(error=str(ex)))

            if not self.token:
                self.token = requestPayload.get("token", None)

            # application specific requestPayload
            extra = requestPayload.get("extra", {})

            device = requestPayload.get("device", DEVICE_TYPE_IOS).lower()
            channel = requestPayload.get("channel", "default")
            token = self.db.tokens.find_one({"token": self.token})

            if not token:
                token = EntityBuilder.build_token(
                    self.token, device, self.appname, channel
                )
                if not self.can("create_token"):
                    self.send_response(
                        BAD_REQUEST,
                        dict(error="Unknow token and you have no permission to create"),
                    )
                    return
                try:
                    # TODO check permission to insert
                    self.db.tokens.insert(token)
                except Exception as ex:
                    self.send_response(INTERNAL_SERVER_ERROR, dict(error=str(ex)))

            if device == DEVICE_TYPE_SMS:
                requestPayload.setdefault("sms", {})
                requestPayload["sms"].setdefault("to", requestPayload.get("token", ""))
                requestPayload["sms"].setdefault(
                    "message", requestPayload.get("message", "")
                )
                sms = self.smsconnections[self.app["shortname"]][0]
                sms.process(
                    token=requestPayload["token"],
                    alert=requestPayload["alert"],
                    extra=extra,
                    sms=requestPayload["sms"],
                )
                self.send_response(ACCEPTED)
            elif device == DEVICE_TYPE_IOS:

                # Use splitlines trick to remove line ending (only for iOS).
                if type(requestPayload["alert"]) is not dict:
                    alert = "".join(requestPayload["alert"].splitlines())
                else:
                    alert = requestPayload["alert"]
                requestPayload.setdefault("apns", {})
                requestPayload["apns"].setdefault(
                    "badge", requestPayload.get("badge", None)
                )
                requestPayload["apns"].setdefault(
                    "sound", requestPayload.get("sound", None)
                )
                requestPayload["apns"].setdefault(
                    "content", requestPayload.get("content", None)
                )
                requestPayload["apns"].setdefault(
                    "custom", requestPayload.get("custom", None)
                )
                conn = self.get_apns_conn()
                if conn:
                    conn.process(
                        token=self.token,
                        alert=alert,
                        extra=extra,
                        apns=requestPayload["apns"],
                    )
                else:
                    _logger.error("no active apns connection")
                self.send_response(ACCEPTED)
	    elif device == DEVICE_TYPE_FCM or device == DEVICE_TYPE_IOS_FCM or device == DEVICE_TYPE_ANDROID_FCM:
                requestPayload.setdefault("fcm", {})
                try:
                    fcm = self.fcmconnections[self.app["shortname"]][0]
                    response = fcm.process(
                        token=self.token,
                        alert=requestPayload["alert"],
                        extra=requestPayload["extra"],
                        fcm=requestPayload["fcm"],
                    )
                    self.send_response(ACCEPTED)
                except FCMException as ex:
                    self.send_response(INTERNAL_SERVER_ERROR, dict(error=ex.error))
            elif device == DEVICE_TYPE_ANDROID:
                if "gcm" not in requestPayload:
                    requestPayload.setdefault("gcm", {})
                try:
                    gcm = self.gcmconnections[self.app["shortname"]][0]
                    response = gcm.process(
                        token=[self.token],
                        alert=requestPayload["alert"],
                        extra=requestPayload["extra"],
                        gcm=requestPayload["gcm"],
                    )
                    responserequestPayload = response.json()
                    if responserequestPayload["failure"] == 0:
                        self.send_response(ACCEPTED)
                except GCMUpdateRegIDsException as ex:
                    self.send_response(ACCEPTED)
                except GCMInvalidRegistrationException as ex:
                    self.send_response(
                        BAD_REQUEST, dict(error=str(ex), regids=ex.regids)
                    )
                except GCMNotRegisteredException as ex:
                    self.send_response(
                        BAD_REQUEST, dict(error=str(ex), regids=ex.regids)
                    )
                except GCMException as ex:
                    self.send_response(INTERNAL_SERVER_ERROR, dict(error=str(ex)))
            elif device == DEVICE_TYPE_WNS:
                requestPayload.setdefault("wns", {})
                wns = self.wnsconnections[self.app["shortname"]][0]
                wns.process(
                    token=requestPayload["token"],
                    alert=requestPayload["alert"],
                    extra=extra,
                    wns=requestPayload["wns"],
                )
                self.send_response(ACCEPTED)
            elif device == DEVICE_TYPE_MPNS:
                requestPayload.setdefault("mpns", {})
                mpns = self.mpnsconnections[self.app["shortname"]][0]
                mpns.process(
                    token=requestPayload["token"],
                    alert=requestPayload["alert"],
                    extra=extra,
                    mpns=requestPayload["mpns"],
                )
                self.send_response(ACCEPTED)
            else:
                self.send_response(BAD_REQUEST, dict(error="Invalid device type"))

            logmessage = "Message length: %s, Access key: %s" % (
                len(requestPayload["alert"]),
                self.appkey,
            )
            self.add_to_log("%s notification" % self.appname, logmessage)
        except Exception as ex:
            import traceback

            traceback.print_exc()
            self.send_response(INTERNAL_SERVER_ERROR, dict(error=str(ex)))