diff --git a/pushserver/api/routes/v2/add.py b/pushserver/api/routes/v2/add.py index 22dec9f..a4d3c86 100644 --- a/pushserver/api/routes/v2/add.py +++ b/pushserver/api/routes/v2/add.py @@ -1,64 +1,74 @@ -from fastapi import APIRouter, BackgroundTasks, Request +from fastapi import APIRouter, BackgroundTasks, HTTPException, Request from fastapi.responses import JSONResponse from pushserver.models.requests import AddRequest, fix_platform_name, AddResponse from pushserver.resources import settings from pushserver.resources.storage import TokenStorage +from pushserver.resources.storage.errors import StorageError from pushserver.resources.utils import (check_host, log_event, log_add_request) router = APIRouter() @router.post('/{account}', response_model=AddResponse) 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__) - storage = TokenStorage() - storage.add(account, add_request) 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}) diff --git a/pushserver/api/routes/v2/push.py b/pushserver/api/routes/v2/push.py index 39e2046..d7e0816 100644 --- a/pushserver/api/routes/v2/push.py +++ b/pushserver/api/routes/v2/push.py @@ -1,129 +1,138 @@ import json -from fastapi import APIRouter, BackgroundTasks, Request, status +from fastapi import APIRouter, BackgroundTasks, HTTPException, Request, status from fastapi.responses import JSONResponse from fastapi.encoders import jsonable_encoder from pydantic import ValidationError from pushserver.models.requests import WakeUpRequest, PushRequest from pushserver.resources import settings from pushserver.resources.storage import TokenStorage +from pushserver.resources.storage.errors import StorageError from pushserver.resources.notification import handle_request from pushserver.resources.utils import (check_host, log_event, log_incoming_request, log_push_request) router = APIRouter() @router.post('/{account}/push', response_model=PushRequest) async def push_requests(account: str, request: Request, push_request: PushRequest, 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"{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(handle_request, wp_request=push_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: storage = TokenStorage() - storage_data = storage[account] + 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=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, push_parameters in storage_data.items(): 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 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(device) code = 200 description = 'push notification responses' data.append(results) for device in expired_devices: msg = f'Removing {device} from {account}' log_event(loggers=settings.params.loggers, msg=msg, level='deb') storage.remove(account, device) 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}) diff --git a/pushserver/api/routes/v2/remove.py b/pushserver/api/routes/v2/remove.py index f2b4315..17309a8 100644 --- a/pushserver/api/routes/v2/remove.py +++ b/pushserver/api/routes/v2/remove.py @@ -1,90 +1,99 @@ -from fastapi import APIRouter, BackgroundTasks, Request, status +from fastapi import APIRouter, BackgroundTasks, HTTPException, Request, status from fastapi.responses import JSONResponse from pushserver.models.requests import RemoveRequest, RemoveResponse from pushserver.resources import settings from pushserver.resources.storage import TokenStorage +from pushserver.resources.storage.errors import StorageError from pushserver.resources.utils import (check_host, log_event, log_remove_request) router = APIRouter() @router.delete('/{account}', response_model=RemoveResponse) 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, request_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() - storage_data = storage[account] + 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 print(storage_data) 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'} ) try: device = storage_data[request_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: device = f"{rm_request.app_id}-{rm_request.device_id}" storage.remove(account, device) 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})