updated handler exceptions
This commit is contained in:
parent
cecf1e69a2
commit
56b693989d
|
|
@ -5,9 +5,11 @@ from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi import Request, HTTPException, status
|
from fastapi import Request, HTTPException, status
|
||||||
from fastapi.responses import JSONResponse
|
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 middlewares.token_middleware import AuthHeaderMiddleware
|
||||||
from application.create_file import create_app
|
from application.create_file import create_app
|
||||||
from api_objects.errors.errors_dictionary import ErrorHandlers
|
|
||||||
from prometheus_fastapi_instrumentator import Instrumentator
|
from prometheus_fastapi_instrumentator import Instrumentator
|
||||||
|
|
||||||
app = create_app(routers=routers)
|
app = create_app(routers=routers)
|
||||||
|
|
@ -24,17 +26,20 @@ app.add_middleware(
|
||||||
)
|
)
|
||||||
app.add_middleware(AuthHeaderMiddleware)
|
app.add_middleware(AuthHeaderMiddleware)
|
||||||
|
|
||||||
# Initialize error handlers
|
# Initialize Exception and ExceptionInstance handlers
|
||||||
error_handlers = ErrorHandlers.create(
|
CustomExceptionHandler = HTTPExceptionEvyosHandler(**dict(
|
||||||
requests=Request,
|
statuses=status,
|
||||||
exceptions=HTTPException,
|
exceptions=HTTPException,
|
||||||
response_model=JSONResponse,
|
response_model=JSONResponse,
|
||||||
status=status,
|
exceptions_dict=EXCEPTION_DICTS,
|
||||||
)
|
errors_dict=ERRORS_DICT,
|
||||||
|
error_language_dict=ERRORS_LANG
|
||||||
|
))
|
||||||
|
CustomExceptionAnyHandler = HTTPExceptionAnyHandler(response_model=JSONResponse)
|
||||||
|
|
||||||
# Register error handlers with bound methods
|
# Register error handlers with bound methods
|
||||||
app.add_exception_handler(HTTPException, error_handlers.exception_handler_http)
|
app.add_exception_handler(HTTPExceptionEvyos, CustomExceptionHandler.handle_exception)
|
||||||
app.add_exception_handler(Exception, error_handlers.exception_handler_exception)
|
app.add_exception_handler(Exception, CustomExceptionAnyHandler.any_exception_handler)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
uvicorn_config = {
|
uvicorn_config = {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ from api_services.templates.password_templates import (
|
||||||
from api_services.token_service import TokenService
|
from api_services.token_service import TokenService
|
||||||
from api_services.redis.functions import RedisActions
|
from api_services.redis.functions import RedisActions
|
||||||
from api_library.response_handlers import ResponseHandler
|
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
|
# from api_library.user_logger import UserLogger
|
||||||
|
|
||||||
|
|
@ -74,38 +74,41 @@ class AuthenticationLoginEventMethods(MethodToEvent):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def authentication_login_with_domain_and_creds(cls, data: Login, request: Request):
|
def authentication_login_with_domain_and_creds(cls, data: Login, request: Request):
|
||||||
try:
|
from api_objects import HTTPExceptionEvyos
|
||||||
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")
|
|
||||||
|
|
||||||
|
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(
|
# 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"),
|
"access_token": access_dict.get("access_token"),
|
||||||
"refresh_token": access_dict.get("refresher_token"),
|
"refresh_token": access_dict.get("refresher_token"),
|
||||||
"access_object": access_dict.get("access_object"),
|
"access_object": access_dict.get("access_object"),
|
||||||
"user": found_user.get_dict(),
|
"user": found_user.get_dict(),
|
||||||
}
|
},
|
||||||
return ResponseHandler.success(
|
)
|
||||||
message="User logged in successfully",
|
# except Exception as e:
|
||||||
data=response_data,
|
# # UserLogger.log_login_attempt(
|
||||||
)
|
# # request, None, data.domain, data.access_key, success=False, error=str(e)
|
||||||
except Exception as e:
|
# # )
|
||||||
# UserLogger.log_login_attempt(
|
# raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))
|
||||||
# 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):
|
class AuthenticationSelectEventMethods(MethodToEvent):
|
||||||
|
|
@ -125,6 +128,9 @@ class AuthenticationSelectEventMethods(MethodToEvent):
|
||||||
cls, data: EmployeeSelection, token_dict: EmployeeTokenObject, request: Request
|
cls, data: EmployeeSelection, token_dict: EmployeeTokenObject, request: Request
|
||||||
):
|
):
|
||||||
"""Handle employee company selection"""
|
"""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:
|
if data.company_uu_id not in token_dict.companies_uu_id_list:
|
||||||
return ResponseHandler.unauthorized(
|
return ResponseHandler.unauthorized(
|
||||||
"Company not found in user's company list"
|
"Company not found in user's company list"
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ def endpoint_restriction_available(request: Request, data: CheckEndpointAccess):
|
||||||
system=True,
|
system=True,
|
||||||
).data
|
).data
|
||||||
if not endpoint:
|
if not endpoint:
|
||||||
EndpointRestriction.raise_http_exception(
|
raise EndpointRestriction.raise_http_exception(
|
||||||
status_code="HTTP_404_NOT_FOUND",
|
status_code="HTTP_404_NOT_FOUND",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message="Only Occupant can see this data",
|
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,
|
== token_dict.selected_occupant.living_space_id,
|
||||||
).data
|
).data
|
||||||
if not event_occupant:
|
if not event_occupant:
|
||||||
EndpointRestriction.raise_http_exception(
|
raise EndpointRestriction.raise_http_exception(
|
||||||
status_code="HTTP_404_NOT_FOUND",
|
status_code="HTTP_404_NOT_FOUND",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message="This endpoint is not available for this occupant",
|
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,
|
Event2Employee.employee_id == token_dict.selected_company.employee_id,
|
||||||
).data
|
).data
|
||||||
if not event_employee:
|
if not event_employee:
|
||||||
EndpointRestriction.raise_http_exception(
|
raise EndpointRestriction.raise_http_exception(
|
||||||
status_code="HTTP_404_NOT_FOUND",
|
status_code="HTTP_404_NOT_FOUND",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message="This endpoint is not available for this employee",
|
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 api_objects.errors.errors_dictionary import ErrorHandlers
|
||||||
from prometheus_fastapi_instrumentator import Instrumentator
|
from prometheus_fastapi_instrumentator import Instrumentator
|
||||||
|
|
||||||
|
|
||||||
app = create_app(routers=routers)
|
app = create_app(routers=routers)
|
||||||
Instrumentator().instrument(app=app).expose(app=app)
|
Instrumentator().instrument(app=app).expose(app=app)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,10 @@ class AuthActions:
|
||||||
person_uu_id=str(found_user.person.uu_id),
|
person_uu_id=str(found_user.person.uu_id),
|
||||||
request=dict(request.headers),
|
request=dict(request.headers),
|
||||||
available_occupants=occupants_selection_dict,
|
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(
|
return dict(
|
||||||
|
|
@ -136,6 +140,7 @@ class AuthActions:
|
||||||
company_address=company_address,
|
company_address=company_address,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
AccessObjectActions.save_object_to_redis(
|
AccessObjectActions.save_object_to_redis(
|
||||||
access_token=access_token,
|
access_token=access_token,
|
||||||
model_object=EmployeeTokenObject(
|
model_object=EmployeeTokenObject(
|
||||||
|
|
@ -151,6 +156,10 @@ class AuthActions:
|
||||||
companies_id_list=companies_id_list,
|
companies_id_list=companies_id_list,
|
||||||
duty_uu_id_list=duty_uu_id_list,
|
duty_uu_id_list=duty_uu_id_list,
|
||||||
duty_id_list=duty_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(
|
return dict(
|
||||||
|
|
@ -185,11 +194,30 @@ class AuthActions:
|
||||||
found_user.generate_access_token() if not access_token else access_token
|
found_user.generate_access_token() if not access_token else access_token
|
||||||
)
|
)
|
||||||
# Prepare the user's details to save in Redis Session
|
# Prepare the user's details to save in Redis Session
|
||||||
if found_user.is_occupant: # Check if user is NOT an occupant
|
if found_user.is_occupant: # Check if user is an occupant
|
||||||
return cls.do_occupant_login_token(
|
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
|
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
|
@classmethod
|
||||||
def update_selected_to_redis(cls, request, add_payload):
|
def update_selected_to_redis(cls, request, add_payload):
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ class AccessObjectActions:
|
||||||
Raises:
|
Raises:
|
||||||
HTTPException: If save fails
|
HTTPException: If save fails
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
RedisActions.save_object_to_redis(
|
RedisActions.save_object_to_redis(
|
||||||
access_token=access_token,
|
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 import status
|
||||||
from fastapi.responses import JSONResponse
|
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 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:
|
class AlchemyJsonResponse:
|
||||||
|
|
@ -11,27 +103,16 @@ class AlchemyJsonResponse:
|
||||||
result: AlchemyResponse
|
result: AlchemyResponse
|
||||||
completed: bool
|
completed: bool
|
||||||
filter_attributes: Any = None
|
filter_attributes: Any = None
|
||||||
response_model: Any = None
|
response_model: MODEL_TYPE = None
|
||||||
cls_object: Any = 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__(
|
def __new__(
|
||||||
cls,
|
cls,
|
||||||
message: str,
|
message: str,
|
||||||
status_code: str = "HTTP_200_OK",
|
status_code: str = "HTTP_200_OK",
|
||||||
result: Union[Any, list] = None,
|
result: Union[BaseModelRegular, BaseModel, PydanticBaseModel] = None,
|
||||||
completed: bool = True,
|
completed: bool = True,
|
||||||
response_model: Any = None,
|
response_model: MODEL_TYPE = None,
|
||||||
cls_object: Any = None,
|
cls_object: Any = None,
|
||||||
filter_attributes: Any = None,
|
filter_attributes: Any = None,
|
||||||
):
|
):
|
||||||
|
|
@ -40,108 +121,121 @@ class AlchemyJsonResponse:
|
||||||
cls.result = result
|
cls.result = result
|
||||||
cls.completed = completed
|
cls.completed = completed
|
||||||
cls.response_model = response_model
|
cls.response_model = response_model
|
||||||
|
cls.filter_attributes = filter_attributes
|
||||||
pagination_dict = {
|
cls.cls_object = cls_object
|
||||||
"size/total_count": [10, 10],
|
pagination = Pagination()
|
||||||
"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=[],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
if cls.result.first:
|
if cls.result.first:
|
||||||
return JSONResponse(
|
raise Exception("Invalid data type 4 alchemy response")
|
||||||
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(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
if not cls.result.get(1).filter_attr and isinstance(cls.result.data, list):
|
if filter_attributes:
|
||||||
counts = cls.result.count
|
pagination.change(
|
||||||
return JSONResponse(
|
page=filter_attributes.page, size=filter_attributes.size,
|
||||||
status_code=cls.status_code,
|
order_field=filter_attributes.order_field,
|
||||||
content=dict(
|
order_type=filter_attributes.order_type,
|
||||||
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],
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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 = []
|
data = []
|
||||||
for data_object in cls.result.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:
|
if cls.response_model:
|
||||||
data_dict = cls.response_model(
|
data_dict = cls.response_model(**data_object.get_dict()).dump()
|
||||||
**data_object.get_dict(include_joins=include_joins)
|
|
||||||
).dump()
|
|
||||||
data.append(data_dict)
|
data.append(data_dict)
|
||||||
|
pagination.feed(data)
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=cls.status_code,
|
status_code=cls.status_code,
|
||||||
content=dict(
|
content=dict(
|
||||||
total_count=total_count or 1,
|
pagination=pagination.as_dict(),
|
||||||
count=cls.result.count,
|
|
||||||
pagination=pagination_dict,
|
|
||||||
message=cls.message,
|
message=cls.message,
|
||||||
completed=cls.completed,
|
completed=cls.completed,
|
||||||
data=data,
|
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,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,12 @@ services:
|
||||||
- auth_venv:/service_app/.venv
|
- auth_venv:/service_app/.venv
|
||||||
- auth_logs:/service_app/logs
|
- auth_logs:/service_app/logs
|
||||||
|
|
||||||
|
# wag_management_init_service:
|
||||||
|
# container_name: wag_management_init_service
|
||||||
|
# build:
|
||||||
|
# context: .
|
||||||
|
# dockerfile: service_app_init/Dockerfile
|
||||||
|
|
||||||
# wag_management_event_service:
|
# wag_management_event_service:
|
||||||
# container_name: wag_management_event_service
|
# container_name: wag_management_event_service
|
||||||
# # restart: on-failure
|
# # restart: on-failure
|
||||||
|
|
@ -41,11 +47,7 @@ services:
|
||||||
# - validation_venv:/service_app/.venv
|
# - validation_venv:/service_app/.venv
|
||||||
# - validation_logs:/service_app/logs
|
# - validation_logs:/service_app/logs
|
||||||
|
|
||||||
# wag_management_init_service:
|
|
||||||
# container_name: wag_management_init_service
|
|
||||||
# build:
|
|
||||||
# context: .
|
|
||||||
# dockerfile: service_app_init/Dockerfile
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
auth_venv:
|
auth_venv:
|
||||||
|
|
|
||||||
|
|
@ -14,20 +14,6 @@ from api_events.events.address.address import (
|
||||||
AddressPostCodeUpdateEventMethod,
|
AddressPostCodeUpdateEventMethod,
|
||||||
AddressPostCodeListEventMethod,
|
AddressPostCodeListEventMethod,
|
||||||
)
|
)
|
||||||
from api_events.events.application.authentication import (
|
|
||||||
AuthenticationLoginEventMethod,
|
|
||||||
AuthenticationSelectEventMethod,
|
|
||||||
AuthenticationCheckTokenEventMethod,
|
|
||||||
AuthenticationRefreshEventMethod,
|
|
||||||
AuthenticationChangePasswordEventMethod,
|
|
||||||
AuthenticationCreatePasswordEventMethod,
|
|
||||||
AuthenticationResetPasswordEventMethod,
|
|
||||||
AuthenticationDisconnectUserEventMethod,
|
|
||||||
AuthenticationLogoutEventMethod,
|
|
||||||
AuthenticationRefreshTokenEventMethod,
|
|
||||||
AuthenticationForgotPasswordEventMethod,
|
|
||||||
AuthenticationDownloadAvatarEventMethod,
|
|
||||||
)
|
|
||||||
from api_events.events.account.account_records import (
|
from api_events.events.account.account_records import (
|
||||||
AccountRecordsListEventMethod,
|
AccountRecordsListEventMethod,
|
||||||
AccountRecordsCreateEventMethod,
|
AccountRecordsCreateEventMethod,
|
||||||
|
|
@ -184,18 +170,6 @@ __all__ = [
|
||||||
"PeopleUpdateEventMethod",
|
"PeopleUpdateEventMethod",
|
||||||
"PeoplePatchEventMethod",
|
"PeoplePatchEventMethod",
|
||||||
"PeopleCreateEventMethod",
|
"PeopleCreateEventMethod",
|
||||||
"AuthenticationLoginEventMethod",
|
|
||||||
"AuthenticationSelectEventMethod",
|
|
||||||
"AuthenticationCheckTokenEventMethod",
|
|
||||||
"AuthenticationRefreshEventMethod",
|
|
||||||
"AuthenticationChangePasswordEventMethod",
|
|
||||||
"AuthenticationCreatePasswordEventMethod",
|
|
||||||
"AuthenticationResetPasswordEventMethod",
|
|
||||||
"AuthenticationDisconnectUserEventMethod",
|
|
||||||
"AuthenticationLogoutEventMethod",
|
|
||||||
"AuthenticationRefreshTokenEventMethod",
|
|
||||||
"AuthenticationForgotPasswordEventMethod",
|
|
||||||
"AuthenticationDownloadAvatarEventMethod",
|
|
||||||
"AccountRecordsListEventMethod",
|
"AccountRecordsListEventMethod",
|
||||||
"AccountRecordsCreateEventMethod",
|
"AccountRecordsCreateEventMethod",
|
||||||
"AccountRecordsUpdateEventMethod",
|
"AccountRecordsUpdateEventMethod",
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ class AccountRecordsListEventMethods(MethodToEvent):
|
||||||
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
|
token_dict: typing.Union[EmployeeTokenObject, OccupantTokenObject],
|
||||||
):
|
):
|
||||||
if not isinstance(token_dict, OccupantTokenObject):
|
if not isinstance(token_dict, OccupantTokenObject):
|
||||||
raise AccountRecords().raise_http_exception(
|
raise AccountRecords.raise_http_exception(
|
||||||
status_code="HTTP_404_NOT_FOUND",
|
status_code="HTTP_404_NOT_FOUND",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message="Only Occupant can see this data",
|
message="Only Occupant can see this data",
|
||||||
|
|
@ -76,7 +76,7 @@ class AccountRecordsListEventMethods(MethodToEvent):
|
||||||
id=token_dict.selected_occupant.living_space_id
|
id=token_dict.selected_occupant.living_space_id
|
||||||
).data
|
).data
|
||||||
if not living_space:
|
if not living_space:
|
||||||
raise AccountRecords().raise_http_exception(
|
raise AccountRecords.raise_http_exception(
|
||||||
status_code="HTTP_404_NOT_FOUND",
|
status_code="HTTP_404_NOT_FOUND",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message="Living space not found",
|
message="Living space not found",
|
||||||
|
|
@ -214,7 +214,7 @@ class AccountRecordsCreateEventMethods(MethodToEvent):
|
||||||
BuildIbans.build_id == token_dict.selected_occupant.build_id,
|
BuildIbans.build_id == token_dict.selected_occupant.build_id,
|
||||||
).data
|
).data
|
||||||
if not build_iban:
|
if not build_iban:
|
||||||
BuildIbans.raise_http_exception(
|
raise BuildIbans.raise_http_exception(
|
||||||
status_code="HTTP_404_NOT_FOUND",
|
status_code="HTTP_404_NOT_FOUND",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"{data.iban} is not found in company related to your organization",
|
message=f"{data.iban} is not found in company related to your organization",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
|
|
||||||
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
|
|
||||||
|
|
||||||
|
|
||||||
class DecisionBookEvents(MethodToEvent): ...
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
|
|
||||||
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
|
|
||||||
|
|
||||||
|
|
||||||
class ApplicationEvents(MethodToEvent): ...
|
|
||||||
|
|
@ -1,750 +0,0 @@
|
||||||
import json
|
|
||||||
from typing import Union
|
|
||||||
from fastapi import status
|
|
||||||
from fastapi.requests import Request
|
|
||||||
from fastapi.exceptions import HTTPException
|
|
||||||
|
|
||||||
from api_objects import OccupantTokenObject, EmployeeTokenObject
|
|
||||||
from api_objects.auth.token_objects import CompanyToken, OccupantToken
|
|
||||||
from api_services.templates.password_templates import (
|
|
||||||
password_is_changed_template,
|
|
||||||
change_your_password_template,
|
|
||||||
)
|
|
||||||
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.user_logger import UserLogger
|
|
||||||
|
|
||||||
from api_validations.validations_request import (
|
|
||||||
Login,
|
|
||||||
Logout,
|
|
||||||
ChangePassword,
|
|
||||||
EmployeeSelection,
|
|
||||||
OccupantSelection,
|
|
||||||
CreatePassword,
|
|
||||||
Forgot,
|
|
||||||
# ResetPassword,
|
|
||||||
# RefreshToken,
|
|
||||||
)
|
|
||||||
from api_validations.validations_response import (
|
|
||||||
AuthenticationLoginResponse,
|
|
||||||
AuthenticationRefreshResponse,
|
|
||||||
AuthenticationUserInfoResponse,
|
|
||||||
)
|
|
||||||
from ApiServices.api_handlers.auth_actions.auth import AuthActions
|
|
||||||
from api_configs import Auth, ApiStatic
|
|
||||||
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
|
|
||||||
|
|
||||||
from databases import (
|
|
||||||
Companies,
|
|
||||||
Staff,
|
|
||||||
Duties,
|
|
||||||
Departments,
|
|
||||||
Employees,
|
|
||||||
BuildLivingSpace,
|
|
||||||
BuildParts,
|
|
||||||
Build,
|
|
||||||
Duty,
|
|
||||||
Event2Occupant,
|
|
||||||
Event2Employee,
|
|
||||||
Users,
|
|
||||||
UsersTokens,
|
|
||||||
OccupantTypes,
|
|
||||||
RelationshipEmployee2Build,
|
|
||||||
)
|
|
||||||
|
|
||||||
from api_services import (
|
|
||||||
send_email,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationLoginEventMethods(MethodToEvent):
|
|
||||||
event_type = "LOGIN"
|
|
||||||
event_description = "Login via domain and access key : [email] | [phone]"
|
|
||||||
event_category = "AUTHENTICATION"
|
|
||||||
|
|
||||||
__event_keys__ = {
|
|
||||||
"e672846d-cc45-4d97-85d5-6f96747fac67": "authentication_login_with_domain_and_creds",
|
|
||||||
}
|
|
||||||
__event_validation__ = {
|
|
||||||
"e672846d-cc45-4d97-85d5-6f96747fac67": AuthenticationLoginResponse,
|
|
||||||
}
|
|
||||||
|
|
||||||
@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")
|
|
||||||
|
|
||||||
# UserLogger.log_login_attempt(
|
|
||||||
# request, found_user.id, data.domain, data.access_key, success=True
|
|
||||||
# )
|
|
||||||
response_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))
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationSelectEventMethods(MethodToEvent):
|
|
||||||
event_type = "LOGIN"
|
|
||||||
event_description = "Select Employee Duty or Occupant Type"
|
|
||||||
event_category = "AUTHENTICATION"
|
|
||||||
|
|
||||||
__event_keys__ = {
|
|
||||||
"cee96b9b-8487-4e9f-aaed-2e8c79687bf9": "authentication_select_company_or_occupant_type",
|
|
||||||
}
|
|
||||||
__event_validation__ = {
|
|
||||||
"cee96b9b-8487-4e9f-aaed-2e8c79687bf9": "authentication_select_company_or_occupant_type",
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _handle_employee_selection(
|
|
||||||
cls, data: EmployeeSelection, token_dict: EmployeeTokenObject, request: Request
|
|
||||||
):
|
|
||||||
"""Handle employee company selection"""
|
|
||||||
if data.company_uu_id not in token_dict.companies_uu_id_list:
|
|
||||||
return ResponseHandler.unauthorized(
|
|
||||||
"Company not found in user's company list"
|
|
||||||
)
|
|
||||||
|
|
||||||
selected_company = Companies.filter_one(
|
|
||||||
Companies.uu_id == data.company_uu_id
|
|
||||||
).data
|
|
||||||
if not selected_company:
|
|
||||||
return ResponseHandler.not_found("Company not found")
|
|
||||||
|
|
||||||
# Get department IDs for the company
|
|
||||||
department_ids = [
|
|
||||||
dept.id
|
|
||||||
for dept in Departments.filter_all(
|
|
||||||
Departments.company_id == selected_company.id
|
|
||||||
).data
|
|
||||||
]
|
|
||||||
|
|
||||||
# Get duties IDs for the company
|
|
||||||
duties_ids = [
|
|
||||||
duty.id
|
|
||||||
for duty in Duties.filter_all(Duties.company_id == selected_company.id).data
|
|
||||||
]
|
|
||||||
|
|
||||||
# Get staff IDs
|
|
||||||
staff_ids = [
|
|
||||||
staff.id for staff in Staff.filter_all(Staff.duties_id.in_(duties_ids)).data
|
|
||||||
]
|
|
||||||
|
|
||||||
# Get employee
|
|
||||||
employee = Employees.filter_one(
|
|
||||||
Employees.people_id == token_dict.person_id,
|
|
||||||
Employees.staff_id.in_(staff_ids),
|
|
||||||
).data
|
|
||||||
|
|
||||||
if not employee:
|
|
||||||
return ResponseHandler.not_found("Employee not found")
|
|
||||||
|
|
||||||
# Get reachable events
|
|
||||||
reachable_event_list_id = Event2Employee.get_event_id_by_employee_id(
|
|
||||||
employee_id=employee.id
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get staff and duties
|
|
||||||
staff = Staff.filter_one(Staff.id == employee.staff_id).data
|
|
||||||
duties = Duties.filter_one(Duties.id == staff.duties_id).data
|
|
||||||
department = Departments.filter_one(Departments.id == duties.department_id).data
|
|
||||||
|
|
||||||
# Get bulk duty
|
|
||||||
bulk_id = Duty.filter_by_one(system=True, duty_code="BULK").data
|
|
||||||
bulk_duty_id = Duties.filter_by_one(
|
|
||||||
company_id=selected_company.id,
|
|
||||||
duties_id=bulk_id.id,
|
|
||||||
**Duties.valid_record_dict,
|
|
||||||
).data
|
|
||||||
|
|
||||||
# Create company token
|
|
||||||
company_token = CompanyToken(
|
|
||||||
company_uu_id=selected_company.uu_id.__str__(),
|
|
||||||
company_id=selected_company.id,
|
|
||||||
department_id=department.id,
|
|
||||||
department_uu_id=department.uu_id.__str__(),
|
|
||||||
duty_id=duties.id,
|
|
||||||
duty_uu_id=duties.uu_id.__str__(),
|
|
||||||
bulk_duties_id=bulk_duty_id.id,
|
|
||||||
staff_id=staff.id,
|
|
||||||
staff_uu_id=staff.uu_id.__str__(),
|
|
||||||
employee_id=employee.id,
|
|
||||||
employee_uu_id=employee.uu_id.__str__(),
|
|
||||||
reachable_event_list_id=reachable_event_list_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Update Redis
|
|
||||||
AuthActions.update_selected_to_redis(request=request, add_payload=company_token)
|
|
||||||
return ResponseHandler.success("Company selected successfully")
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _handle_occupant_selection(
|
|
||||||
cls, data: OccupantSelection, token_dict: OccupantTokenObject, request: Request
|
|
||||||
):
|
|
||||||
"""Handle occupant type selection"""
|
|
||||||
# Get occupant type
|
|
||||||
occupant_type = OccupantTypes.filter_by_one(
|
|
||||||
system=True, uu_id=data.occupant_uu_id
|
|
||||||
).data
|
|
||||||
if not occupant_type:
|
|
||||||
return ResponseHandler.not_found("Occupant Type not found")
|
|
||||||
|
|
||||||
# Get build part
|
|
||||||
build_part = BuildParts.filter_by_one(
|
|
||||||
system=True, uu_id=data.build_part_uu_id
|
|
||||||
).data
|
|
||||||
if not build_part:
|
|
||||||
return ResponseHandler.not_found("Build Part not found")
|
|
||||||
|
|
||||||
# Get build and company info
|
|
||||||
build = Build.filter_one(Build.id == build_part.build_id).data
|
|
||||||
related_company = RelationshipEmployee2Build.filter_one(
|
|
||||||
RelationshipEmployee2Build.member_id == build.id
|
|
||||||
).data
|
|
||||||
company_related = Companies.filter_one(
|
|
||||||
Companies.id == related_company.company_id
|
|
||||||
).data
|
|
||||||
responsible_employee = Employees.filter_one(
|
|
||||||
Employees.id == related_company.employee_id
|
|
||||||
).data
|
|
||||||
|
|
||||||
# Get selected occupant type
|
|
||||||
selected_occupant_type = BuildLivingSpace.filter_one(
|
|
||||||
BuildLivingSpace.occupant_type == occupant_type.id,
|
|
||||||
BuildLivingSpace.person_id == token_dict.person_id,
|
|
||||||
BuildLivingSpace.build_parts_id == build_part.id,
|
|
||||||
).data
|
|
||||||
if not selected_occupant_type:
|
|
||||||
return ResponseHandler.not_found("Selected occupant type not found")
|
|
||||||
|
|
||||||
# Get reachable events
|
|
||||||
reachable_event_list_id = Event2Occupant.get_event_id_by_build_living_space_id(
|
|
||||||
build_living_space_id=selected_occupant_type.id
|
|
||||||
)
|
|
||||||
|
|
||||||
# Create occupant token
|
|
||||||
occupant_token = OccupantToken(
|
|
||||||
living_space_id=selected_occupant_type.id,
|
|
||||||
living_space_uu_id=selected_occupant_type.uu_id.__str__(),
|
|
||||||
occupant_type_id=occupant_type.id,
|
|
||||||
occupant_type_uu_id=occupant_type.uu_id.__str__(),
|
|
||||||
occupant_type=occupant_type.occupant_type,
|
|
||||||
build_id=build.id,
|
|
||||||
build_uuid=build.uu_id.__str__(),
|
|
||||||
build_part_id=build_part.id,
|
|
||||||
build_part_uuid=build_part.uu_id.__str__(),
|
|
||||||
responsible_employee_id=responsible_employee.id,
|
|
||||||
responsible_employee_uuid=responsible_employee.uu_id.__str__(),
|
|
||||||
responsible_company_id=company_related.id,
|
|
||||||
responsible_company_uuid=company_related.uu_id.__str__(),
|
|
||||||
reachable_event_list_id=reachable_event_list_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Update Redis
|
|
||||||
AuthActions.update_selected_to_redis(
|
|
||||||
request=request, add_payload=occupant_token
|
|
||||||
)
|
|
||||||
return ResponseHandler.success("Occupant selected successfully")
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def authentication_select_company_or_occupant_type(
|
|
||||||
cls,
|
|
||||||
request: Request,
|
|
||||||
data: Union[EmployeeSelection, OccupantSelection],
|
|
||||||
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
|
|
||||||
):
|
|
||||||
"""Handle selection of company or occupant type"""
|
|
||||||
try:
|
|
||||||
if isinstance(token_dict, EmployeeTokenObject):
|
|
||||||
return cls._handle_employee_selection(data, token_dict, request)
|
|
||||||
elif isinstance(token_dict, OccupantTokenObject):
|
|
||||||
return cls._handle_occupant_selection(data, token_dict, request)
|
|
||||||
return ResponseHandler.error(
|
|
||||||
"Invalid token type", status_code=status.HTTP_400_BAD_REQUEST
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
return ResponseHandler.error(
|
|
||||||
str(e), status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationCheckTokenEventMethods(MethodToEvent):
|
|
||||||
event_type = "LOGIN"
|
|
||||||
event_description = "Check Token is valid for user"
|
|
||||||
event_category = "AUTHENTICATION"
|
|
||||||
|
|
||||||
__event_keys__ = {
|
|
||||||
"73d77e45-a33f-4f12-909e-3b56f00d8a12": "authentication_check_token_is_valid",
|
|
||||||
}
|
|
||||||
__event_validation__ = {
|
|
||||||
"73d77e45-a33f-4f12-909e-3b56f00d8a12": "authentication_check_token_is_valid",
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def authentication_check_token_is_valid(cls, request: Request):
|
|
||||||
try:
|
|
||||||
if RedisActions.get_object_via_access_key(request=request):
|
|
||||||
return ResponseHandler.success("Access Token is valid")
|
|
||||||
except HTTPException:
|
|
||||||
return ResponseHandler.unauthorized("Access Token is NOT valid")
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationRefreshEventMethods(MethodToEvent):
|
|
||||||
event_type = "LOGIN"
|
|
||||||
event_description = "Refresh user info using access token"
|
|
||||||
event_category = "AUTHENTICATION"
|
|
||||||
|
|
||||||
__event_keys__ = {
|
|
||||||
"48379bb2-ba81-4d8e-a9dd-58837cfcbf67": "authentication_refresh_user_info",
|
|
||||||
}
|
|
||||||
__event_validation__ = {
|
|
||||||
"48379bb2-ba81-4d8e-a9dd-58837cfcbf67": AuthenticationRefreshResponse,
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def authentication_refresh_user_info(
|
|
||||||
cls,
|
|
||||||
request: Request,
|
|
||||||
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
|
|
||||||
):
|
|
||||||
try:
|
|
||||||
access_token = request.headers.get(Auth.ACCESS_TOKEN_TAG)
|
|
||||||
if not access_token:
|
|
||||||
return ResponseHandler.unauthorized()
|
|
||||||
|
|
||||||
# Get user and token info
|
|
||||||
found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data
|
|
||||||
if not found_user:
|
|
||||||
return ResponseHandler.not_found("User not found")
|
|
||||||
user_token = UsersTokens.filter_one(
|
|
||||||
UsersTokens.domain == found_user.domain_name,
|
|
||||||
UsersTokens.user_id == found_user.id,
|
|
||||||
UsersTokens.token_type == "RememberMe",
|
|
||||||
).data
|
|
||||||
response_data = {
|
|
||||||
"access_token": access_token,
|
|
||||||
"refresh_token": getattr(user_token, "token", None),
|
|
||||||
"user": found_user.get_dict(),
|
|
||||||
}
|
|
||||||
return ResponseHandler.success(
|
|
||||||
"User info refreshed successfully",
|
|
||||||
data=response_data,
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
return ResponseHandler.error(str(e))
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationChangePasswordEventMethods(MethodToEvent):
|
|
||||||
event_type = "LOGIN"
|
|
||||||
event_description = "Change password with access token"
|
|
||||||
event_category = "AUTHENTICATION"
|
|
||||||
|
|
||||||
__event_keys__ = {
|
|
||||||
"f09f7c1a-bee6-4e32-8444-962ec8f39091": "authentication_change_password",
|
|
||||||
}
|
|
||||||
__event_validation__ = {
|
|
||||||
"f09f7c1a-bee6-4e32-8444-962ec8f39091": "authentication_change_password",
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def authentication_change_password(
|
|
||||||
cls,
|
|
||||||
request: Request,
|
|
||||||
data: ChangePassword,
|
|
||||||
token_dict: Union[EmployeeTokenObject, OccupantTokenObject],
|
|
||||||
):
|
|
||||||
try:
|
|
||||||
if not isinstance(token_dict, EmployeeTokenObject):
|
|
||||||
return ResponseHandler.unauthorized(
|
|
||||||
"Only employees can change password"
|
|
||||||
)
|
|
||||||
|
|
||||||
found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data
|
|
||||||
if not found_user:
|
|
||||||
return ResponseHandler.not_found("User not found")
|
|
||||||
|
|
||||||
if not found_user.check_password(data.old_password):
|
|
||||||
# UserLogger.log_password_change(
|
|
||||||
# request,
|
|
||||||
# found_user.id,
|
|
||||||
# "change",
|
|
||||||
# success=False,
|
|
||||||
# error="Invalid old password",
|
|
||||||
# )
|
|
||||||
return ResponseHandler.unauthorized("Old password is incorrect")
|
|
||||||
|
|
||||||
found_user.set_password(data.new_password)
|
|
||||||
# UserLogger.log_password_change(
|
|
||||||
# request, found_user.id, "change", success=True
|
|
||||||
# )
|
|
||||||
|
|
||||||
return ResponseHandler.success("Password changed successfully")
|
|
||||||
except Exception as e:
|
|
||||||
# UserLogger.log_password_change(
|
|
||||||
# request,
|
|
||||||
# found_user.id if found_user else None,
|
|
||||||
# "change",
|
|
||||||
# success=False,
|
|
||||||
# error=str(e),
|
|
||||||
# )
|
|
||||||
return ResponseHandler.error(str(e))
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationCreatePasswordEventMethods(MethodToEvent):
|
|
||||||
|
|
||||||
event_type = "LOGIN"
|
|
||||||
event_description = "Create password with password reset token requested via email"
|
|
||||||
event_category = "AUTHENTICATION"
|
|
||||||
|
|
||||||
__event_keys__ = {
|
|
||||||
"c519f9af-92e1-47b2-abf7-5a3316d075f7": "authentication_create_password",
|
|
||||||
}
|
|
||||||
__event_validation__ = {
|
|
||||||
"c519f9af-92e1-47b2-abf7-5a3316d075f7": "authentication_create_password",
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def authentication_create_password(cls, data: CreatePassword):
|
|
||||||
|
|
||||||
if not data.re_password == data.password:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_406_NOT_ACCEPTABLE, detail="Password must match"
|
|
||||||
)
|
|
||||||
if found_user := Users.filter_one(
|
|
||||||
Users.password_token == data.password_token
|
|
||||||
).data:
|
|
||||||
found_user.create_password(found_user=found_user, password=data.password)
|
|
||||||
found_user.password_token = ""
|
|
||||||
found_user.save()
|
|
||||||
send_email_completed = send_email(
|
|
||||||
subject=f"Dear {found_user.user_tag}, your password has been changed.",
|
|
||||||
receivers=[str(found_user.email)],
|
|
||||||
html=password_is_changed_template(user_name=found_user.user_tag),
|
|
||||||
)
|
|
||||||
if not send_email_completed:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=400, detail="Email can not be sent. Try again later"
|
|
||||||
)
|
|
||||||
return ResponseHandler.success(
|
|
||||||
"Password is created successfully",
|
|
||||||
data=found_user.get_dict(),
|
|
||||||
)
|
|
||||||
return ResponseHandler.not_found("Record not found")
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationDisconnectUserEventMethods(MethodToEvent):
|
|
||||||
|
|
||||||
event_type = "LOGIN"
|
|
||||||
event_description = "Disconnect all sessions of user in access token"
|
|
||||||
event_category = "AUTHENTICATION"
|
|
||||||
|
|
||||||
__event_keys__ = {
|
|
||||||
"8b586848-2fb3-4161-abbe-642157eec7ce": "authentication_disconnect_user",
|
|
||||||
}
|
|
||||||
__event_validation__ = {
|
|
||||||
"8b586848-2fb3-4161-abbe-642157eec7ce": "authentication_disconnect_user",
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def authentication_disconnect_user(
|
|
||||||
cls, data: Logout, token_dict: Union[EmployeeTokenObject, OccupantTokenObject]
|
|
||||||
):
|
|
||||||
found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data
|
|
||||||
if not found_user:
|
|
||||||
return ResponseHandler.not_found("User not found")
|
|
||||||
if already_tokens := RedisActions.get_object_via_user_uu_id(
|
|
||||||
user_id=str(found_user.uu_id)
|
|
||||||
):
|
|
||||||
for key, token_user in already_tokens.items():
|
|
||||||
RedisActions.delete(key)
|
|
||||||
selected_user = Users.filter_one(
|
|
||||||
Users.uu_id == token_user.get("uu_id"),
|
|
||||||
).data
|
|
||||||
selected_user.remove_refresher_token(
|
|
||||||
domain=data.domain, disconnect=True
|
|
||||||
)
|
|
||||||
return ResponseHandler.success(
|
|
||||||
"All sessions are disconnected",
|
|
||||||
data=selected_user.get_dict(),
|
|
||||||
)
|
|
||||||
return ResponseHandler.not_found("Invalid data")
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationLogoutEventMethods(MethodToEvent):
|
|
||||||
|
|
||||||
event_type = "LOGIN"
|
|
||||||
event_description = "Logout only single session of user which domain is provided"
|
|
||||||
event_category = "AUTHENTICATION"
|
|
||||||
|
|
||||||
__event_keys__ = {
|
|
||||||
"5cc22e4e-a0f7-4077-be41-1871feb3dfd1": "authentication_logout_user",
|
|
||||||
}
|
|
||||||
__event_validation__ = {
|
|
||||||
"5cc22e4e-a0f7-4077-be41-1871feb3dfd1": "authentication_logout_user",
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def authentication_logout_user(
|
|
||||||
cls, request: Request, data: Logout, token_dict: dict = None
|
|
||||||
):
|
|
||||||
token_user = None
|
|
||||||
if already_tokens := RedisActions.get_object_via_access_key(request=request):
|
|
||||||
for key in already_tokens:
|
|
||||||
token_user = RedisActions.get_json(key)
|
|
||||||
if token_user.get("domain") == data.domain:
|
|
||||||
RedisActions.delete(key)
|
|
||||||
selected_user = Users.filter_one(
|
|
||||||
Users.uu_id == token_user.get("uu_id"),
|
|
||||||
).data
|
|
||||||
selected_user.remove_refresher_token(domain=data.domain)
|
|
||||||
|
|
||||||
return ResponseHandler.success(
|
|
||||||
"Session is logged out",
|
|
||||||
data=token_user,
|
|
||||||
)
|
|
||||||
return ResponseHandler.not_found("Logout is not successfully completed")
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationRefreshTokenEventMethods(MethodToEvent):
|
|
||||||
|
|
||||||
event_type = "LOGIN"
|
|
||||||
event_description = "Refresh access token with refresher token"
|
|
||||||
event_category = "AUTHENTICATION"
|
|
||||||
|
|
||||||
__event_keys__ = {
|
|
||||||
"c90f3334-10c9-4181-b5ff-90d98a0287b2": "authentication_refresher_token",
|
|
||||||
}
|
|
||||||
__event_validation__ = {
|
|
||||||
"c90f3334-10c9-4181-b5ff-90d98a0287b2": AuthenticationRefreshResponse,
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def authentication_refresher_token(
|
|
||||||
# cls, request: Request, data: RefreshToken, token_dict: dict = None
|
|
||||||
cls,
|
|
||||||
request: Request,
|
|
||||||
data,
|
|
||||||
token_dict: dict = None,
|
|
||||||
):
|
|
||||||
token_refresher = UsersTokens.filter_by_one(
|
|
||||||
token=data.refresh_token,
|
|
||||||
domain=data.domain,
|
|
||||||
**UsersTokens.valid_record_dict,
|
|
||||||
).data
|
|
||||||
if not token_refresher:
|
|
||||||
return ResponseHandler.not_found("Invalid data")
|
|
||||||
if found_user := Users.filter_one(
|
|
||||||
Users.id == token_refresher.user_id,
|
|
||||||
).data:
|
|
||||||
found_user: Users = found_user
|
|
||||||
access_key = AuthActions.save_access_token_to_redis(
|
|
||||||
request=request, found_user=found_user, domain=data.domain
|
|
||||||
)
|
|
||||||
found_user.last_agent = request.headers.get("User-Agent", None)
|
|
||||||
found_user.last_platform = request.headers.get("Origin", None)
|
|
||||||
found_user.last_remote_addr = getattr(
|
|
||||||
request, "remote_addr", None
|
|
||||||
) or request.headers.get("X-Forwarded-For", None)
|
|
||||||
found_user.last_seen = str(system_arrow.now())
|
|
||||||
response_data = {
|
|
||||||
"access_token": access_key,
|
|
||||||
"refresh_token": data.refresh_token,
|
|
||||||
}
|
|
||||||
return ResponseHandler.success(
|
|
||||||
"User is logged in successfully via refresher token",
|
|
||||||
data=response_data,
|
|
||||||
)
|
|
||||||
return ResponseHandler.not_found("Invalid data")
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationForgotPasswordEventMethods(MethodToEvent):
|
|
||||||
|
|
||||||
event_type = "LOGIN"
|
|
||||||
event_description = "Send an email to user for a valid password reset token"
|
|
||||||
event_category = "AUTHENTICATION"
|
|
||||||
|
|
||||||
__event_keys__ = {
|
|
||||||
"e3ca6e24-b9f8-4127-949c-3bfa364e3513": "authentication_forgot_password",
|
|
||||||
}
|
|
||||||
__event_validation__ = {
|
|
||||||
"e3ca6e24-b9f8-4127-949c-3bfa364e3513": "authentication_forgot_password",
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def authentication_forgot_password(
|
|
||||||
cls,
|
|
||||||
request: Request,
|
|
||||||
data: Forgot,
|
|
||||||
):
|
|
||||||
found_user: Users = Users.check_user_exits(
|
|
||||||
access_key=data.access_key, domain=data.domain
|
|
||||||
)
|
|
||||||
forgot_key = AuthActions.save_access_token_to_redis(
|
|
||||||
request=request, found_user=found_user, domain=data.domain
|
|
||||||
)
|
|
||||||
forgot_link = ApiStatic.forgot_link(forgot_key=forgot_key)
|
|
||||||
send_email_completed = send_email(
|
|
||||||
subject=f"Dear {found_user.user_tag}, your forgot password link has been sent.",
|
|
||||||
receivers=[str(found_user.email)],
|
|
||||||
html=change_your_password_template(
|
|
||||||
user_name=found_user.user_tag, forgot_link=forgot_link
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if not send_email_completed:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=400, detail="Email can not be sent. Try again later"
|
|
||||||
)
|
|
||||||
found_user.password_token = forgot_key
|
|
||||||
found_user.password_token_is_valid = str(system_arrow.shift(days=1))
|
|
||||||
found_user.save()
|
|
||||||
|
|
||||||
return ResponseHandler.success(
|
|
||||||
"Password is change link is sent to your email or phone",
|
|
||||||
data={},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationResetPasswordEventMethods(MethodToEvent):
|
|
||||||
|
|
||||||
event_type = "UPDATE"
|
|
||||||
__event_keys__ = {
|
|
||||||
"af9e121e-24bb-44ac-a616-471d5754360e": "authentication_reset_password",
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def authentication_reset_password(cls, data: Forgot):
|
|
||||||
from sqlalchemy import or_
|
|
||||||
|
|
||||||
found_user = Users.query.filter(
|
|
||||||
or_(
|
|
||||||
Users.email == str(data.access_key).lower(),
|
|
||||||
Users.phone_number == str(data.access_key).replace(" ", ""),
|
|
||||||
),
|
|
||||||
).first()
|
|
||||||
if not found_user:
|
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
|
||||||
detail="Given access key or domain is not matching with the any user record.",
|
|
||||||
)
|
|
||||||
|
|
||||||
reset_password_token = found_user.reset_password_token(found_user=found_user)
|
|
||||||
send_email_completed = send_email(
|
|
||||||
subject=f"Dear {found_user.user_tag}, a password reset request has been received.",
|
|
||||||
receivers=[str(found_user.email)],
|
|
||||||
html=change_your_password_template(
|
|
||||||
user_name=found_user.user_tag,
|
|
||||||
forgot_link=ApiStatic.forgot_link(forgot_key=reset_password_token),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if not send_email_completed:
|
|
||||||
raise found_user.raise_http_exception(
|
|
||||||
status_code=400, message="Email can not be sent. Try again later"
|
|
||||||
)
|
|
||||||
return ResponseHandler.success(
|
|
||||||
"Password change link is sent to your email or phone",
|
|
||||||
data=found_user.get_dict(),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationDownloadAvatarEventMethods(MethodToEvent):
|
|
||||||
|
|
||||||
event_type = "LOGIN"
|
|
||||||
event_description = "Download avatar icon and profile info of user"
|
|
||||||
event_category = "AUTHENTICATION"
|
|
||||||
|
|
||||||
__event_keys__ = {
|
|
||||||
"c140cd5f-307f-4046-a93e-3ade032a57a7": "authentication_download_avatar",
|
|
||||||
}
|
|
||||||
__event_validation__ = {
|
|
||||||
"c140cd5f-307f-4046-a93e-3ade032a57a7": AuthenticationUserInfoResponse,
|
|
||||||
}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def authentication_download_avatar(
|
|
||||||
cls, token_dict: Union[EmployeeTokenObject, OccupantTokenObject]
|
|
||||||
):
|
|
||||||
if found_user := Users.filter_one(Users.id == token_dict.user_id).data:
|
|
||||||
expired_starts = str(
|
|
||||||
system_arrow.now() - system_arrow.get(str(found_user.expiry_ends))
|
|
||||||
)
|
|
||||||
expired_int = (
|
|
||||||
system_arrow.now() - system_arrow.get(str(found_user.expiry_ends))
|
|
||||||
).days
|
|
||||||
|
|
||||||
user_info = {
|
|
||||||
"lang": token_dict.lang,
|
|
||||||
"full_name": found_user.person.full_name,
|
|
||||||
"avatar": found_user.avatar,
|
|
||||||
"remember_me": found_user.remember_me,
|
|
||||||
"expiry_ends": str(found_user.expiry_ends),
|
|
||||||
"expired_str": expired_starts,
|
|
||||||
"expired_int": int(expired_int),
|
|
||||||
}
|
|
||||||
return ResponseHandler.success(
|
|
||||||
"Avatar and profile is shared via user credentials",
|
|
||||||
data=user_info,
|
|
||||||
)
|
|
||||||
return ResponseHandler.not_found("Invalid data")
|
|
||||||
|
|
||||||
|
|
||||||
AuthenticationLoginEventMethod = AuthenticationLoginEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/login")
|
|
||||||
)
|
|
||||||
AuthenticationSelectEventMethod = AuthenticationSelectEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/select")
|
|
||||||
)
|
|
||||||
AuthenticationCheckTokenEventMethod = AuthenticationCheckTokenEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/valid")
|
|
||||||
)
|
|
||||||
AuthenticationRefreshEventMethod = AuthenticationRefreshEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/refresh")
|
|
||||||
)
|
|
||||||
AuthenticationChangePasswordEventMethod = AuthenticationChangePasswordEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/change_password")
|
|
||||||
)
|
|
||||||
AuthenticationCreatePasswordEventMethod = AuthenticationCreatePasswordEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/create_password")
|
|
||||||
)
|
|
||||||
AuthenticationDisconnectUserEventMethod = AuthenticationDisconnectUserEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/disconnect")
|
|
||||||
)
|
|
||||||
AuthenticationLogoutEventMethod = AuthenticationLogoutEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/logout")
|
|
||||||
)
|
|
||||||
AuthenticationRefreshTokenEventMethod = AuthenticationRefreshTokenEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/refresher")
|
|
||||||
)
|
|
||||||
AuthenticationForgotPasswordEventMethod = AuthenticationForgotPasswordEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/forgot")
|
|
||||||
)
|
|
||||||
AuthenticationDownloadAvatarEventMethod = AuthenticationDownloadAvatarEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/avatar")
|
|
||||||
)
|
|
||||||
AuthenticationResetPasswordEventMethod = AuthenticationResetPasswordEventMethods(
|
|
||||||
action=ActionsSchema(endpoint="/authentication/reset_password")
|
|
||||||
)
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
|
|
||||||
from api_objects.auth.token_objects import EmployeeTokenObject, OccupantTokenObject
|
|
||||||
|
|
||||||
|
|
||||||
class RulesEvents(MethodToEvent): ...
|
|
||||||
|
|
@ -80,7 +80,7 @@ class BuildAreaCreateEventMethods(MethodToEvent):
|
||||||
selected_build = None
|
selected_build = None
|
||||||
if isinstance(token_dict, OccupantTokenObject):
|
if isinstance(token_dict, OccupantTokenObject):
|
||||||
if not token_dict.selected_occupant.build_uuid == data.build_uu_id:
|
if not token_dict.selected_occupant.build_uuid == data.build_uu_id:
|
||||||
BuildArea.raise_http_exception(
|
raise BuildArea.raise_http_exception(
|
||||||
status_code="HTTP_403_FORBIDDEN",
|
status_code="HTTP_403_FORBIDDEN",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"Occupant can not create build area for {data.build_uu_id}",
|
message=f"Occupant can not create build area for {data.build_uu_id}",
|
||||||
|
|
@ -96,7 +96,7 @@ class BuildAreaCreateEventMethods(MethodToEvent):
|
||||||
employee_id=token_dict.selected_company.employee_id
|
employee_id=token_dict.selected_company.employee_id
|
||||||
).all()
|
).all()
|
||||||
if not str(data.build_uu_id) in [str(build.uu_id) for build in build_ids]:
|
if not str(data.build_uu_id) in [str(build.uu_id) for build in build_ids]:
|
||||||
BuildArea.raise_http_exception(
|
raise BuildArea.raise_http_exception(
|
||||||
status_code="HTTP_403_FORBIDDEN",
|
status_code="HTTP_403_FORBIDDEN",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"Employee can not create build area for {data.build_uu_id}",
|
message=f"Employee can not create build area for {data.build_uu_id}",
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class BuildSitesListEventMethods(MethodToEvent):
|
||||||
)
|
)
|
||||||
employees_build_list = [build.address_id for build in employees_build.all()]
|
employees_build_list = [build.address_id for build in employees_build.all()]
|
||||||
if not employees_build_list:
|
if not employees_build_list:
|
||||||
BuildSites.raise_http_exception(
|
raise BuildSites.raise_http_exception(
|
||||||
status_code="HTTP_404_NOT_FOUND",
|
status_code="HTTP_404_NOT_FOUND",
|
||||||
error_case="NOT_FOUND",
|
error_case="NOT_FOUND",
|
||||||
message="Employee has no build sites registered",
|
message="Employee has no build sites registered",
|
||||||
|
|
@ -86,7 +86,7 @@ class BuildSitesCreateEventMethods(MethodToEvent):
|
||||||
):
|
):
|
||||||
if isinstance(token_dict, OccupantTokenObject):
|
if isinstance(token_dict, OccupantTokenObject):
|
||||||
if not token_dict.selected_occupant.build_uuid == data.build_uu_id:
|
if not token_dict.selected_occupant.build_uuid == data.build_uu_id:
|
||||||
BuildSites.raise_http_exception(
|
raise BuildSites.raise_http_exception(
|
||||||
status_code="HTTP_403_FORBIDDEN",
|
status_code="HTTP_403_FORBIDDEN",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"Occupant can not create build sites for {data.build_uu_id}",
|
message=f"Occupant can not create build sites for {data.build_uu_id}",
|
||||||
|
|
@ -99,7 +99,7 @@ class BuildSitesCreateEventMethods(MethodToEvent):
|
||||||
employee_id=token_dict.selected_company.employee_id
|
employee_id=token_dict.selected_company.employee_id
|
||||||
).all()
|
).all()
|
||||||
if not str(data.build_uu_id) in [str(build.uu_id) for build in build_ids]:
|
if not str(data.build_uu_id) in [str(build.uu_id) for build in build_ids]:
|
||||||
BuildSites.raise_http_exception(
|
raise BuildSites.raise_http_exception(
|
||||||
status_code="HTTP_403_FORBIDDEN",
|
status_code="HTTP_403_FORBIDDEN",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"Employee can not create build sites for {data.build_uu_id}",
|
message=f"Employee can not create build sites for {data.build_uu_id}",
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ class BuildingLivingSpacesListEventMethods(MethodToEvent):
|
||||||
Build.id == token_dict.selected_occupant.build_id,
|
Build.id == token_dict.selected_occupant.build_id,
|
||||||
).data
|
).data
|
||||||
if not occupants_build_id:
|
if not occupants_build_id:
|
||||||
Build.raise_http_exception(
|
raise Build.raise_http_exception(
|
||||||
status_code="HTTP_403_FORBIDDEN",
|
status_code="HTTP_403_FORBIDDEN",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"Occupant has no build registered in the system. Contact with your company.",
|
message=f"Occupant has no build registered in the system. Contact with your company.",
|
||||||
|
|
@ -57,7 +57,7 @@ class BuildingLivingSpacesListEventMethods(MethodToEvent):
|
||||||
BuildParts.build_id.in_(occupants_build_id.id),
|
BuildParts.build_id.in_(occupants_build_id.id),
|
||||||
).data
|
).data
|
||||||
if not occupants_build_parts:
|
if not occupants_build_parts:
|
||||||
Build.raise_http_exception(
|
raise Build.raise_http_exception(
|
||||||
status_code="HTTP_403_FORBIDDEN",
|
status_code="HTTP_403_FORBIDDEN",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"Occupant has no build parts registered in the system. Contact with your company.",
|
message=f"Occupant has no build parts registered in the system. Contact with your company.",
|
||||||
|
|
@ -80,7 +80,7 @@ class BuildingLivingSpacesListEventMethods(MethodToEvent):
|
||||||
employee_id=token_dict.selected_company.employee_id
|
employee_id=token_dict.selected_company.employee_id
|
||||||
)
|
)
|
||||||
if not build_id_list_query:
|
if not build_id_list_query:
|
||||||
Build.raise_http_exception(
|
raise Build.raise_http_exception(
|
||||||
status_code="HTTP_403_FORBIDDEN",
|
status_code="HTTP_403_FORBIDDEN",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"Employee has no build registered in the system. Contact with your supervisor.",
|
message=f"Employee has no build registered in the system. Contact with your supervisor.",
|
||||||
|
|
@ -92,7 +92,7 @@ class BuildingLivingSpacesListEventMethods(MethodToEvent):
|
||||||
),
|
),
|
||||||
).data
|
).data
|
||||||
if not build_part_id_list_query:
|
if not build_part_id_list_query:
|
||||||
Build.raise_http_exception(
|
raise Build.raise_http_exception(
|
||||||
status_code="HTTP_403_FORBIDDEN",
|
status_code="HTTP_403_FORBIDDEN",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"Employee has no build parts registered in the system. Contact with your supervisor.",
|
message=f"Employee has no build parts registered in the system. Contact with your supervisor.",
|
||||||
|
|
@ -142,7 +142,7 @@ class BuildingLivingSpacesCreateEventMethods(MethodToEvent):
|
||||||
BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]),
|
BuildParts.build_id.in_([build.id for build in build_id_list_query.all()]),
|
||||||
).data
|
).data
|
||||||
if not build_part:
|
if not build_part:
|
||||||
BuildLivingSpace.raise_http_exception(
|
raise BuildLivingSpace.raise_http_exception(
|
||||||
status_code="HTTP_404_NOT_FOUND",
|
status_code="HTTP_404_NOT_FOUND",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"{data.build_parts_uu_id} - Build Part is not found in database. Check build part uu_id",
|
message=f"{data.build_parts_uu_id} - Build Part is not found in database. Check build part uu_id",
|
||||||
|
|
@ -154,7 +154,7 @@ class BuildingLivingSpacesCreateEventMethods(MethodToEvent):
|
||||||
People.uu_id == data.person_uu_id,
|
People.uu_id == data.person_uu_id,
|
||||||
).data
|
).data
|
||||||
if not life_person:
|
if not life_person:
|
||||||
BuildLivingSpace.raise_http_exception(
|
raise BuildLivingSpace.raise_http_exception(
|
||||||
status_code="HTTP_404_NOT_FOUND",
|
status_code="HTTP_404_NOT_FOUND",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"{data.person_uu_id} - Living Person is not found in database.",
|
message=f"{data.person_uu_id} - Living Person is not found in database.",
|
||||||
|
|
@ -164,7 +164,7 @@ class BuildingLivingSpacesCreateEventMethods(MethodToEvent):
|
||||||
)
|
)
|
||||||
occupant_type = OccupantTypes.filter_by_one(uu_id=data.occupant_type_uu_id).data
|
occupant_type = OccupantTypes.filter_by_one(uu_id=data.occupant_type_uu_id).data
|
||||||
if not occupant_type:
|
if not occupant_type:
|
||||||
BuildLivingSpace.raise_http_exception(
|
raise BuildLivingSpace.raise_http_exception(
|
||||||
status_code="HTTP_404_NOT_FOUND",
|
status_code="HTTP_404_NOT_FOUND",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"{data.occupant_type_uu_id} - Occupant Type is not found in database. Check occupant type uu_id",
|
message=f"{data.occupant_type_uu_id} - Occupant Type is not found in database. Check occupant type uu_id",
|
||||||
|
|
@ -252,7 +252,7 @@ class BuildingLivingSpacesUpdateEventMethods(MethodToEvent):
|
||||||
),
|
),
|
||||||
).data
|
).data
|
||||||
if not build_part:
|
if not build_part:
|
||||||
BuildLivingSpace.raise_http_exception(
|
raise BuildLivingSpace.raise_http_exception(
|
||||||
status_code="HTTP_403_FORBIDDEN",
|
status_code="HTTP_403_FORBIDDEN",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"{data.life_person_uu_id} - Living Person is not found in database.",
|
message=f"{data.life_person_uu_id} - Living Person is not found in database.",
|
||||||
|
|
@ -264,7 +264,7 @@ class BuildingLivingSpacesUpdateEventMethods(MethodToEvent):
|
||||||
People.uu_id == data.life_person_uu_id or ""
|
People.uu_id == data.life_person_uu_id or ""
|
||||||
).data
|
).data
|
||||||
if not life_person:
|
if not life_person:
|
||||||
BuildLivingSpace.raise_http_exception(
|
raise BuildLivingSpace.raise_http_exception(
|
||||||
status_code="HTTP_403_FORBIDDEN",
|
status_code="HTTP_403_FORBIDDEN",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message=f"{data.life_person_uu_id} - Living Person is not found in database.",
|
message=f"{data.life_person_uu_id} - Living Person is not found in database.",
|
||||||
|
|
@ -290,7 +290,7 @@ class BuildingLivingSpacesUpdateEventMethods(MethodToEvent):
|
||||||
if data_dict["is_tenant_live"]:
|
if data_dict["is_tenant_live"]:
|
||||||
owner_person = getattr(last_living_space, "owner_person_id", None)
|
owner_person = getattr(last_living_space, "owner_person_id", None)
|
||||||
if not owner_person:
|
if not owner_person:
|
||||||
BuildLivingSpace.raise_http_exception(
|
raise BuildLivingSpace.raise_http_exception(
|
||||||
status_code="HTTP_403_FORBIDDEN",
|
status_code="HTTP_403_FORBIDDEN",
|
||||||
error_case="UNAUTHORIZED",
|
error_case="UNAUTHORIZED",
|
||||||
message="Owner person of build part is not defined. Please register owner of part first.",
|
message="Owner person of build part is not defined. Please register owner of part first.",
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ from api_objects.auth.token_objects import (
|
||||||
OccupantToken,
|
OccupantToken,
|
||||||
ApplicationToken,
|
ApplicationToken,
|
||||||
)
|
)
|
||||||
|
from api_objects.errors.errorHandlers import HTTPExceptionEvyos
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"OccupantTokenObject",
|
"OccupantTokenObject",
|
||||||
|
|
@ -14,4 +15,5 @@ __all__ = [
|
||||||
"CompanyToken",
|
"CompanyToken",
|
||||||
"OccupantToken",
|
"OccupantToken",
|
||||||
"ApplicationToken",
|
"ApplicationToken",
|
||||||
|
"HTTPExceptionEvyos",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ class ApplicationToken(BaseModel):
|
||||||
|
|
||||||
domain: Optional[str] = "app.evyos.com.tr"
|
domain: Optional[str] = "app.evyos.com.tr"
|
||||||
lang: Optional[str] = "TR"
|
lang: Optional[str] = "TR"
|
||||||
timezone: Optional[str] = "Europe/Istanbul"
|
timezone: Optional[str] = "GMT+3"
|
||||||
|
|
||||||
user_type: int = UserType.occupant.value
|
user_type: int = UserType.occupant.value
|
||||||
credentials: dict = None
|
credentials: dict = None
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,6 @@
|
||||||
from .errors_dictionary import ErrorMessages
|
|
||||||
|
|
||||||
|
|
||||||
class AlchemyError:
|
class HTTPExceptionError:
|
||||||
ERRORS_DICT = {
|
|
||||||
"100": "HTTP_100_CONTINUE",
|
|
||||||
"101": "HTTP_101_SWITCHING_PROTOCOLS",
|
|
||||||
"102": "HTTP_102_PROCESSING",
|
|
||||||
"103": "HTTP_103_EARLY_HINTS",
|
|
||||||
"200": "HTTP_200_OK",
|
|
||||||
"201": "HTTP_201_CREATED",
|
|
||||||
"202": "HTTP_202_ACCEPTED",
|
|
||||||
"203": "HTTP_203_NON_AUTHORITATIVE_INFORMATION",
|
|
||||||
"204": "HTTP_204_NO_CONTENT",
|
|
||||||
"205": "HTTP_205_RESET_CONTENT",
|
|
||||||
"206": "HTTP_206_PARTIAL_CONTENT",
|
|
||||||
"207": "HTTP_207_MULTI_STATUS",
|
|
||||||
"208": "HTTP_208_ALREADY_REPORTED",
|
|
||||||
"226": "HTTP_226_IM_USED",
|
|
||||||
"300": "HTTP_300_MULTIPLE_CHOICES",
|
|
||||||
"301": "HTTP_301_MOVED_PERMANENTLY",
|
|
||||||
"302": "HTTP_302_FOUND",
|
|
||||||
"303": "HTTP_303_SEE_OTHER",
|
|
||||||
"304": "HTTP_304_NOT_MODIFIED",
|
|
||||||
"305": "HTTP_305_USE_PROXY",
|
|
||||||
"306": "HTTP_306_RESERVED",
|
|
||||||
"307": "HTTP_307_TEMPORARY_REDIRECT",
|
|
||||||
"308": "HTTP_308_PERMANENT_REDIRECT",
|
|
||||||
"400": "HTTP_400_BAD_REQUEST",
|
|
||||||
"401": "HTTP_401_UNAUTHORIZED",
|
|
||||||
"402": "HTTP_402_PAYMENT_REQUIRED",
|
|
||||||
"403": "HTTP_403_FORBIDDEN",
|
|
||||||
"404": "HTTP_404_NOT_FOUND",
|
|
||||||
"405": "HTTP_405_METHOD_NOT_ALLOWED",
|
|
||||||
"406": "HTTP_406_NOT_ACCEPTABLE",
|
|
||||||
"407": "HTTP_407_PROXY_AUTHENTICATION_REQUIRED",
|
|
||||||
"408": "HTTP_408_REQUEST_TIMEOUT",
|
|
||||||
"409": "HTTP_409_CONFLICT",
|
|
||||||
"410": "HTTP_410_GONE",
|
|
||||||
"411": "HTTP_411_LENGTH_REQUIRED",
|
|
||||||
"412": "HTTP_412_PRECONDITION_FAILED",
|
|
||||||
"413": "HTTP_413_REQUEST_ENTITY_TOO_LARGE",
|
|
||||||
"414": "HTTP_414_REQUEST_URI_TOO_LONG",
|
|
||||||
"415": "HTTP_415_UNSUPPORTED_MEDIA_TYPE",
|
|
||||||
"416": "HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE",
|
|
||||||
"417": "HTTP_417_EXPECTATION_FAILED",
|
|
||||||
"418": "HTTP_418_IM_A_TEAPOT",
|
|
||||||
"421": "HTTP_421_MISDIRECTED_REQUEST",
|
|
||||||
"422": "HTTP_422_UNPROCESSABLE_ENTITY",
|
|
||||||
"423": "HTTP_423_LOCKED",
|
|
||||||
"424": "HTTP_424_FAILED_DEPENDENCY",
|
|
||||||
"426": "HTTP_426_UPGRADE_REQUIRED",
|
|
||||||
"428": "HTTP_428_PRECONDITION_REQUIRED",
|
|
||||||
"429": "HTTP_429_TOO_MANY_REQUESTS",
|
|
||||||
"431": "HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE",
|
|
||||||
"451": "HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS",
|
|
||||||
"500": "HTTP_500_INTERNAL_SERVER_ERROR",
|
|
||||||
}
|
|
||||||
ERRORS_KEYS = {
|
|
||||||
"delete": "DeletedRecord",
|
|
||||||
"update": "UpdatedRecord",
|
|
||||||
"create": "CreatedRecord",
|
|
||||||
"list": "ListedRecords",
|
|
||||||
"not_found": "RecordNotFound",
|
|
||||||
"already_exist": "AlreadyExists",
|
|
||||||
"not_deleted": "RecordNotDeleted",
|
|
||||||
"not_updated": "RecordNotUpdated",
|
|
||||||
"not_created": "RecordNotCreated",
|
|
||||||
"not_listed": "RecordsNotListed",
|
|
||||||
"not_confirm": "IsNotConfirmed",
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, lang):
|
def __init__(self, lang):
|
||||||
self.lang = lang
|
self.lang = lang
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
# class HTTPExceptionInstance:
|
||||||
|
|
||||||
|
# def __init__(self, statuses, exceptions, exceptions_dict, errors_dict, response_model, error_language_dict):
|
||||||
|
# self.EXCEPTIONS = exceptions # from fastapi.exceptions import HTTPException
|
||||||
|
# self.STATUSES = statuses # from fastapi import status
|
||||||
|
# self.EXCEPTION_DICTS: dict = exceptions_dict
|
||||||
|
# self.ERRORS_DICT: dict = errors_dict
|
||||||
|
# self.ERRORS_LANG: dict = error_language_dict
|
||||||
|
# self.RESPONSE_MODEL: Any = response_model
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPExceptionEvyos(Exception):
|
||||||
|
|
||||||
|
def __init__(self, error_code: str, lang: str):
|
||||||
|
self.error_code = error_code
|
||||||
|
self.lang = lang
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPExceptionEvyosHandler:
|
||||||
|
|
||||||
|
def __init__(self, statuses, exceptions, exceptions_dict, errors_dict, response_model, error_language_dict):
|
||||||
|
self.EXCEPTIONS = exceptions # from fastapi.exceptions import HTTPException
|
||||||
|
self.STATUSES = statuses # from fastapi import status
|
||||||
|
self.EXCEPTION_DICTS: dict = exceptions_dict
|
||||||
|
self.ERRORS_DICT: dict = errors_dict
|
||||||
|
self.ERRORS_LANG: dict = error_language_dict
|
||||||
|
self.RESPONSE_MODEL: Any = response_model
|
||||||
|
|
||||||
|
def retrieve_error_status_code(self, exc: HTTPExceptionEvyos):
|
||||||
|
grab_status = self.ERRORS_DICT.get(str(exc.error_code).upper(), "")
|
||||||
|
grab_status_code = self.EXCEPTION_DICTS.get(str(grab_status).upper(), "500")
|
||||||
|
return getattr(self.STATUSES, str(grab_status_code), getattr(self.STATUSES, "HTTP_500_INTERNAL_SERVER_ERROR"))
|
||||||
|
|
||||||
|
def retrieve_error_message(self, exc: HTTPExceptionEvyos):
|
||||||
|
message_by_lang = self.ERRORS_LANG.get(str(exc.lang).lower(), {})
|
||||||
|
message_by_code = message_by_lang.get(str(exc.error_code).upper(), "Unknown error")
|
||||||
|
return message_by_code
|
||||||
|
|
||||||
|
def handle_exception(self, request, exc: HTTPExceptionEvyos):
|
||||||
|
headers = getattr(request, "headers", {})
|
||||||
|
status_code = self.retrieve_error_status_code(exc)
|
||||||
|
error_message = self.retrieve_error_message(exc)
|
||||||
|
return self.RESPONSE_MODEL(
|
||||||
|
status_code=int(status_code),
|
||||||
|
content={"message": error_message, "lang": exc.lang},
|
||||||
|
)
|
||||||
|
|
||||||
|
class HTTPExceptionAnyHandler:
|
||||||
|
|
||||||
|
def __init__(self, response_model):
|
||||||
|
self.RESPONSE_MODEL: Any = response_model
|
||||||
|
|
||||||
|
def any_exception_handler(self, request, exc: Exception):
|
||||||
|
return self.RESPONSE_MODEL(
|
||||||
|
status_code=200,
|
||||||
|
content={"message": str(exc), "lang": None, "status_code": 417},
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
from .baseErrorCluster import (
|
||||||
|
BASE_ERRORS,
|
||||||
|
BASE_ERROR_LANGUAGE,
|
||||||
|
EXCEPTION_DICTS,
|
||||||
|
)
|
||||||
|
|
||||||
|
ERRORS_LANG = {
|
||||||
|
"tr": {
|
||||||
|
**BASE_ERROR_LANGUAGE["tr"],
|
||||||
|
},
|
||||||
|
"en": {
|
||||||
|
**BASE_ERROR_LANGUAGE["en"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ERRORS_DICT = {
|
||||||
|
**BASE_ERRORS,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
|
||||||
|
BASE_ERRORS = {
|
||||||
|
"NOT_CREATED": 405,
|
||||||
|
"NOT_DELETED": 405,
|
||||||
|
"NOT_UPDATED": 405,
|
||||||
|
"NOT_LISTED": 404,
|
||||||
|
"NOT_FOUND": 404,
|
||||||
|
"ALREADY_EXISTS": 400,
|
||||||
|
"IS_NOT_CONFIRMED": 405,
|
||||||
|
"NOT_AUTHORIZED": 401,
|
||||||
|
"NOT_VALID": 406,
|
||||||
|
"NOT_ACCEPTABLE": 406,
|
||||||
|
"INVALID_DATA": 422,
|
||||||
|
"UNKNOWN_ERROR": 502,
|
||||||
|
}
|
||||||
|
|
||||||
|
BASE_ERROR_LANGUAGE = {
|
||||||
|
"tr": {
|
||||||
|
"NOT_CREATED": "Kayıt oluşturulamadı.",
|
||||||
|
"NOT_DELETED": "Kayıt silinemedi.",
|
||||||
|
"NOT_UPDATED": "Kayıt güncellenemedi.",
|
||||||
|
"NOT_LISTED": "Kayıt listelenemedi.",
|
||||||
|
"NOT_FOUND": "Kayıt bulunamadı.",
|
||||||
|
"ALREADY_EXISTS": "Kayıt zaten mevcut.",
|
||||||
|
"IS_NOT_CONFIRMED": "Kayıt onaylanmadı.",
|
||||||
|
"NOT_AUTHORIZED": "Yetkisiz kullanıcı.",
|
||||||
|
"NOT_VALID": "Gecersiz veri.",
|
||||||
|
"NOT_ACCEPTABLE": "Gecersiz veri.",
|
||||||
|
"INVALID_DATA": "Gecersiz veri.",
|
||||||
|
"UNKNOWN_ERROR": "Bilinmeyen bir hata oluştu.",
|
||||||
|
},
|
||||||
|
"en": {
|
||||||
|
"NOT_CREATED": "Not Created.",
|
||||||
|
"NOT_DELETED": "Not Deleted.",
|
||||||
|
"NOT_UPDATED": "Not Updated.",
|
||||||
|
"NOT_LISTED": "Not Listed.",
|
||||||
|
"NOT_FOUND": "Not Found.",
|
||||||
|
"ALREADY_EXISTS": "Already Exists.",
|
||||||
|
"IS_NOT_CONFIRMED": "Not Confirmed.",
|
||||||
|
"NOT_AUTHORIZED": "Not Authorized.",
|
||||||
|
"NOT_VALID": "Not Valid.",
|
||||||
|
"NOT_ACCEPTABLE": "Not Acceptable.",
|
||||||
|
"INVALID_DATA": "Invalid Data.",
|
||||||
|
"UNKNOWN_ERROR": "Unknown Error occured.",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
from fastapi import status
|
||||||
|
EXCEPTION_DICTS = {
|
||||||
|
"100": "HTTP_100_CONTINUE",
|
||||||
|
"101": "HTTP_101_SWITCHING_PROTOCOLS",
|
||||||
|
"102": "HTTP_102_PROCESSING",
|
||||||
|
"103": "HTTP_103_EARLY_HINTS",
|
||||||
|
"200": "HTTP_200_OK",
|
||||||
|
"201": "HTTP_201_CREATED",
|
||||||
|
"202": "HTTP_202_ACCEPTED",
|
||||||
|
"203": "HTTP_203_NON_AUTHORITATIVE_INFORMATION",
|
||||||
|
"204": "HTTP_204_NO_CONTENT",
|
||||||
|
"205": "HTTP_205_RESET_CONTENT",
|
||||||
|
"206": "HTTP_206_PARTIAL_CONTENT",
|
||||||
|
"207": "HTTP_207_MULTI_STATUS",
|
||||||
|
"208": "HTTP_208_ALREADY_REPORTED",
|
||||||
|
"226": "HTTP_226_IM_USED",
|
||||||
|
"300": "HTTP_300_MULTIPLE_CHOICES",
|
||||||
|
"301": "HTTP_301_MOVED_PERMANENTLY",
|
||||||
|
"302": "HTTP_302_FOUND",
|
||||||
|
"303": "HTTP_303_SEE_OTHER",
|
||||||
|
"304": "HTTP_304_NOT_MODIFIED",
|
||||||
|
"305": "HTTP_305_USE_PROXY",
|
||||||
|
"306": "HTTP_306_RESERVED",
|
||||||
|
"307": "HTTP_307_TEMPORARY_REDIRECT",
|
||||||
|
"308": "HTTP_308_PERMANENT_REDIRECT",
|
||||||
|
"400": "HTTP_400_BAD_REQUEST",
|
||||||
|
"401": "HTTP_401_UNAUTHORIZED",
|
||||||
|
"402": "HTTP_402_PAYMENT_REQUIRED",
|
||||||
|
"403": "HTTP_403_FORBIDDEN",
|
||||||
|
"404": "HTTP_404_NOT_FOUND",
|
||||||
|
"405": "HTTP_405_METHOD_NOT_ALLOWED",
|
||||||
|
"406": "HTTP_406_NOT_ACCEPTABLE",
|
||||||
|
"407": "HTTP_407_PROXY_AUTHENTICATION_REQUIRED",
|
||||||
|
"408": "HTTP_408_REQUEST_TIMEOUT",
|
||||||
|
"409": "HTTP_409_CONFLICT",
|
||||||
|
"410": "HTTP_410_GONE",
|
||||||
|
"411": "HTTP_411_LENGTH_REQUIRED",
|
||||||
|
"412": "HTTP_412_PRECONDITION_FAILED",
|
||||||
|
"413": "HTTP_413_REQUEST_ENTITY_TOO_LARGE",
|
||||||
|
"414": "HTTP_414_REQUEST_URI_TOO_LONG",
|
||||||
|
"415": "HTTP_415_UNSUPPORTED_MEDIA_TYPE",
|
||||||
|
"416": "HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE",
|
||||||
|
"417": "HTTP_417_EXPECTATION_FAILED",
|
||||||
|
"418": "HTTP_418_IM_A_TEAPOT",
|
||||||
|
"421": "HTTP_421_MISDIRECTED_REQUEST",
|
||||||
|
"422": "HTTP_422_UNPROCESSABLE_ENTITY",
|
||||||
|
"423": "HTTP_423_LOCKED",
|
||||||
|
"424": "HTTP_424_FAILED_DEPENDENCY",
|
||||||
|
"426": "HTTP_426_UPGRADE_REQUIRED",
|
||||||
|
"428": "HTTP_428_PRECONDITION_REQUIRED",
|
||||||
|
"429": "HTTP_429_TOO_MANY_REQUESTS",
|
||||||
|
"431": "HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE",
|
||||||
|
"451": "HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS",
|
||||||
|
"500": "HTTP_500_INTERNAL_SERVER_ERROR",
|
||||||
|
"502": "HTTP_502_BAD_GATEWAY",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
from json import loads
|
|
||||||
|
|
||||||
|
|
||||||
class ErrorMessages:
|
|
||||||
__messages__ = {}
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_message(cls, message_key, lang):
|
|
||||||
return cls.__messages__[lang][message_key]
|
|
||||||
|
|
||||||
|
|
||||||
class ErrorHandlers:
|
|
||||||
def __init__(self, requests, exceptions, response_model, status):
|
|
||||||
self.requests = requests # from fastapi.requests import Request
|
|
||||||
self.exceptions = exceptions # from fastapi.exceptions import HTTPException
|
|
||||||
self.response_model = (
|
|
||||||
response_model # from fastapi.responses import JSONResponse
|
|
||||||
)
|
|
||||||
self.status = status # from fastapi import status
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(cls, requests, exceptions, response_model, status):
|
|
||||||
return cls(requests, exceptions, response_model, status)
|
|
||||||
|
|
||||||
def exception_handler_http(self, request, exc):
|
|
||||||
exc_detail = getattr(exc, "detail", None)
|
|
||||||
try:
|
|
||||||
detail = loads(str(exc_detail))
|
|
||||||
return self.response_model(
|
|
||||||
status_code=exc.status_code,
|
|
||||||
content={
|
|
||||||
"Data": detail.get("data", {}),
|
|
||||||
"Error": detail.get("error_case", "UNKNOWN"),
|
|
||||||
"Message": detail.get(
|
|
||||||
"message", "An error occurred while processing the request"
|
|
||||||
),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
return self.response_model(
|
|
||||||
status_code=exc.status_code,
|
|
||||||
content={"Error": str(exc_detail), "Message": f"{str(e)}", "Data": {}},
|
|
||||||
)
|
|
||||||
|
|
||||||
def exception_handler_exception(self, request, exc):
|
|
||||||
return self.response_model(
|
|
||||||
status_code=self.status.HTTP_417_EXPECTATION_FAILED,
|
|
||||||
content={"message": exc.__str__()},
|
|
||||||
)
|
|
||||||
|
|
@ -1,21 +1,22 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
import uuid
|
import uuid
|
||||||
import requests
|
import requests
|
||||||
|
import secrets
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from fastapi.exceptions import HTTPException
|
|
||||||
|
from api_services.redis.functions import RedisActions
|
||||||
from databases.no_sql_models.validations import (
|
from databases.no_sql_models.validations import (
|
||||||
PasswordHistoryViaUser,
|
PasswordHistoryViaUser,
|
||||||
AccessHistoryViaUser,
|
AccessHistoryViaUser,
|
||||||
)
|
)
|
||||||
from api_library.date_time_actions.date_functions import system_arrow, client_arrow
|
from api_library.date_time_actions.date_functions import system_arrow
|
||||||
from api_configs import ApiStatic, Auth
|
from api_configs import ApiStatic, Auth
|
||||||
|
|
||||||
|
|
||||||
class PasswordModule:
|
class PasswordModule:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_token(length=32):
|
def generate_token(length=32):
|
||||||
return uuid.uuid4().__str__()[:length]
|
return secrets.token_urlsafe(length)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_hashed_password(domain: str, id_: str, password: str):
|
def create_hashed_password(domain: str, id_: str, password: str):
|
||||||
|
|
@ -25,6 +26,10 @@ class PasswordModule:
|
||||||
def check_password(cls, domain, id_, password, password_hashed):
|
def check_password(cls, domain, id_, password, password_hashed):
|
||||||
return cls.create_hashed_password(domain, id_, password) == password_hashed
|
return cls.create_hashed_password(domain, id_, password) == password_hashed
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generate_access_token(cls):
|
||||||
|
return secrets.token_urlsafe(Auth.ACCESS_TOKEN_LENGTH)
|
||||||
|
|
||||||
|
|
||||||
class AuthModule(PasswordModule):
|
class AuthModule(PasswordModule):
|
||||||
|
|
||||||
|
|
@ -33,6 +38,7 @@ class AuthModule(PasswordModule):
|
||||||
from databases import Users
|
from databases import Users
|
||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
from fastapi import status
|
from fastapi import status
|
||||||
|
from fastapi.exceptions import HTTPException
|
||||||
|
|
||||||
found_user: Users = Users.query.filter(
|
found_user: Users = Users.query.filter(
|
||||||
or_(
|
or_(
|
||||||
|
|
@ -56,9 +62,6 @@ class AuthModule(PasswordModule):
|
||||||
)
|
)
|
||||||
return found_user
|
return found_user
|
||||||
|
|
||||||
def generate_access_token(self):
|
|
||||||
return self.generate_token(Auth.ACCESS_TOKEN_LENGTH)
|
|
||||||
|
|
||||||
def remove_refresher_token(self, domain, disconnect: bool = False):
|
def remove_refresher_token(self, domain, disconnect: bool = False):
|
||||||
from databases import UsersTokens
|
from databases import UsersTokens
|
||||||
|
|
||||||
|
|
@ -76,6 +79,8 @@ class AuthModule(PasswordModule):
|
||||||
UsersTokens.save()
|
UsersTokens.save()
|
||||||
|
|
||||||
def check_password_is_different(self, password):
|
def check_password_is_different(self, password):
|
||||||
|
from fastapi.exceptions import HTTPException
|
||||||
|
|
||||||
main_domain = self.get_main_domain_and_other_domains(get_main_domain=True)
|
main_domain = self.get_main_domain_and_other_domains(get_main_domain=True)
|
||||||
if self.hash_password == self.create_hashed_password(
|
if self.hash_password == self.create_hashed_password(
|
||||||
domain=main_domain, id_=self.uu_id, password=password
|
domain=main_domain, id_=self.uu_id, password=password
|
||||||
|
|
@ -88,9 +93,9 @@ class AuthModule(PasswordModule):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_password(found_user, password, password_token=None):
|
def create_password(found_user, password, password_token=None):
|
||||||
from databases import MongoQueryIdentity, Users
|
from databases import MongoQueryIdentity, Users
|
||||||
|
from fastapi.exceptions import HTTPException
|
||||||
|
|
||||||
found_user: Users = found_user
|
found_user: Users = found_user
|
||||||
|
|
||||||
if found_user.password_token:
|
if found_user.password_token:
|
||||||
replace_day = 0
|
replace_day = 0
|
||||||
try:
|
try:
|
||||||
|
|
@ -145,9 +150,7 @@ class AuthModule(PasswordModule):
|
||||||
return found_user.password_token
|
return found_user.password_token
|
||||||
|
|
||||||
def generate_refresher_token(self, domain: str, remember_me=False):
|
def generate_refresher_token(self, domain: str, remember_me=False):
|
||||||
from databases import (
|
from databases import UsersTokens
|
||||||
UsersTokens,
|
|
||||||
)
|
|
||||||
|
|
||||||
if remember_me:
|
if remember_me:
|
||||||
refresh_token = self.generate_token(Auth.REFRESHER_TOKEN_LENGTH)
|
refresh_token = self.generate_token(Auth.REFRESHER_TOKEN_LENGTH)
|
||||||
|
|
@ -183,6 +186,7 @@ class AuthModule(PasswordModule):
|
||||||
|
|
||||||
|
|
||||||
class UserLoginModule(AuthModule):
|
class UserLoginModule(AuthModule):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_login_details_to_mongo_database(
|
def set_login_details_to_mongo_database(
|
||||||
cls, found_user, headers_request, access_token, record_id
|
cls, found_user, headers_request, access_token, record_id
|
||||||
|
|
@ -212,8 +216,8 @@ class UserLoginModule(AuthModule):
|
||||||
"address": address_package,
|
"address": address_package,
|
||||||
"user_id": found_user.id,
|
"user_id": found_user.id,
|
||||||
}
|
}
|
||||||
already_exits = mongo_db.mongo_engine.filter_by(filter_query) or None
|
already_exits = mongo_db.mongo_engine.filter_by(filter_query).data
|
||||||
no_address_validates = mongo_db.mongo_engine.get_all()[0] == 0
|
no_address_validates = mongo_db.mongo_engine.get_all().data
|
||||||
access_via_user = query_engine.update_access_history_via_user(
|
access_via_user = query_engine.update_access_history_via_user(
|
||||||
AccessHistoryViaUser(
|
AccessHistoryViaUser(
|
||||||
**{
|
**{
|
||||||
|
|
@ -241,7 +245,6 @@ class UserLoginModule(AuthModule):
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
print("update_mongo", update_mongo)
|
|
||||||
else:
|
else:
|
||||||
insert_mongo = mongo_db.mongo_engine.insert(
|
insert_mongo = mongo_db.mongo_engine.insert(
|
||||||
payload={
|
payload={
|
||||||
|
|
@ -257,14 +260,14 @@ class UserLoginModule(AuthModule):
|
||||||
"is_first": True if no_address_validates else False,
|
"is_first": True if no_address_validates else False,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
print("insert_mongo", insert_mongo)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def login_user_with_credentials(cls, data, request):
|
def login_user_with_credentials(cls, data, request):
|
||||||
from databases.sql_models.identity.identity import Users
|
from databases.sql_models.identity.identity import Users
|
||||||
from ApiServices.api_handlers.auth_actions.auth import AuthActions
|
from ApiServices.api_handlers.auth_actions.auth import AuthActions
|
||||||
|
from fastapi.exceptions import HTTPException
|
||||||
|
|
||||||
found_user = Users.check_user_exits(
|
found_user: Users = Users.check_user_exits(
|
||||||
access_key=data.access_key, domain=data.domain
|
access_key=data.access_key, domain=data.domain
|
||||||
)
|
)
|
||||||
if not found_user:
|
if not found_user:
|
||||||
|
|
@ -280,19 +283,20 @@ class UserLoginModule(AuthModule):
|
||||||
)
|
)
|
||||||
|
|
||||||
if found_user.check_password(
|
if found_user.check_password(
|
||||||
domain=data.domain,
|
domain=data.domain,
|
||||||
id_=found_user.uu_id,
|
id_=found_user.uu_id,
|
||||||
password_hashed=found_user.hash_password,
|
password_hashed=found_user.hash_password,
|
||||||
password=data.password,
|
password=data.password,
|
||||||
):
|
):
|
||||||
access_object_to_redis = AuthActions.save_access_token_to_redis(
|
access_object_to_redis = AuthActions.save_access_token_to_redis(
|
||||||
request=request,
|
request=request,
|
||||||
found_user=found_user,
|
found_user=found_user,
|
||||||
domain=data.domain,
|
domain=data.domain,
|
||||||
# remember_me=data.remember_me,
|
# remember_me=data.remember_me,
|
||||||
)
|
)
|
||||||
print("access_object_to_redis", access_object_to_redis)
|
|
||||||
access_token = access_object_to_redis.get("access_token")
|
access_token = access_object_to_redis.get("access_token")
|
||||||
|
|
||||||
|
access_object_to_redis["user"] = found_user
|
||||||
headers_request = dict(request.headers)
|
headers_request = dict(request.headers)
|
||||||
headers_request["evyos-user-agent"] = headers_request.get("user-agent")
|
headers_request["evyos-user-agent"] = headers_request.get("user-agent")
|
||||||
headers_request["evyos-platform"] = headers_request.get("user-agent")
|
headers_request["evyos-platform"] = headers_request.get("user-agent")
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ from sqlalchemy import (
|
||||||
Numeric,
|
Numeric,
|
||||||
Integer,
|
Integer,
|
||||||
)
|
)
|
||||||
from sqlalchemy.orm import mapped_column, Mapped, relationship
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||||
|
|
||||||
from api_validations.validations_request import (
|
from api_validations.validations_request import (
|
||||||
InsertDecisionBook,
|
InsertDecisionBook,
|
||||||
|
|
@ -26,6 +26,19 @@ from api_validations.validations_request import (
|
||||||
InsertBuildDecisionBookProjects,
|
InsertBuildDecisionBookProjects,
|
||||||
)
|
)
|
||||||
from databases.sql_models.core_mixin import CrudCollection
|
from databases.sql_models.core_mixin import CrudCollection
|
||||||
|
from databases.language_models.building.decision_book import (
|
||||||
|
BuildDecisionBookLanguageModel,
|
||||||
|
BuildDecisionBookInvitationsLanguageModel,
|
||||||
|
BuildDecisionBookPersonLanguageModel,
|
||||||
|
BuildDecisionBookPersonOccupantsLanguageModel,
|
||||||
|
BuildDecisionBookItemsLanguageModel,
|
||||||
|
BuildDecisionBookItemsUnapprovedLanguageModel,
|
||||||
|
BuildDecisionBookPaymentsLanguageModel,
|
||||||
|
BuildDecisionBookLegalLanguageModel,
|
||||||
|
BuildDecisionBookProjectsLanguageModel,
|
||||||
|
BuildDecisionBookProjectPersonLanguageModel,
|
||||||
|
BuildDecisionBookProjectItemsLanguageModel,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BuildDecisionBook(CrudCollection):
|
class BuildDecisionBook(CrudCollection):
|
||||||
|
|
@ -44,6 +57,7 @@ class BuildDecisionBook(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "build_decision_book"
|
__tablename__ = "build_decision_book"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = BuildDecisionBookLanguageModel
|
||||||
|
|
||||||
decision_book_pdf_path: Mapped[str] = mapped_column(
|
decision_book_pdf_path: Mapped[str] = mapped_column(
|
||||||
String, server_default="", nullable=True
|
String, server_default="", nullable=True
|
||||||
|
|
@ -242,6 +256,7 @@ class BuildDecisionBookInvitations(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "build_decision_book_invitations"
|
__tablename__ = "build_decision_book_invitations"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = BuildDecisionBookInvitationsLanguageModel
|
||||||
|
|
||||||
build_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
build_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||||
build_uu_id: Mapped[str] = mapped_column(
|
build_uu_id: Mapped[str] = mapped_column(
|
||||||
|
|
@ -341,6 +356,7 @@ class BuildDecisionBookPerson(CrudCollection):
|
||||||
__tablename__ = "build_decision_book_person"
|
__tablename__ = "build_decision_book_person"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
__enum_list__ = [("management_typecode", "BuildManagementType", "bm")]
|
__enum_list__ = [("management_typecode", "BuildManagementType", "bm")]
|
||||||
|
__language_model__ = BuildDecisionBookPersonLanguageModel
|
||||||
|
|
||||||
dues_percent_discount: Mapped[int] = mapped_column(SmallInteger, server_default="0")
|
dues_percent_discount: Mapped[int] = mapped_column(SmallInteger, server_default="0")
|
||||||
dues_fix_discount: Mapped[float] = mapped_column(Numeric(10, 2), server_default="0")
|
dues_fix_discount: Mapped[float] = mapped_column(Numeric(10, 2), server_default="0")
|
||||||
|
|
@ -517,6 +533,7 @@ class BuildDecisionBookPersonOccupants(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "build_decision_book_person_occupants"
|
__tablename__ = "build_decision_book_person_occupants"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = BuildDecisionBookPersonOccupantsLanguageModel
|
||||||
|
|
||||||
build_decision_book_person_id: Mapped[int] = mapped_column(
|
build_decision_book_person_id: Mapped[int] = mapped_column(
|
||||||
ForeignKey("build_decision_book_person.id"), nullable=False
|
ForeignKey("build_decision_book_person.id"), nullable=False
|
||||||
|
|
@ -559,6 +576,7 @@ class BuildDecisionBookItems(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "build_decision_book_items"
|
__tablename__ = "build_decision_book_items"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = BuildDecisionBookItemsLanguageModel
|
||||||
|
|
||||||
item_order: Mapped[int] = mapped_column(
|
item_order: Mapped[int] = mapped_column(
|
||||||
SmallInteger, nullable=False, comment="Order Number of Item"
|
SmallInteger, nullable=False, comment="Order Number of Item"
|
||||||
|
|
@ -799,6 +817,7 @@ class BuildDecisionBookItemsUnapproved(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "build_decision_book_items_unapproved"
|
__tablename__ = "build_decision_book_items_unapproved"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = BuildDecisionBookItemsUnapprovedLanguageModel
|
||||||
|
|
||||||
item_objection: Mapped[str] = mapped_column(
|
item_objection: Mapped[str] = mapped_column(
|
||||||
Text, nullable=False, comment="Objection Content"
|
Text, nullable=False, comment="Objection Content"
|
||||||
|
|
@ -841,6 +860,7 @@ class BuildDecisionBookPayments(CrudCollection):
|
||||||
__tablename__ = "build_decision_book_payments"
|
__tablename__ = "build_decision_book_payments"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
__enum_list__ = [("receive_debit", "DebitTypes", "D")]
|
__enum_list__ = [("receive_debit", "DebitTypes", "D")]
|
||||||
|
__language_model__ = BuildDecisionBookPaymentsLanguageModel
|
||||||
|
|
||||||
payment_plan_time_periods: Mapped[str] = mapped_column(
|
payment_plan_time_periods: Mapped[str] = mapped_column(
|
||||||
String(10), nullable=False, comment="Payment Plan Time Periods"
|
String(10), nullable=False, comment="Payment Plan Time Periods"
|
||||||
|
|
@ -951,6 +971,7 @@ class BuildDecisionBookLegal(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "build_decision_book_legal"
|
__tablename__ = "build_decision_book_legal"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = BuildDecisionBookLegalLanguageModel
|
||||||
|
|
||||||
period_start_date: Mapped[TIMESTAMP] = mapped_column(
|
period_start_date: Mapped[TIMESTAMP] = mapped_column(
|
||||||
TIMESTAMP(timezone=True), nullable=False, comment="Start Date of Legal Period"
|
TIMESTAMP(timezone=True), nullable=False, comment="Start Date of Legal Period"
|
||||||
|
|
@ -1027,6 +1048,7 @@ class BuildDecisionBookProjects(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "build_decision_book_projects"
|
__tablename__ = "build_decision_book_projects"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = BuildDecisionBookProjectsLanguageModel
|
||||||
|
|
||||||
project_no: Mapped[str] = mapped_column(
|
project_no: Mapped[str] = mapped_column(
|
||||||
String(12), nullable=True, comment="Project Number of Decision Book"
|
String(12), nullable=True, comment="Project Number of Decision Book"
|
||||||
|
|
@ -1194,6 +1216,7 @@ class BuildDecisionBookProjectPerson(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "build_decision_book_project_person"
|
__tablename__ = "build_decision_book_project_person"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = BuildDecisionBookProjectPersonLanguageModel
|
||||||
# __enum_list__ = [("management_typecode", "ProjectTeamTypes", "PTT-EMP")]
|
# __enum_list__ = [("management_typecode", "ProjectTeamTypes", "PTT-EMP")]
|
||||||
|
|
||||||
dues_percent_discount: Mapped[int] = mapped_column(SmallInteger, server_default="0")
|
dues_percent_discount: Mapped[int] = mapped_column(SmallInteger, server_default="0")
|
||||||
|
|
@ -1226,6 +1249,7 @@ class BuildDecisionBookProjectItems(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "build_decision_book_project_items"
|
__tablename__ = "build_decision_book_project_items"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = BuildDecisionBookProjectItemsLanguageModel
|
||||||
|
|
||||||
item_header: Mapped[str] = mapped_column(
|
item_header: Mapped[str] = mapped_column(
|
||||||
String, nullable=False, comment="Item Header"
|
String, nullable=False, comment="Item Header"
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,13 @@ from sqlalchemy import (
|
||||||
Numeric,
|
Numeric,
|
||||||
)
|
)
|
||||||
from sqlalchemy.orm import mapped_column, Mapped
|
from sqlalchemy.orm import mapped_column, Mapped
|
||||||
|
|
||||||
|
from databases.language_models.company.employee import (
|
||||||
|
StaffLanguageModel,
|
||||||
|
EmployeesLanguageModel,
|
||||||
|
EmployeeHistoryLanguageModel,
|
||||||
|
EmployeesSalariesLanguageModel,
|
||||||
|
)
|
||||||
from databases.sql_models.core_mixin import CrudCollection
|
from databases.sql_models.core_mixin import CrudCollection
|
||||||
|
|
||||||
from api_validations.validations_request import InsertCompanyEmployees
|
from api_validations.validations_request import InsertCompanyEmployees
|
||||||
|
|
@ -14,6 +21,7 @@ class Staff(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "staff"
|
__tablename__ = "staff"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = StaffLanguageModel
|
||||||
|
|
||||||
staff_description: Mapped[str] = mapped_column(
|
staff_description: Mapped[str] = mapped_column(
|
||||||
String, server_default="", comment="Staff Description"
|
String, server_default="", comment="Staff Description"
|
||||||
|
|
@ -61,6 +69,7 @@ class Employees(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "employees"
|
__tablename__ = "employees"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = EmployeesLanguageModel
|
||||||
|
|
||||||
staff_id: Mapped[int] = mapped_column(ForeignKey("staff.id"))
|
staff_id: Mapped[int] = mapped_column(ForeignKey("staff.id"))
|
||||||
staff_uu_id: Mapped[str] = mapped_column(
|
staff_uu_id: Mapped[str] = mapped_column(
|
||||||
|
|
@ -81,6 +90,7 @@ class EmployeeHistory(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "employee_history"
|
__tablename__ = "employee_history"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = EmployeeHistoryLanguageModel
|
||||||
|
|
||||||
staff_id: Mapped[int] = mapped_column(
|
staff_id: Mapped[int] = mapped_column(
|
||||||
ForeignKey("staff.id"), nullable=False, comment="Staff ID"
|
ForeignKey("staff.id"), nullable=False, comment="Staff ID"
|
||||||
|
|
@ -105,6 +115,7 @@ class EmployeesSalaries(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "employee_salaries"
|
__tablename__ = "employee_salaries"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = EmployeesSalariesLanguageModel
|
||||||
|
|
||||||
gross_salary: Mapped[float] = mapped_column(
|
gross_salary: Mapped[float] = mapped_column(
|
||||||
Numeric(20, 6), nullable=False, comment="Gross Salary"
|
Numeric(20, 6), nullable=False, comment="Gross Salary"
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ from sqlalchemy_mixins.serialize import SerializeMixin
|
||||||
from sqlalchemy_mixins.repr import ReprMixin
|
from sqlalchemy_mixins.repr import ReprMixin
|
||||||
from sqlalchemy_mixins.smartquery import SmartQueryMixin
|
from sqlalchemy_mixins.smartquery import SmartQueryMixin
|
||||||
|
|
||||||
from api_library import DateTimeLocal, client_arrow, system_arrow
|
from api_library import DateTimeLocal, system_arrow
|
||||||
from databases.sql_models.sql_operations import FilterAttributes
|
from databases.sql_models.sql_operations import FilterAttributes
|
||||||
from databases.sql_models.postgres_database import Base
|
from databases.sql_models.postgres_database import Base
|
||||||
|
|
||||||
|
|
@ -138,14 +138,14 @@ class CrudMixin(Base, SmartQueryMixin, SessionMixin, FilterAttributes):
|
||||||
return True, int(val)
|
return True, int(val)
|
||||||
elif key_ == Mapped[TIMESTAMP]:
|
elif key_ == Mapped[TIMESTAMP]:
|
||||||
return True, str(
|
return True, str(
|
||||||
cls.client_arrow.get(str(val)).format("DD-MM-YYYY HH:mm:ss")
|
cls.client_arrow.get(str(val)).format("DD-MM-YYYY HH:mm:ss +0")
|
||||||
)
|
)
|
||||||
elif key_ == Mapped[str]:
|
elif key_ == Mapped[str]:
|
||||||
return True, str(val)
|
return True, str(val)
|
||||||
else:
|
else:
|
||||||
if isinstance(val, datetime.datetime):
|
if isinstance(val, datetime.datetime):
|
||||||
return True, str(
|
return True, str(
|
||||||
cls.client_arrow.get(str(val)).format("DD-MM-YYYY HH:mm:ss")
|
cls.client_arrow.get(str(val)).format("DD-MM-YYYY HH:mm:ss +0")
|
||||||
)
|
)
|
||||||
elif isinstance(value_type, bool):
|
elif isinstance(value_type, bool):
|
||||||
return True, bool(val)
|
return True, bool(val)
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,9 @@ class Users(CrudCollection, UserLoginModule, SelectAction):
|
||||||
person_uu_id: Mapped[str] = mapped_column(
|
person_uu_id: Mapped[str] = mapped_column(
|
||||||
String, server_default="", comment="Person UUID", index=True
|
String, server_default="", comment="Person UUID", index=True
|
||||||
)
|
)
|
||||||
|
local_timezone = mapped_column(
|
||||||
|
String, server_default="GMT+3", comment="Local timezone of user"
|
||||||
|
)
|
||||||
person = relationship("People", back_populates="user", foreign_keys=[person_id])
|
person = relationship("People", back_populates="user", foreign_keys=[person_id])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
@ -183,11 +186,6 @@ class Users(CrudCollection, UserLoginModule, SelectAction):
|
||||||
@classmethod
|
@classmethod
|
||||||
def credentials(cls):
|
def credentials(cls):
|
||||||
person_object = People.filter_by_one(system=True, id=cls.person_id).data
|
person_object = People.filter_by_one(system=True, id=cls.person_id).data
|
||||||
# if not person_object:
|
|
||||||
# raise HTTPException(
|
|
||||||
# status_code=401,
|
|
||||||
# detail="Person not found. Please contact the admin.",
|
|
||||||
# )
|
|
||||||
if person_object:
|
if person_object:
|
||||||
return {
|
return {
|
||||||
"person_id": person_object.id,
|
"person_id": person_object.id,
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ from databases.sql_models.core_mixin import CrudCollection
|
||||||
class ApiEnumDropdown(CrudCollection):
|
class ApiEnumDropdown(CrudCollection):
|
||||||
__tablename__ = "api_enum_dropdown"
|
__tablename__ = "api_enum_dropdown"
|
||||||
__exclude__fields__ = ["enum_class"]
|
__exclude__fields__ = ["enum_class"]
|
||||||
|
__language_model__ = None
|
||||||
|
|
||||||
id: Mapped[int] = mapped_column(primary_key=True)
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
uu_id: Mapped[str] = mapped_column(
|
uu_id: Mapped[str] = mapped_column(
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
from sqlalchemy import String, Boolean
|
from sqlalchemy import String
|
||||||
from databases.sql_models.core_mixin import CrudCollection
|
|
||||||
from sqlalchemy.orm import mapped_column, Mapped
|
from sqlalchemy.orm import mapped_column, Mapped
|
||||||
|
|
||||||
|
from databases.language_models.rules.rules import EndpointRestrictionLanguageModel
|
||||||
|
from databases.sql_models.core_mixin import CrudCollection
|
||||||
|
|
||||||
|
|
||||||
class EndpointRestriction(CrudCollection):
|
class EndpointRestriction(CrudCollection):
|
||||||
"""
|
"""
|
||||||
|
|
@ -10,6 +12,7 @@ class EndpointRestriction(CrudCollection):
|
||||||
|
|
||||||
__tablename__ = "endpoint_restriction"
|
__tablename__ = "endpoint_restriction"
|
||||||
__exclude__fields__ = []
|
__exclude__fields__ = []
|
||||||
|
__language_model__ = EndpointRestrictionLanguageModel
|
||||||
|
|
||||||
endpoint_function: Mapped[str] = mapped_column(
|
endpoint_function: Mapped[str] = mapped_column(
|
||||||
String, server_default="", comment="Function name of the API endpoint"
|
String, server_default="", comment="Function name of the API endpoint"
|
||||||
|
|
|
||||||
|
|
@ -50,18 +50,9 @@ class FilterAttributes:
|
||||||
"""Save the data via the metadata."""
|
"""Save the data via the metadata."""
|
||||||
try:
|
try:
|
||||||
meta_data = getattr(cls, "meta_data", {})
|
meta_data = getattr(cls, "meta_data", {})
|
||||||
meta_data_created = meta_data.get("created", False)
|
if meta_data.get("created", False):
|
||||||
if meta_data_created:
|
|
||||||
print("meta_data_created commit", meta_data_created)
|
|
||||||
cls.__session__.commit()
|
cls.__session__.commit()
|
||||||
print("meta_data_created rollback", meta_data_created)
|
|
||||||
cls.__session__.rollback()
|
cls.__session__.rollback()
|
||||||
# cls.raise_http_exception(
|
|
||||||
# status_code="HTTP_304_NOT_MODIFIED",
|
|
||||||
# error_case=meta_data.get("error_case", "Error on save and commit"),
|
|
||||||
# data={},
|
|
||||||
# message=meta_data.get("message", "Error on save and commit"),
|
|
||||||
# )
|
|
||||||
except SQLAlchemyError as e:
|
except SQLAlchemyError as e:
|
||||||
cls.raise_http_exception(
|
cls.raise_http_exception(
|
||||||
status_code="HTTP_304_NOT_MODIFIED",
|
status_code="HTTP_304_NOT_MODIFIED",
|
||||||
|
|
@ -233,8 +224,9 @@ class FilterAttributes:
|
||||||
for smart_iter in cls.filter_expr(**filter_list.get("query", {})):
|
for smart_iter in cls.filter_expr(**filter_list.get("query", {})):
|
||||||
if key := arg_left(smart_iter):
|
if key := arg_left(smart_iter):
|
||||||
args = cls.add_new_arg_to_args(args, key, smart_iter)
|
args = cls.add_new_arg_to_args(args, key, smart_iter)
|
||||||
query = cls._query().filter(*args)
|
query = cls._query()
|
||||||
cls.total_count = query.count()
|
cls.total_count = query.count()
|
||||||
|
query = query.filter(*args)
|
||||||
if cls.filter_attr:
|
if cls.filter_attr:
|
||||||
data_query = cls.add_query_to_filter(query, filter_list)
|
data_query = cls.add_query_to_filter(query, filter_list)
|
||||||
cls.filter_attr = None
|
cls.filter_attr = None
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,6 @@ def create_application_defaults_func(create_address=False):
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print("Service App Initial Default Runner is running")
|
print("Service App Initial Default Runner is running")
|
||||||
# do_alembic()
|
do_alembic()
|
||||||
create_application_defaults_func(create_address=True)
|
# create_application_defaults_func(create_address=True)
|
||||||
print("Service App Initial Default Runner is completed")
|
print("Service App Initial Default Runner is completed")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue