updated handler exceptions
This commit is contained in:
@@ -5,9 +5,11 @@ from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi import Request, HTTPException, status
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from api_objects.errors.errorMessages import EXCEPTION_DICTS, ERRORS_DICT, ERRORS_LANG
|
||||
from api_objects.errors.errorHandlers import HTTPExceptionEvyos, HTTPExceptionAnyHandler, HTTPExceptionEvyosHandler
|
||||
|
||||
from middlewares.token_middleware import AuthHeaderMiddleware
|
||||
from application.create_file import create_app
|
||||
from api_objects.errors.errors_dictionary import ErrorHandlers
|
||||
from prometheus_fastapi_instrumentator import Instrumentator
|
||||
|
||||
app = create_app(routers=routers)
|
||||
@@ -24,17 +26,20 @@ app.add_middleware(
|
||||
)
|
||||
app.add_middleware(AuthHeaderMiddleware)
|
||||
|
||||
# Initialize error handlers
|
||||
error_handlers = ErrorHandlers.create(
|
||||
requests=Request,
|
||||
exceptions=HTTPException,
|
||||
response_model=JSONResponse,
|
||||
status=status,
|
||||
)
|
||||
# Initialize Exception and ExceptionInstance handlers
|
||||
CustomExceptionHandler = HTTPExceptionEvyosHandler(**dict(
|
||||
statuses=status,
|
||||
exceptions=HTTPException,
|
||||
response_model=JSONResponse,
|
||||
exceptions_dict=EXCEPTION_DICTS,
|
||||
errors_dict=ERRORS_DICT,
|
||||
error_language_dict=ERRORS_LANG
|
||||
))
|
||||
CustomExceptionAnyHandler = HTTPExceptionAnyHandler(response_model=JSONResponse)
|
||||
|
||||
# Register error handlers with bound methods
|
||||
app.add_exception_handler(HTTPException, error_handlers.exception_handler_http)
|
||||
app.add_exception_handler(Exception, error_handlers.exception_handler_exception)
|
||||
app.add_exception_handler(HTTPExceptionEvyos, CustomExceptionHandler.handle_exception)
|
||||
app.add_exception_handler(Exception, CustomExceptionAnyHandler.any_exception_handler)
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn_config = {
|
||||
|
||||
@@ -13,7 +13,7 @@ from api_services.templates.password_templates import (
|
||||
from api_services.token_service import TokenService
|
||||
from api_services.redis.functions import RedisActions
|
||||
from api_library.response_handlers import ResponseHandler
|
||||
from api_library.date_time_actions.date_functions import system_arrow
|
||||
from api_library.date_time_actions.date_functions import system_arrow, DateTimeLocal
|
||||
|
||||
# from api_library.user_logger import UserLogger
|
||||
|
||||
@@ -74,38 +74,41 @@ class AuthenticationLoginEventMethods(MethodToEvent):
|
||||
|
||||
@classmethod
|
||||
def authentication_login_with_domain_and_creds(cls, data: Login, request: Request):
|
||||
try:
|
||||
access_dict = Users.login_user_with_credentials(data=data, request=request)
|
||||
found_user = access_dict.get("user")
|
||||
if not found_user:
|
||||
# UserLogger.log_login_attempt(
|
||||
# request,
|
||||
# None,
|
||||
# data.domain,
|
||||
# data.access_key,
|
||||
# success=False,
|
||||
# error="Invalid credentials",
|
||||
# )
|
||||
return ResponseHandler.unauthorized("Invalid credentials")
|
||||
from api_objects import HTTPExceptionEvyos
|
||||
|
||||
raise HTTPExceptionEvyos(
|
||||
error_code="UNKNOWN_ERROR",
|
||||
lang="en",
|
||||
)
|
||||
access_dict = Users.login_user_with_credentials(data=data, request=request)
|
||||
found_user = access_dict.get("user")
|
||||
Users.client_arrow = DateTimeLocal(
|
||||
is_client=True, timezone=found_user.local_timezone
|
||||
)
|
||||
if not found_user:
|
||||
# UserLogger.log_login_attempt(
|
||||
# request, found_user.id, data.domain, data.access_key, success=True
|
||||
# request,
|
||||
# None,
|
||||
# data.domain,
|
||||
# data.access_key,
|
||||
# success=False,
|
||||
# error="Invalid credentials",
|
||||
# )
|
||||
response_data = {
|
||||
return ResponseHandler.unauthorized("Invalid credentials")
|
||||
return ResponseHandler.success(
|
||||
message="User logged in successfully",
|
||||
data={
|
||||
"access_token": access_dict.get("access_token"),
|
||||
"refresh_token": access_dict.get("refresher_token"),
|
||||
"access_object": access_dict.get("access_object"),
|
||||
"user": found_user.get_dict(),
|
||||
}
|
||||
return ResponseHandler.success(
|
||||
message="User logged in successfully",
|
||||
data=response_data,
|
||||
)
|
||||
except Exception as e:
|
||||
# UserLogger.log_login_attempt(
|
||||
# request, None, data.domain, data.access_key, success=False, error=str(e)
|
||||
# )
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))
|
||||
},
|
||||
)
|
||||
# except Exception as e:
|
||||
# # UserLogger.log_login_attempt(
|
||||
# # request, None, data.domain, data.access_key, success=False, error=str(e)
|
||||
# # )
|
||||
# raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))
|
||||
|
||||
|
||||
class AuthenticationSelectEventMethods(MethodToEvent):
|
||||
@@ -125,6 +128,9 @@ class AuthenticationSelectEventMethods(MethodToEvent):
|
||||
cls, data: EmployeeSelection, token_dict: EmployeeTokenObject, request: Request
|
||||
):
|
||||
"""Handle employee company selection"""
|
||||
Users.client_arrow = DateTimeLocal(
|
||||
is_client=True, timezone=token_dict.local_timezone
|
||||
)
|
||||
if data.company_uu_id not in token_dict.companies_uu_id_list:
|
||||
return ResponseHandler.unauthorized(
|
||||
"Company not found in user's company list"
|
||||
|
||||
@@ -79,7 +79,7 @@ def endpoint_restriction_available(request: Request, data: CheckEndpointAccess):
|
||||
system=True,
|
||||
).data
|
||||
if not endpoint:
|
||||
EndpointRestriction.raise_http_exception(
|
||||
raise EndpointRestriction.raise_http_exception(
|
||||
status_code="HTTP_404_NOT_FOUND",
|
||||
error_case="UNAUTHORIZED",
|
||||
message="Only Occupant can see this data",
|
||||
@@ -94,7 +94,7 @@ def endpoint_restriction_available(request: Request, data: CheckEndpointAccess):
|
||||
== token_dict.selected_occupant.living_space_id,
|
||||
).data
|
||||
if not event_occupant:
|
||||
EndpointRestriction.raise_http_exception(
|
||||
raise EndpointRestriction.raise_http_exception(
|
||||
status_code="HTTP_404_NOT_FOUND",
|
||||
error_case="UNAUTHORIZED",
|
||||
message="This endpoint is not available for this occupant",
|
||||
@@ -110,7 +110,7 @@ def endpoint_restriction_available(request: Request, data: CheckEndpointAccess):
|
||||
Event2Employee.employee_id == token_dict.selected_company.employee_id,
|
||||
).data
|
||||
if not event_employee:
|
||||
EndpointRestriction.raise_http_exception(
|
||||
raise EndpointRestriction.raise_http_exception(
|
||||
status_code="HTTP_404_NOT_FOUND",
|
||||
error_case="UNAUTHORIZED",
|
||||
message="This endpoint is not available for this employee",
|
||||
|
||||
@@ -10,6 +10,7 @@ from application.create_file import create_app
|
||||
from api_objects.errors.errors_dictionary import ErrorHandlers
|
||||
from prometheus_fastapi_instrumentator import Instrumentator
|
||||
|
||||
|
||||
app = create_app(routers=routers)
|
||||
Instrumentator().instrument(app=app).expose(app=app)
|
||||
|
||||
|
||||
@@ -84,6 +84,10 @@ class AuthActions:
|
||||
person_uu_id=str(found_user.person.uu_id),
|
||||
request=dict(request.headers),
|
||||
available_occupants=occupants_selection_dict,
|
||||
timezone=(
|
||||
found_user.local_timezone if found_user.local_timezone else "GMT+0"
|
||||
),
|
||||
lang=found_user.lang if found_user.lang else "tr",
|
||||
),
|
||||
)
|
||||
return dict(
|
||||
@@ -136,6 +140,7 @@ class AuthActions:
|
||||
company_address=company_address,
|
||||
)
|
||||
)
|
||||
|
||||
AccessObjectActions.save_object_to_redis(
|
||||
access_token=access_token,
|
||||
model_object=EmployeeTokenObject(
|
||||
@@ -151,6 +156,10 @@ class AuthActions:
|
||||
companies_id_list=companies_id_list,
|
||||
duty_uu_id_list=duty_uu_id_list,
|
||||
duty_id_list=duty_id_list,
|
||||
timezone=(
|
||||
found_user.local_timezone if found_user.local_timezone else "GMT+0"
|
||||
),
|
||||
lang=found_user.lang if found_user.lang else "tr",
|
||||
),
|
||||
)
|
||||
return dict(
|
||||
@@ -185,11 +194,30 @@ class AuthActions:
|
||||
found_user.generate_access_token() if not access_token else access_token
|
||||
)
|
||||
# Prepare the user's details to save in Redis Session
|
||||
if found_user.is_occupant: # Check if user is NOT an occupant
|
||||
return cls.do_occupant_login_token(
|
||||
if found_user.is_occupant: # Check if user is an occupant
|
||||
cls.do_occupant_login_token(request, found_user, domain, access_token)
|
||||
|
||||
return {
|
||||
"access_object": cls.do_occupant_login_token(
|
||||
request, found_user, domain, access_token
|
||||
),
|
||||
"access_token": access_token,
|
||||
"refresher_token": (
|
||||
found_user.generate_refresh_token()
|
||||
if found_user.remember_me
|
||||
else None
|
||||
),
|
||||
}
|
||||
cls.do_employee_login_token(request, found_user, domain, access_token)
|
||||
return {
|
||||
"access_object": cls.do_employee_login_token(
|
||||
request, found_user, domain, access_token
|
||||
)
|
||||
return cls.do_employee_login_token(request, found_user, domain, access_token)
|
||||
),
|
||||
"access_token": access_token,
|
||||
"refresher_token": (
|
||||
found_user.generate_refresh_token() if found_user.remember_me else None
|
||||
),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def update_selected_to_redis(cls, request, add_payload):
|
||||
|
||||
@@ -24,6 +24,7 @@ class AccessObjectActions:
|
||||
Raises:
|
||||
HTTPException: If save fails
|
||||
"""
|
||||
|
||||
try:
|
||||
RedisActions.save_object_to_redis(
|
||||
access_token=access_token,
|
||||
|
||||
@@ -1,8 +1,100 @@
|
||||
from typing import Any, Union
|
||||
from typing import Any, Union, Callable, Any
|
||||
from fastapi import status
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from pydantic import BaseModel
|
||||
from api_validations.validations_request import PydanticBaseModel, BaseModelRegular
|
||||
from databases.sql_models.response_model import AlchemyResponse
|
||||
from sqlalchemy.orm import Query
|
||||
|
||||
MODEL_TYPE = Callable[[Any], Any]
|
||||
|
||||
class Pagination:
|
||||
size: int = 10
|
||||
page: int = 1
|
||||
orderField: str = "id"
|
||||
orderType: str = "asc"
|
||||
pageCount: int = 1
|
||||
totalCount: int = 1
|
||||
totalPage: int = 1
|
||||
|
||||
def change(self, page=None, size=None, order_field=None, order_type=None):
|
||||
self.page = page or self.page
|
||||
self.size = size or self.size
|
||||
self.orderField = order_field or self.orderField
|
||||
self.orderType = order_type or self.orderType
|
||||
self.setter_page()
|
||||
|
||||
def feed(self, data):
|
||||
if isinstance(data, list):
|
||||
self.totalCount = len(data)
|
||||
elif isinstance(data, AlchemyResponse):
|
||||
self.totalCount = data.count
|
||||
elif isinstance(data, Query):
|
||||
self.totalCount = data.count()
|
||||
|
||||
def setter_page(self):
|
||||
self.pageCount = self.size
|
||||
self.totalPage = int(round(self.totalCount / self.size, 0))
|
||||
if self.totalCount % self.size > 0:
|
||||
if self.page == self.totalPage:
|
||||
self.pageCount = self.totalCount % self.size
|
||||
self.totalPage = int(round(self.totalCount / self.size, 0)) + 1
|
||||
|
||||
def as_dict(self):
|
||||
return {
|
||||
"size": self.size,
|
||||
"page": self.page,
|
||||
"totalCount": self.totalCount,
|
||||
"totalPage": self.totalPage,
|
||||
"pageCount": self.pageCount,
|
||||
"orderField": self.orderField,
|
||||
"orderType": self.orderType,
|
||||
}
|
||||
|
||||
|
||||
class SingleAlchemyResponse:
|
||||
status_code = "HTTP_200_OK"
|
||||
result: AlchemyResponse
|
||||
response_model: MODEL_TYPE
|
||||
message: str
|
||||
completed: bool
|
||||
|
||||
def __new__(
|
||||
cls,
|
||||
message: str,
|
||||
response_model: MODEL_TYPE,
|
||||
status_code: str = "HTTP_200_OK",
|
||||
result: AlchemyResponse = None,
|
||||
completed: bool = True,
|
||||
):
|
||||
cls.status_code = getattr(status, status_code, "HTTP_200_OK")
|
||||
cls.message = message
|
||||
cls.result = result
|
||||
cls.completed = completed
|
||||
cls.response_model = response_model
|
||||
|
||||
if not isinstance(cls.result, AlchemyResponse):
|
||||
raise Exception("Invalid response type 4 single alchemy response")
|
||||
|
||||
if not cls.result.first:
|
||||
raise Exception("Invalid data type 4 single alchemy response")
|
||||
|
||||
pagination = Pagination()
|
||||
pagination.change(page=1)
|
||||
BaseModelRegular(**cls.result.data.get_dict())
|
||||
data = cls.result.data.get_dict()
|
||||
if cls.response_model:
|
||||
data = cls.response_model(**cls.result.data.get_dict()).dump()
|
||||
return JSONResponse(
|
||||
status_code=cls.status_code,
|
||||
content=dict(
|
||||
pagination=pagination.as_dict(),
|
||||
completed=cls.completed,
|
||||
message=cls.message,
|
||||
data=data,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class AlchemyJsonResponse:
|
||||
@@ -11,27 +103,16 @@ class AlchemyJsonResponse:
|
||||
result: AlchemyResponse
|
||||
completed: bool
|
||||
filter_attributes: Any = None
|
||||
response_model: Any = None
|
||||
response_model: MODEL_TYPE = None
|
||||
cls_object: Any = None
|
||||
|
||||
@staticmethod
|
||||
def get_total_count(cls_object, filter_attributes):
|
||||
total_page_number = 1
|
||||
count_to_use = cls_object.total_count / int(filter_attributes.size)
|
||||
if cls_object.total_count > int(filter_attributes.size):
|
||||
if isinstance(count_to_use, int):
|
||||
total_page_number = round(count_to_use, 0)
|
||||
elif isinstance(count_to_use, float):
|
||||
total_page_number = round(count_to_use, 0) + 1
|
||||
return total_page_number
|
||||
|
||||
def __new__(
|
||||
cls,
|
||||
message: str,
|
||||
status_code: str = "HTTP_200_OK",
|
||||
result: Union[Any, list] = None,
|
||||
result: Union[BaseModelRegular, BaseModel, PydanticBaseModel] = None,
|
||||
completed: bool = True,
|
||||
response_model: Any = None,
|
||||
response_model: MODEL_TYPE = None,
|
||||
cls_object: Any = None,
|
||||
filter_attributes: Any = None,
|
||||
):
|
||||
@@ -40,108 +121,121 @@ class AlchemyJsonResponse:
|
||||
cls.result = result
|
||||
cls.completed = completed
|
||||
cls.response_model = response_model
|
||||
|
||||
pagination_dict = {
|
||||
"size/total_count": [10, 10],
|
||||
"page/total_page": [1, 1],
|
||||
"order_field": "id",
|
||||
"order_type": "asc",
|
||||
}
|
||||
if filter_attributes:
|
||||
total_page_number = cls.get_total_count(cls_object, filter_attributes)
|
||||
pagination_dict = {
|
||||
"size/total_count": [filter_attributes.size, cls_object.total_count],
|
||||
"page/total_page": [filter_attributes.page, total_page_number],
|
||||
"order_field": filter_attributes.order_field,
|
||||
"order_type": filter_attributes.order_type,
|
||||
}
|
||||
|
||||
if isinstance(cls.result, dict) or isinstance(cls.result, list):
|
||||
return JSONResponse(
|
||||
status_code=cls.status_code,
|
||||
content=dict(
|
||||
total_count=len(cls.result),
|
||||
count=len(cls.result),
|
||||
pagination=pagination_dict,
|
||||
completed=cls.completed,
|
||||
message=cls.message,
|
||||
data=cls.result,
|
||||
),
|
||||
)
|
||||
|
||||
first_item = getattr(cls.result, "data", None)
|
||||
if not first_item:
|
||||
return JSONResponse(
|
||||
status_code=cls.status_code,
|
||||
content=dict(
|
||||
total_count=0,
|
||||
count=0,
|
||||
pagination=pagination_dict,
|
||||
completed=cls.completed,
|
||||
message=cls.message,
|
||||
data=[],
|
||||
),
|
||||
)
|
||||
cls.filter_attributes = filter_attributes
|
||||
cls.cls_object = cls_object
|
||||
pagination = Pagination()
|
||||
|
||||
if cls.result.first:
|
||||
return JSONResponse(
|
||||
status_code=cls.status_code,
|
||||
content=dict(
|
||||
total_count=1,
|
||||
count=1,
|
||||
pagination=pagination_dict,
|
||||
completed=cls.completed,
|
||||
message=cls.message,
|
||||
data=cls.result.data.get_dict(),
|
||||
),
|
||||
)
|
||||
raise Exception("Invalid data type 4 alchemy response")
|
||||
|
||||
if not cls.result.get(1).filter_attr and isinstance(cls.result.data, list):
|
||||
counts = cls.result.count
|
||||
return JSONResponse(
|
||||
status_code=cls.status_code,
|
||||
content=dict(
|
||||
total_count=counts,
|
||||
count=counts,
|
||||
pagination=pagination_dict,
|
||||
completed=cls.completed,
|
||||
message=cls.message,
|
||||
data=[result_data.get_dict() for result_data in cls.result.data],
|
||||
),
|
||||
if filter_attributes:
|
||||
pagination.change(
|
||||
page=filter_attributes.page, size=filter_attributes.size,
|
||||
order_field=filter_attributes.order_field,
|
||||
order_type=filter_attributes.order_type,
|
||||
)
|
||||
|
||||
# filter_model = cls.result.get(1).filter_attr
|
||||
total_count = cls.result.get(1).query.limit(None).offset(None).count()
|
||||
total_page_number = cls.get_total_count(cls_object, filter_attributes)
|
||||
pagination_dict = {
|
||||
"size/total_count": [filter_attributes.size, cls_object.total_count],
|
||||
"page/total_page": [filter_attributes.page, total_page_number],
|
||||
"order_field": filter_attributes.order_field,
|
||||
"order_type": filter_attributes.order_type,
|
||||
}
|
||||
include_joins = dict(
|
||||
include_joins=(
|
||||
filter_attributes.include_joins
|
||||
if filter_attributes.include_joins
|
||||
else []
|
||||
)
|
||||
)
|
||||
data = []
|
||||
for data_object in cls.result.data:
|
||||
data_dict = data_object.get_dict(include_joins=include_joins)
|
||||
data_dict = data_object.get_dict()
|
||||
if cls.response_model:
|
||||
data_dict = cls.response_model(
|
||||
**data_object.get_dict(include_joins=include_joins)
|
||||
).dump()
|
||||
data_dict = cls.response_model(**data_object.get_dict()).dump()
|
||||
data.append(data_dict)
|
||||
pagination.feed(data)
|
||||
return JSONResponse(
|
||||
status_code=cls.status_code,
|
||||
content=dict(
|
||||
total_count=total_count or 1,
|
||||
count=cls.result.count,
|
||||
pagination=pagination_dict,
|
||||
pagination=pagination.as_dict(),
|
||||
message=cls.message,
|
||||
completed=cls.completed,
|
||||
data=data,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class ListJsonResponse:
|
||||
status_code = "HTTP_200_OK"
|
||||
result: list
|
||||
message: str
|
||||
completed: bool
|
||||
filter_attributes: Any
|
||||
response_model: MODEL_TYPE = None,
|
||||
cls_object: Any = None,
|
||||
|
||||
def __new__(
|
||||
cls,
|
||||
message: str,
|
||||
status_code: str = "HTTP_200_OK",
|
||||
result: Union[BaseModelRegular, BaseModel, PydanticBaseModel] = None,
|
||||
completed: bool = True,
|
||||
response_model: MODEL_TYPE = None,
|
||||
cls_object: Any = None,
|
||||
filter_attributes: Any = None,
|
||||
):
|
||||
cls.status_code = getattr(status, status_code, "HTTP_200_OK")
|
||||
cls.message = message
|
||||
cls.result = result
|
||||
cls.completed = completed
|
||||
cls.filter_attributes = filter_attributes
|
||||
cls.response_model: MODEL_TYPE = response_model
|
||||
|
||||
if not isinstance(cls.result, list):
|
||||
raise Exception("Invalid data type 4 list json response")
|
||||
pagination = Pagination()
|
||||
pagination.change(page=1)
|
||||
data = list(cls.result)
|
||||
if cls.response_model:
|
||||
data = [cls.response_model(**data_object).dump() for data_object in cls.result]
|
||||
pagination.feed(data)
|
||||
return JSONResponse(
|
||||
status_code=cls.status_code,
|
||||
content=dict(
|
||||
pagination=pagination.as_dict(),
|
||||
completed=cls.completed,
|
||||
message=cls.message,
|
||||
data=cls.result,
|
||||
),
|
||||
)
|
||||
|
||||
class DictJsonResponse:
|
||||
status_code = "HTTP_200_OK"
|
||||
result: dict
|
||||
message: str
|
||||
completed: bool
|
||||
filter_attributes: Any
|
||||
response_model: MODEL_TYPE = None,
|
||||
cls_object: Any = None,
|
||||
|
||||
def __new__(
|
||||
cls,
|
||||
message: str,
|
||||
status_code: str = "HTTP_200_OK",
|
||||
result: Union[BaseModelRegular, BaseModel, PydanticBaseModel] = None,
|
||||
completed: bool = True,
|
||||
response_model: MODEL_TYPE = None,
|
||||
cls_object: Any = None,
|
||||
filter_attributes: Any = None,
|
||||
):
|
||||
cls.status_code = getattr(status, status_code, "HTTP_200_OK")
|
||||
cls.message = message
|
||||
cls.result = result
|
||||
cls.completed = completed
|
||||
cls.filter_attributes = filter_attributes
|
||||
cls.response_model: MODEL_TYPE = response_model
|
||||
|
||||
if not isinstance(cls.result, dict):
|
||||
raise Exception("Invalid data type 4 dict json response")
|
||||
|
||||
pagination = Pagination()
|
||||
pagination.change(page=1)
|
||||
data = cls.result
|
||||
if cls.response_model:
|
||||
data = cls.response_model(**cls.result).dump()
|
||||
return JSONResponse(
|
||||
status_code=cls.status_code,
|
||||
content=dict(
|
||||
pagination=pagination.as_dict(),
|
||||
completed=cls.completed,
|
||||
message=cls.message,
|
||||
data=data,
|
||||
),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user