コード例 #1
0
    def connection(self) -> HTTP20Connection:
        """
        Open an apple connection
        requires a ssl context

        :return: an hyper.http20.connection.HTTP20Connection object
        """
        host = self.url_push
        port = self.port
        ssl_context = self.ssl_context

        connection = HTTP20Connection(host=host,
                                      port=port,
                                      ssl_context=ssl_context,
                                      force_proto=tls.H2C_PROTOCOL)

        cert_file_name = self.cert_file.split('/')[-1]
        key_file_name = self.key_file.split('/')[-1] if self.key_file else None

        if key_file_name:
            msg = f'{self.app_name.capitalize()} app: Connecting to {host}:{port} ' \
                    f'using {cert_file_name} certificate ' \
                    f'and {key_file_name} key files'
        else:
            msg = f'{self.app_name.capitalize()} app: Connecting to {host}:{port} ' \
                    f'using {cert_file_name} certificate'

        log_event(loggers=self.loggers, msg=msg, level='deb')

        return connection
コード例 #2
0
 def query_tokens(key):
     username, domain = key.split('@', 1)
     tokens = {}
     try:
         for device in PushTokens.objects(PushTokens.username == username, PushTokens.domain == domain):
             tokens[f'{device.app_id}-{device.device_id}'] = {'device_id': device.device_id, 'token': device.device_token,
                                                              'background_token': device.background_token, 'platform': device.platform,
                                                              'app_id': device.app_id, 'silent': bool(int(device.silent))}
     except CQLEngineException as e:
         log_event(loggers=settings.params.loggers, msg=f'Get token(s) failed: {e}', level='error')
         raise StorageError
     return tokens
コード例 #3
0
    def add(self, account, contact_params):
        username, domain = account.split('@', 1)
        try:
            (token, background_token) = contact_params.token.split('#')
        except ValueError:
            token = contact_params.token
            background_token = None

        try:
            PushTokens.create(username=username, domain=domain, device_id=contact_params.device_id,
                              device_token=token, background_token=background_token, platform=contact_params.platform,
                              silent=str(int(contact_params.silent is True)), app_id=contact_params.app_id,
                              user_agent=contact_params.user_agent)
        except (CQLEngineException, InvalidRequest) as e:
            log_event(loggers=settings.params.loggers, msg=f'Storing token failed: {e}', level='error')
            raise StorageError
        try:
            OpenSips.create(opensipskey=account, opensipsval='1')
        except (CQLEngineException, InvalidRequest) as e:
            log_event(loggers=settings.params.loggers, msg=e, level='error')
            raise StorageError
コード例 #4
0
ファイル: base.py プロジェクト: onebot-collab/sylk-pushserver
    def log_request(self, path: str) -> None:
        """
        Write in log information about push notification,
        using log_event function

        :param path: `str`, path where push notification will be sent.
        :param app_name: `str` for friendly log.
        :param platform: `str`, 'apple' or 'firebase'.
        :param request_id: `str`, request ID generated on request event.
        :param headers: `json`, of push notification.
        :param payload: `json`, of push notification.
        :param loggers: `dict` global logging instances to write messages (params.loggers)
        """

        # log_app_name = app_name.capitalize()
        log_platform = self.platform.capitalize()

        log_path = path if path else self.path

        level = 'info'
        msg = f'outgoing {log_platform} request {self.request_id} to {log_path}'
        log_event(loggers=self.loggers, msg=msg, level=level)

        msg = f'outgoing {log_platform} request {self.request_id} headers: {self.headers}'
        log_event(loggers=self.loggers, msg=msg, level='deb')

        msg = f'outgoing {log_platform} request {self.request_id} body: {self.payload}'
        log_event(loggers=self.loggers, msg=msg, level='deb')
コード例 #5
0
ファイル: base.py プロジェクト: onebot-collab/sylk-pushserver
    def log_results(self):
        """
        Log to journal system the result of push notification
        """
        body = self.results['body']
        code = self.results['code']
        reason = self.results['reason']
        url = self.results['url']

        level = 'info'
        body = json.dumps(body)
        msg = f"outgoing {self.platform.title()} response for request " \
                f"{self.request_id} body: {body}"
        log_event(loggers=self.loggers, msg=msg, level='deb')

        if code == 200:
            msg = f"outgoing {self.platform.title()} response for request " \
                  f"{self.request_id}: push notification sent successfully"
            log_event(loggers=self.loggers, msg=msg, level=level)
        else:
            msg = f"outgoing {self.platform.title()} response for " \
                  f"{self.request_id}, push failed with code {code}: {reason}"
            log_event(loggers=self.loggers, msg=msg, level='error')

        body = {'incoming_body': self.wp_request.__dict__,
                'outgoing_headers': self.headers,
                'outgoing_body': self.payload
                }

        if self.log_remote.get('log_urls'):
            self.log_remotely(body=body, code=code, reason=reason, url=url)
コード例 #6
0
 def __new__(self):
     configuration = CassandraConfig.__cfgtype__(CassandraConfig.__cfgfile__)
     if configuration.files:
         msg='Reading storage configuration from {}'.format(', '.join(configuration.files))
         log_event(loggers=settings.params.loggers, msg=msg, level='info')
     makedirs(ServerConfig.spool_dir.normalized)
     if CASSANDRA_MODULES_AVAILABLE and CassandraConfig.cluster_contact_points:
         if CassandraConfig.debug:
             logging.getLogger('cassandra').setLevel(logging.DEBUG)
         else:
             logging.getLogger('cassandra').setLevel(logging.INFO)
         log_event(loggers=settings.params.loggers, msg='Using Cassandra for token storage', level='info')
         return CassandraStorage()
     else:
         log_event(loggers=settings.params.loggers, msg='Using pickle file for token storage', level='info')
         return FileStorage()
コード例 #7
0
async def push_requests(account: str,
                        request: Request,
                        push_request: PushRequest,
                        background_tasks: BackgroundTasks,
                        device: Optional[str] = None):

    host, port = request.client.host, request.client.port

    code, description, data = '', '', []

    if check_host(host, settings.params.allowed_pool):
        request_id = f"{push_request.event}-{account}-{push_request.call_id}"

        if not settings.params.return_async:
            background_tasks.add_task(log_push_request,
                                      task='log_request',
                                      host=host,
                                      loggers=settings.params.loggers,
                                      request_id=request_id,
                                      body=push_request.__dict__)
            background_tasks.add_task(log_incoming_request,
                                      task='log_success',
                                      host=host,
                                      loggers=settings.params.loggers,
                                      request_id=request_id,
                                      body=push_request.__dict__)
            background_tasks.add_task(task_push,
                                      account=account,
                                      push_request=push_request,
                                      request_id=request_id,
                                      host=host,
                                      device=device)
            status_code, code = status.HTTP_202_ACCEPTED, 202
            description, data = 'accepted for delivery', {}

            try:
                return JSONResponse(status_code=status_code,
                                    content={
                                        'code': code,
                                        'description': description,
                                        'data': data
                                    })
            except json.decoder.JSONDecodeError:
                return JSONResponse(status_code=status_code,
                                    content={
                                        'code': code,
                                        'description': description,
                                        'data': {}
                                    })

        else:
            storage = TokenStorage()
            try:
                storage_data = storage[account]
            except StorageError:
                error = HTTPException(status_code=500,
                                      detail="Internal error: storage")
                log_push_request(
                    task='log_failure',
                    host=host,
                    loggers=settings.params.loggers,
                    request_id=request_id,
                    body=push_request.__dict__,
                    error_msg=f'500: {{\"detail\": \"{error.detail}\"}}')
                raise error
            expired_devices = []

            log_push_request(task='log_request',
                             host=host,
                             loggers=settings.params.loggers,
                             request_id=request_id,
                             body=push_request.__dict__)
            if not storage_data:
                description, data = 'Push request was not sent: user not found', {
                    "account": account
                }
                return JSONResponse(status_code=status.HTTP_404_NOT_FOUND,
                                    content={
                                        'code': 404,
                                        'description': description,
                                        'data': data
                                    })

            for device_key, push_parameters in storage_data.items():
                if device is not None and device != push_parameters[
                        'device_id']:
                    continue

                push_parameters.update(push_request.__dict__)

                reversed_push_parameters = {}
                for item in push_parameters.keys():
                    value = push_parameters[item]
                    if item in ('sip_to', 'sip_from'):
                        item = item.split('_')[1]
                    else:
                        item = item.replace('_', '-')
                    reversed_push_parameters[item] = value

                # Use background_token for cancel
                if push_parameters['event'] == 'cancel' and push_parameters[
                        'background_token'] is not None:
                    reversed_push_parameters['token'] = push_parameters[
                        'background_token']

                try:
                    wp = WakeUpRequest(**reversed_push_parameters)
                except ValidationError as e:
                    error_msg = e.errors()[0]['msg']
                    log_push_request(task='log_failure',
                                     host=host,
                                     loggers=settings.params.loggers,
                                     request_id=request_id,
                                     body=push_request.__dict__,
                                     error_msg=error_msg)
                    content = jsonable_encoder({
                        'code': 400,
                        'description': error_msg,
                        'data': ''
                    })
                    return JSONResponse(
                        status_code=status.HTTP_400_BAD_REQUEST,
                        content=content)

                log_incoming_request(task='log_success',
                                     host=host,
                                     loggers=settings.params.loggers,
                                     request_id=request_id,
                                     body=wp.__dict__)
                results = handle_request(wp, request_id=request_id)

                code = results.get('code')
                if code == 410:
                    expired_devices.append((push_parameters['app_id'],
                                            push_parameters['device_id']))
                    code = 200
                description = 'push notification responses'
                data.append(results)

            for expired_device in expired_devices:
                msg = f'Removing {expired_device[1]} from {account}'
                log_event(loggers=settings.params.loggers,
                          msg=msg,
                          level='info')
                storage.remove(account, *expired_device)

        if code == '':
            description, data = 'Push request was not sent: device not found', {
                "device_id": push_parameters['device_id']
            }
            content = {'code': 404, 'description': description, 'data': data}
            log_push_request(task='log_failure',
                             host=host,
                             loggers=settings.params.loggers,
                             request_id=request_id,
                             body=push_request.__dict__,
                             error_msg=f'{content}')
            return JSONResponse(status_code=status.HTTP_404_NOT_FOUND,
                                content=content)

    else:
        msg = f'incoming request from {host} is denied'
        log_event(loggers=settings.params.loggers, msg=msg, level='deb')
        code = 403
        description = 'access denied by access list'
        data = {}

        log_event(loggers=settings.params.loggers, sg=msg, level='deb')

    return JSONResponse(status_code=code,
                        content={
                            'code': code,
                            'description': description,
                            'data': data
                        })
コード例 #8
0
async def add_requests(account: str, request: Request, add_request: AddRequest,
                       background_tasks: BackgroundTasks):

    add_request.platform = fix_platform_name(add_request.platform)

    host, port = request.client.host, request.client.port

    code, description, data = '', '', {}

    if check_host(host, settings.params.allowed_pool):
        request_id = f"{account}-{add_request.app_id}-{add_request.device_id}"
        if not settings.params.return_async:
            background_tasks.add_task(log_add_request,
                                      task='log_request',
                                      host=host,
                                      loggers=settings.params.loggers,
                                      request_id=request_id,
                                      body=add_request.__dict__)

            background_tasks.add_task(log_add_request,
                                      task='log_success',
                                      host=host,
                                      loggers=settings.params.loggers,
                                      request_id=request_id,
                                      body=add_request.__dict__)

            storage = TokenStorage()
            background_tasks.add_task(storage.add, account, add_request)

            return add_request
        else:
            log_add_request(task='log_request',
                            host=host,
                            loggers=settings.params.loggers,
                            request_id=request_id,
                            body=add_request.__dict__)

            storage = TokenStorage()
            try:
                storage.add(account, add_request)
            except StorageError:
                error = HTTPException(status_code=500,
                                      detail="Internal error: storage")
                log_add_request(
                    task='log_failure',
                    host=host,
                    loggers=settings.params.loggers,
                    request_id=request_id,
                    body=add_request.__dict__,
                    error_msg=f'500: {{\"detail\": \"{error.detail}\"}}')
                raise error

            log_add_request(task='log_success',
                            host=host,
                            loggers=settings.params.loggers,
                            request_id=request_id,
                            body=add_request.__dict__)
            return add_request
    else:
        msg = f'incoming request from {host} is denied'
        log_event(loggers=settings.params.loggers, msg=msg, level='deb')
        code = 403
        description = 'access denied by access list'
        data = {}

        log_event(loggers=settings.params.loggers, msg=msg, level='deb')

    return JSONResponse(status_code=code,
                        content={
                            'code': code,
                            'description': description,
                            'data': data
                        })
コード例 #9
0
ファイル: base.py プロジェクト: onebot-collab/sylk-pushserver
 def log_error(self):
     level = 'error'
     msg = f"outgoing {self.platform.title()} response for " \
           f"{self.request_id}, push failed: " \
           f"{self.error}"
     log_event(loggers=self.loggers, msg=msg, level=level)
コード例 #10
0
ファイル: base.py プロジェクト: onebot-collab/sylk-pushserver
    def log_remotely(self, body: dict, code: str, reason: str, url: str) -> None:
        """
        Fork a log of a payload incoming request to a remote url
        :param body: `dict` response to push request
        :param code: `int` of response to push request
        :param reason: `str` of response to push request
        """

        push_response = {'code': code, 'description': reason, 'push_url': url}
        headers = {'Content-Type': 'application/json'}
        server_ip = self.server_ip('1.2.3.4')
        now = datetime.datetime.now()
        timestamp = now.strftime("%Y-%m-%d %H:%M:%S")
        payload = {'request': body, 'response': push_response,
                   'server_ip': server_ip,'timestamp': timestamp}

        task = 'log remote'

        log_key = self.log_remote.get('log_key')
        log_time_out = self.log_remote.get('log_time_out')

        results = []

        for log_url in self.log_remote['log_urls']:
            msg = f'{task} request {self.request_id} to {log_url}'
            log_event(loggers=self.loggers, msg=msg, level='deb')
            msg = f'{task} request {self.request_id} to {log_url} headers: {headers}'
            log_event(loggers=self.loggers, msg=msg, level='deb')
            msg = f'{task} request {self.request_id} to {log_url} body: {payload}'
            log_event(loggers=self.loggers, msg=msg, level='deb')

        try:
            with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
                futures = [
                    executor.submit(
                        lambda: requests.post(url=log_url,
                                              json=payload,
                                              headers=headers,
                                              timeout=log_time_out or 2)
                    )
                    for log_url in self.log_remote['log_urls']
                ]

            results = [
                f.result()
                for f in futures
            ]
        except requests.exceptions.ConnectionError as exc:
            msg = f'{task} for {self.request_id}: connection error {exc}'
            log_event(loggers=self.loggers, msg=msg, level='error')
        except requests.exceptions.ReadTimeout as exc:
            msg = f'{task} for {self.request_id}: connection error {exc}'
            log_event(loggers=self.loggers, msg=msg, level='error')

        if not results:
            return

        for url, result in list(zip(self.log_remote['log_urls'], results)):
            code = result.status_code
            text = result.text[:500]

            if log_key:
                try:
                    result = result.json()
                    value = result.get(log_key)
                except (json.decoder.JSONDecodeError, AttributeError):
                    value = {}

                if value:

                    msg = f'{task} response for request {self.request_id} from {url} - ' \
                          f'{code} {log_key}: {value}'
                    log_event(loggers=self.loggers, msg=msg, level='deb')
                else:
                    msg = f'{task} response for request {self.request_id} - ' \
                          f'code: {code}, key not found'
                    log_event(loggers=self.loggers, msg=msg, level='error')
            else:
                msg = f'{task} response for request {self.request_id} ' \
                      f'from {url}: {code} {text}'
                log_event(loggers=self.loggers, msg=msg, level='deb')
コード例 #11
0
async def push_requests(request: Request, wp_request: WakeUpRequest,
                        background_tasks: BackgroundTasks):

    wp_request.platform = fix_platform_name(wp_request.platform)

    host, port = request.client.host, request.client.port

    code, description, data = '', '', {}

    if check_host(host, settings.params.allowed_pool):
        request_id = f"{wp_request.event}-{wp_request.app_id}-{wp_request.call_id}"

        if not settings.params.return_async:
            background_tasks.add_task(log_incoming_request,
                                      task='log_request',
                                      host=host,
                                      loggers=settings.params.loggers,
                                      request_id=request_id,
                                      body=wp_request.__dict__)

            background_tasks.add_task(log_incoming_request,
                                      task='log_success',
                                      host=host,
                                      loggers=settings.params.loggers,
                                      request_id=request_id,
                                      body=wp_request.__dict__)
            background_tasks.add_task(handle_request,
                                      wp_request=wp_request,
                                      request_id=request_id)
            status_code, code = status.HTTP_202_ACCEPTED, 202
            description, data = 'accepted for delivery', {}

            try:
                return JSONResponse(status_code=status_code,
                                    content={
                                        'code': code,
                                        'description': description,
                                        'data': data
                                    })
            except json.decoder.JSONDecodeError:
                return JSONResponse(status_code=status_code,
                                    content={
                                        'code': code,
                                        'description': description,
                                        'data': {}
                                    })

        else:
            log_incoming_request(task='log_request',
                                 host=host,
                                 loggers=settings.params.loggers,
                                 request_id=request_id,
                                 body=wp_request.__dict__)

            log_incoming_request(task='log_success',
                                 host=host,
                                 loggers=settings.params.loggers,
                                 request_id=request_id,
                                 body=wp_request.__dict__)
            results = handle_request(wp_request, request_id=request_id)
            code = results.get('code')
            description = 'push notification response'
            data = results

    else:
        msg = f'incoming request from {host} is denied'
        log_event(loggers=settings.params.loggers, msg=msg, level='deb')
        code = 403
        description = 'access denied by access list'
        data = {}

        log_event(loggers=settings.params.loggers, msg=msg, level='deb')

    return JSONResponse(status_code=code,
                        content={
                            'code': code,
                            'description': description,
                            'data': data
                        })
コード例 #12
0
    def send_fcm_notification(self) -> dict:
        """
        Send a native Firebase push notification
        """

        if self.error:
            self.log_error()
            return {'code': 500, 'body': {}, 'reason': 'Internal server error'}

        n_retries, backoff_factor = self.retries_params(
            self.wp_request.media_type)

        counter = 0
        error = False
        code = 200
        response = None
        body = None
        reason = None

        while counter <= n_retries:
            self.log_request(path=self.pns.url_push)

            try:
                response = messaging.send(self.payload['fcm'])
                break
            except Exception as e:
                error = True
                response = f'connection failed: {e}'
                counter += 1
                timer = backoff_factor * (2**(counter - 1))
                conde = 500
                time.sleep(timer)

        if counter == n_retries:
            reason = "maximum retries reached"

        elif error:
            try:
                response = self.requests_retry_session(counter). \
                    post(self.pns.url_push,
                         self.payload,
                         headers=self.headers)
            except Exception as x:
                level = 'error'
                msg = f"outgoing {self.platform.title()} response for " \
                      f"{self.request_id}, push failed: " \
                      f"an error occurred in {x.__class__.__name__}"
                log_event(loggers=self.loggers, msg=msg, level=level)

        body = {'response': response}
        results = {
            'body': body,
            'code': code,
            'reason': reason,
            'url': self.pns.url_push,
            'platform': 'firebase',
            'call_id': self.wp_request.call_id,
            'token': self.token
        }

        self.results = results
        self.log_results()

        # Request is missing required authentication credential.
        # Expected OAuth 2 access token, login cookie or other valid authentication
        # credential. UNAUTHENTICATED
        code = results.get('code')
        reason = results.get('reason')
        if not got401 and code == 401 and reason == 'Unauthorized':
            if not self.pns.get('refreshed_token'):
                level = 'warn'
                msg = f"outgoing {self.platform.title()} response for request " \
                      f"{self.request_id} need a new access token - " \
                      f"server will refresh it and try again"
                log_event(loggers=self.loggers,
                          msg=msg,
                          level=level,
                          to_file=True)
                # retry with a new Fireplace access token
                self.pns.access_token = self.pns.set_access_token()
                level = 'warn'
                msg = f"outgoing {self.platform.title()} response for request " \
                      f"{self.request_id} a new access token was generated - " \
                      f"trying again"
                log_event(loggers=self.loggers,
                          msg=msg,
                          level=level,
                          to_file=True)

                self.results = self.send_notification()

        return results
コード例 #13
0
    def send_http_notification(self) -> dict:
        """
        Send a Firebase push notification over HTTP
        """

        if self.error:
            self.log_error()
            return {'code': 500, 'body': {}, 'reason': 'Internal server error'}

        n_retries, backoff_factor = self.retries_params(
            self.wp_request.media_type)

        counter = 0
        error = False
        code = 500
        reason = ""
        body = None
        response = None

        while counter <= n_retries:
            self.log_request(path=self.pns.url_push)
            try:
                response = requests.post(self.pns.url_push,
                                         self.payload,
                                         headers=self.headers)
                break
            except requests.exceptions.RequestException as e:
                error = True
                reason = f'connection failed: {e}'
                counter += 1
                timer = backoff_factor * (2**(counter - 1))
                time.sleep(timer)

        if counter == n_retries:
            reason = "maximum retries reached"

        elif error:
            try:
                response = self.requests_retry_session(counter). \
                    post(self.pns.url_push,
                         self.payload,
                         headers=self.headers)
            except Exception as x:
                level = 'error'
                msg = f"outgoing {self.platform.title()} response for " \
                      f"{self.request_id}, push failed: " \
                      f"an error occurred in {x.__class__.__name__}"
                log_event(loggers=self.loggers, msg=msg, level=level)
        try:
            body = response.__dict__
        except (TypeError, ValueError):
            code = 500
            reason = 'cannot parse response body'
            body = {}
        else:
            reason = body.get('reason')
            code = response.status_code

        for k in ('raw', 'request', 'connection', 'cookies', 'elapsed'):
            try:
                del body[k]
            except KeyError:
                pass
            except TypeError:
                break

        body = json.dumps(fix_non_serializable_types(body))

        if isinstance(body, str):
            body = json.loads(body)

        if code == 200:
            description = 'OK'
            try:
                failure = body['_content']['failure']
            except KeyError:
                pass
            else:
                if failure == 1:
                    description = body['_content']['results'][0]['error']
                    code = 410

        else:
            try:
                reason = body['reason']
            except KeyError:
                reason = None

            try:
                details = body['_content']['error']['message']
            except KeyError:
                details = None

            try:
                internal_code = body['_content']['error']['code']
            except KeyError:
                internal_code = None

            if internal_code == 400 and 'not a valid FCM registration token' in details:
                code = 410
            elif internal_code == 404:
                code = 410

            if reason and details:
                description = "%s %s" % (reason, details)
            elif reason:
                description = reason
            elif details:
                error_description = details
            else:
                description = 'unknown failure reason'

        keys = list(body.keys())
        for key in keys:
            if not body[key]:
                del body[key]

        results = {
            'body': body,
            'code': code,
            'reason': description,
            'url': self.pns.url_push,
            'platform': 'firebase',
            'call_id': self.wp_request.call_id,
            'token': self.token
        }

        self.results = results
        self.log_results()
        return results
コード例 #14
0
 def load(self):
     try:
         connection.setup(CassandraConfig.cluster_contact_points, CassandraConfig.keyspace, load_balancing_policy=DCAwareRoundRobinPolicy(), protocol_version=4, connection_class=asyncioreactor.AsyncioConnection)
     except NoHostAvailable:
         msg='Not able to connect to any of the Cassandra contact points'
         log_event(loggers=settings.params.loggers, msg=msg, level='error')
コード例 #15
0
async def task_push(account: str,
                    push_request: PushRequest,
                    request_id: str,
                    host: str,
                    device: Optional[str] = None):

    code, description, data = '', '', []
    storage = TokenStorage()
    try:
        storage_data = storage[account]
    except StorageError:
        log_remove_request(
            task='log_failure',
            host=host,
            loggers=settings.params.loggers,
            request_id=request_id,
            body=push_request.__dict__,
            error_msg=f'500: {{\"detail\": \"{error.detail}\"}}')
        return
    expired_devices = []

    if not storage_data:
        # Push request was not sent: user not found
        return

    for device_key, push_parameters in storage_data.items():
        if device is not None and device != push_parameters['device_id']:
            continue

        push_parameters.update(push_request.__dict__)

        reversed_push_parameters = {}
        for item in push_parameters.keys():
            value = push_parameters[item]
            if item in ('sip_to', 'sip_from'):
                item = item.split('_')[1]
            else:
                item = item.replace('_', '-')
            reversed_push_parameters[item] = value

        # Use background_token for cancel
        if push_parameters['event'] == 'cancel' and push_parameters[
                'background_token'] is not None:
            reversed_push_parameters['token'] = push_parameters[
                'background_token']

        try:
            wp = WakeUpRequest(**reversed_push_parameters)
        except ValidationError as e:
            error_msg = e.errors()[0]['msg']
            log_push_request(task='log_failure',
                             host=host,
                             loggers=settings.params.loggers,
                             request_id=request_id,
                             body=push_request.__dict__,
                             error_msg=error_msg)
            return

        log_incoming_request(task='log_success',
                             host=host,
                             loggers=settings.params.loggers,
                             request_id=request_id,
                             body=wp.__dict__)
        results = handle_request(wp, request_id=request_id)

        code = results.get('code')
        if code == 410:
            expired_devices.append(
                (push_parameters.app_id, push_parameters.device_id))
            code = 200
        description = 'push notification responses'
        data.append(results)

    for device in expired_devices:
        msg = f'Removing {device[1]} from {account}'
        log_event(loggers=settings.params.loggers, msg=msg, level='deb')
        storage.remove(account, *device)

    if code == '':
        description, data = 'Push request was not sent: device not found', {
            "device_id": push_parameters['device_id']
        }
        log_event(loggers=settings.params.loggers,
                  msg=f'{description} {data}',
                  level='warn')
    else:
        log_event(loggers=settings.params.loggers,
                  msg=f'{description} {data}',
                  level='deb')
コード例 #16
0
async def remove_requests(account: str,
                          request: Request,
                          rm_request: RemoveRequest,
                          background_tasks: BackgroundTasks):

    host, port = request.client.host, request.client.port

    code, description, data = '', '', {}

    if check_host(host, settings.params.allowed_pool):
        request_id = f"{account}-{rm_request.app_id}-{rm_request.device_id}"

        if not settings.params.return_async:
            background_tasks.add_task(log_remove_request, task='log_request',
                                      host=host, loggers=settings.params.loggers,
                                      request_id=request_id, body=rm_request.__dict__)
            background_tasks.add_task(log_remove_request, task='log_success',
                                      host=host, loggers=settings.params.loggers,
                                      request_id=request_id, body=rm_request.__dict__)
            storage = TokenStorage()
            background_tasks.add_task(storage.remove, account, rm_request.app_id, rm_request.device_id)
            return rm_request
        else:
            log_remove_request(task='log_request',
                               host=host, loggers=settings.params.loggers,
                               request_id=request_id, body=rm_request.__dict__)

            storage = TokenStorage()
            try:
                storage_data = storage[account]
            except StorageError:
                error = HTTPException(status_code=500, detail="Internal error: storage")
                log_remove_request(task='log_failure',
                                host=host, loggers=settings.params.loggers,
                                request_id=request_id, body=rm_request.__dict__,
                                error_msg=f'500: {{\"detail\": \"{error.detail}\"}}')
                raise error
            if not storage_data:
                log_remove_request(task='log_failure',
                                   host=host, loggers=settings.params.loggers,
                                   request_id=request_id, body=rm_request.__dict__,
                                   error_msg="User not found in token storage")
                return JSONResponse(
                    status_code=status.HTTP_404_NOT_FOUND,
                    content={'result': 'User not found'}
                )

            device_id = f"{rm_request.app_id}-{rm_request.device_id}"
            try:
                device = storage_data[device_id]
            except KeyError:
                log_remove_request(task='log_failure',
                                   host=host, loggers=settings.params.loggers,
                                   request_id=request_id, body=rm_request.__dict__,
                                   error_msg="Device or app_id not found in token storage")
                return JSONResponse(
                    status_code=status.HTTP_404_NOT_FOUND,
                    content={'result': 'Not found'}
                )
            else:
                storage.remove(account, rm_request.app_id, rm_request.device_id)
                log_remove_request(task='log_success',
                                   host=host, loggers=settings.params.loggers,
                                   request_id=request_id, body=rm_request.__dict__)
                msg = f'Removing {device}'
                log_event(loggers=settings.params.loggers,
                          msg=msg, level='deb')
                return rm_request

    else:
        msg = f'incoming request from {host} is denied'
        log_event(loggers=settings.params.loggers,
                  msg=msg, level='deb')
        code = 403
        description = 'access denied by access list'
        data = {}

        log_event(loggers=settings.params.loggers,
                  msg=msg, level='deb')

    return JSONResponse(status_code=code, content={'code': code,
                                                   'description': description,
                                                   'data': data})
コード例 #17
0
    async def start_server() -> None:

        asyncio.create_task(autoreload_read_config(wait_for=wait_for))

        level = 'info'
        loggers = settings.params.loggers
        register = settings.params.register

        pns_register = register['pns_register']
        if settings.params.apps['path']:
            msg = f"Loaded {len(pns_register)} applications from " \
                f"{settings.params.apps['path']}:"
        else:
            msg = f"Loaded {len(pns_register)} applications"
        log_event(loggers=loggers, msg=msg, level=level)

        for app in pns_register.keys():
            app_id, platform = app
            name = pns_register[app]['name']
            msg = f"Loaded {platform.capitalize()} "\
                  f"{name.capitalize()} app {app_id}" \

            log_event(loggers=loggers, msg=msg, level=level)

            headers_class = pns_register[app]['headers_class']
            payload_class = pns_register[app]['payload_class']

            msg = f"{name.capitalize()} app {app_id} classes: " \
                  f"{headers_class.__name__}, {payload_class.__name__}"
            log_event(loggers=loggers, msg=msg, level='deb')

            log_remote = pns_register[app]['log_remote']
            if log_remote['error']:
                msg = f"{name.capitalize()} loading of log remote settings failed: " \
                      f"{log_remote['error']}"
                log_event(loggers=loggers, msg=msg, level='warn')
            elif log_remote.get('log_remote_urls'):
                log_settings = ''
                for k, v in log_remote.items():
                    if k == 'error':
                        continue
                    if k == 'log_urls':
                        v = ', '.join(v)
                    if k == 'log_remote_key' and not v:
                        continue
                    if k == 'log_remote_timeout' and not v:
                        continue
                    log_settings += f'{k}: {v} '
                msg = f'{name.capitalize()} log remote settings: {log_settings}'
                log_event(loggers=loggers, msg=msg, level='deb')

        invalid_apps = register['invalid_apps']
        for app in invalid_apps.keys():
            app_id, platform = app[0], app[1]
            name = invalid_apps[app]['name']
            reason = invalid_apps[app]['reason']
            msg = f"{name.capitalize()} app with {app_id} id for {platform} platform " \
                  f"will not be available, reason: {reason}"
            log_event(loggers=loggers, msg=msg, level='warn')

        pnses = register['pnses']

        if len(pnses) == 0:
            msg = f'Loaded {len(pnses)} Push notification services'
        else:
            msg = f'Loaded {len(pnses)} Push notification services: ' \
                    f'{", ".join(pnses)}'
        log_event(loggers=loggers, msg=msg, level='deb')

        for pns in pnses:
            msg = f"{pns.split('PNS')[0]} Push Notification Service - " \
                    f"{pns} class"
            log_event(loggers=loggers, msg=msg, level='deb')

        if settings.params.allowed_pool:
            nets = [net.with_prefixlen for net in settings.params.allowed_pool]
            msg = f"Allowed hosts: " \
                  f"{', '.join(nets)}"
            log_event(loggers=loggers, msg=msg, level=level)

        msg = 'Server is now ready to answer requests'
        log_event(loggers=loggers, msg=msg, level='deb')

        ip, port = settings.params.server['host'], settings.params.server['port']
        msg = f'Sylk Pushserver listening on http://{ip}:{port}'
        log_event(loggers=loggers, msg=msg, level='info')

        await asyncio.sleep(wait_for)