2021-01-01 16:39:25 +01:00
|
|
|
from json import dumps
|
2021-01-02 19:28:03 +01:00
|
|
|
from typing import Dict, List, Optional, Union
|
2021-01-01 16:39:25 +01:00
|
|
|
|
|
|
|
from fittrackee import appLog
|
|
|
|
from flask import Response
|
2021-01-02 19:28:03 +01:00
|
|
|
from flask_sqlalchemy import SQLAlchemy
|
2021-01-01 16:39:25 +01:00
|
|
|
|
|
|
|
|
2021-01-02 19:28:03 +01:00
|
|
|
def get_empty_data_for_datatype(data_type: str) -> Union[str, List]:
|
2021-01-01 16:39:25 +01:00
|
|
|
return '' if data_type in ['gpx', 'chart_data'] else []
|
|
|
|
|
|
|
|
|
|
|
|
class HttpResponse(Response):
|
|
|
|
def __init__(
|
|
|
|
self,
|
2021-01-02 19:28:03 +01:00
|
|
|
response: Optional[Union[str, Dict]] = None,
|
|
|
|
status_code: Optional[int] = None,
|
|
|
|
content_type: Optional[str] = None,
|
|
|
|
) -> None:
|
2021-01-01 16:39:25 +01:00
|
|
|
if isinstance(response, dict):
|
|
|
|
response = dumps(response)
|
|
|
|
content_type = (
|
|
|
|
'application/json' if content_type is None else content_type
|
|
|
|
)
|
|
|
|
super().__init__(
|
|
|
|
response=response,
|
|
|
|
status=status_code,
|
|
|
|
content_type=content_type,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class GenericErrorResponse(HttpResponse):
|
2021-01-02 19:28:03 +01:00
|
|
|
def __init__(
|
|
|
|
self, status_code: int, message: str, status: Optional[str] = None
|
|
|
|
) -> None:
|
2021-01-01 16:39:25 +01:00
|
|
|
response = {
|
|
|
|
'status': 'error' if status is None else status,
|
|
|
|
'message': message,
|
|
|
|
}
|
|
|
|
super().__init__(
|
|
|
|
response=response,
|
|
|
|
status_code=status_code,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class InvalidPayloadErrorResponse(GenericErrorResponse):
|
2021-01-02 19:28:03 +01:00
|
|
|
def __init__(
|
|
|
|
self, message: Optional[str] = None, status: Optional[str] = None
|
|
|
|
) -> None:
|
2021-01-01 16:39:25 +01:00
|
|
|
message = 'Invalid payload.' if message is None else message
|
|
|
|
super().__init__(status_code=400, message=message, status=status)
|
|
|
|
|
|
|
|
|
|
|
|
class DataInvalidPayloadErrorResponse(HttpResponse):
|
2021-01-02 19:28:03 +01:00
|
|
|
def __init__(self, data_type: str, status: Optional[str] = None) -> None:
|
2021-01-01 16:39:25 +01:00
|
|
|
response = {
|
|
|
|
'status': 'error' if status is None else status,
|
|
|
|
'data': {data_type: get_empty_data_for_datatype(data_type)},
|
|
|
|
}
|
|
|
|
super().__init__(response=response, status_code=400)
|
|
|
|
|
|
|
|
|
|
|
|
class UnauthorizedErrorResponse(GenericErrorResponse):
|
2021-01-02 19:28:03 +01:00
|
|
|
def __init__(self, message: Optional[str] = None) -> None:
|
2021-01-01 16:39:25 +01:00
|
|
|
message = (
|
|
|
|
'Invalid token. Please request a new token.'
|
|
|
|
if message is None
|
|
|
|
else message
|
|
|
|
)
|
|
|
|
super().__init__(status_code=401, message=message)
|
|
|
|
|
|
|
|
|
|
|
|
class ForbiddenErrorResponse(GenericErrorResponse):
|
2021-01-02 19:28:03 +01:00
|
|
|
def __init__(self, message: Optional[str] = None) -> None:
|
2021-01-01 16:39:25 +01:00
|
|
|
message = (
|
|
|
|
'You do not have permissions.' if message is None else message
|
|
|
|
)
|
|
|
|
super().__init__(status_code=403, message=message)
|
|
|
|
|
|
|
|
|
|
|
|
class NotFoundErrorResponse(GenericErrorResponse):
|
2021-01-02 19:28:03 +01:00
|
|
|
def __init__(self, message: str) -> None:
|
2021-01-01 16:39:25 +01:00
|
|
|
super().__init__(status_code=404, message=message, status='not found')
|
|
|
|
|
|
|
|
|
|
|
|
class UserNotFoundErrorResponse(NotFoundErrorResponse):
|
2021-01-02 19:28:03 +01:00
|
|
|
def __init__(self) -> None:
|
2021-01-01 16:39:25 +01:00
|
|
|
super().__init__(message='User does not exist.')
|
|
|
|
|
|
|
|
|
|
|
|
class DataNotFoundErrorResponse(HttpResponse):
|
2021-01-02 19:28:03 +01:00
|
|
|
def __init__(self, data_type: str, message: Optional[str] = None) -> None:
|
2021-01-01 16:39:25 +01:00
|
|
|
response = {
|
|
|
|
'status': 'not found',
|
|
|
|
'data': {data_type: get_empty_data_for_datatype(data_type)},
|
|
|
|
}
|
|
|
|
if message:
|
|
|
|
response['message'] = message
|
|
|
|
super().__init__(response=response, status_code=404)
|
|
|
|
|
|
|
|
|
|
|
|
class PayloadTooLargeErrorResponse(GenericErrorResponse):
|
2021-01-02 19:28:03 +01:00
|
|
|
def __init__(self, message: str) -> None:
|
2021-01-01 16:39:25 +01:00
|
|
|
super().__init__(status_code=413, message=message, status='fail')
|
|
|
|
|
|
|
|
|
|
|
|
class InternalServerErrorResponse(GenericErrorResponse):
|
2021-01-02 19:28:03 +01:00
|
|
|
def __init__(
|
|
|
|
self, message: Optional[str] = None, status: Optional[str] = None
|
|
|
|
):
|
2021-01-01 16:39:25 +01:00
|
|
|
message = (
|
|
|
|
'Error. Please try again or contact the administrator.'
|
|
|
|
if message is None
|
|
|
|
else message
|
|
|
|
)
|
|
|
|
super().__init__(status_code=500, message=message, status=status)
|
|
|
|
|
|
|
|
|
|
|
|
def handle_error_and_return_response(
|
2021-01-02 19:28:03 +01:00
|
|
|
error: Exception,
|
|
|
|
message: Optional[str] = None,
|
|
|
|
status: Optional[str] = None,
|
|
|
|
db: Optional[SQLAlchemy] = None,
|
|
|
|
) -> HttpResponse:
|
2021-01-01 16:39:25 +01:00
|
|
|
if db is not None:
|
|
|
|
db.session.rollback()
|
|
|
|
appLog.error(error)
|
|
|
|
return InternalServerErrorResponse(message=message, status=status)
|