Таска 3: разделение кастомных эксепшенов #2

Open
skvachuk wants to merge 5 commits from feature/3 into develop
8 changed files with 39 additions and 12 deletions
Showing only changes of commit 35b968d288 - Show all commits

View File

@@ -8,3 +8,6 @@ from src.application.domain.exceptions.internal_exception import InternalExcepti
from src.application.domain.exceptions.service_unavailable_exception import ServiceUnavailableException from src.application.domain.exceptions.service_unavailable_exception import ServiceUnavailableException
from src.application.domain.exceptions.too_many_requests_exception import TooManyRequestsException from src.application.domain.exceptions.too_many_requests_exception import TooManyRequestsException
from src.application.domain.exceptions.csrf_error_exception import CsrfErrorException from src.application.domain.exceptions.csrf_error_exception import CsrfErrorException
from src.application.domain.exceptions.jwt_error_exception import JwtErrorException
from src.application.domain.exceptions.data_base_error_exception import DataBaseErrorException
from src.application.domain.exceptions.rate_limit_error_exception import RateLimitErrorException

View File

@@ -0,0 +1,8 @@
from src.application.domain.exceptions.application_exceptions import ApplicationException
from typing import Mapping
class DataBaseErrorException(ApplicationException):
def __init__(self, message: str = 'Database error occurred', headers: Mapping[str, str] | None = None):
super().__init__(500, message, headers)

View File

@@ -0,0 +1,8 @@
from src.application.domain.exceptions.application_exceptions import ApplicationException
from typing import Mapping
class JwtErrorException(ApplicationException):
def __init__(self, message: str = 'JWT error occurred', headers: Mapping[str, str] | None = None):
super().__init__(500, message, headers)

View File

@@ -0,0 +1,8 @@
from src.application.domain.exceptions.application_exceptions import ApplicationException
from typing import Mapping
class RateLimitErrorException(ApplicationException):
def __init__(self, message: str = 'Rate limit error occurred', headers: Mapping[str, str] | None = None):
super().__init__(500, message, headers)

View File

@@ -3,7 +3,7 @@ from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from src.application.contracts import ILogger from src.application.contracts import ILogger
from src.application.domain.exceptions import ApplicationException, BadRequestException, InternalException, NotFoundException from src.application.domain.exceptions import ApplicationException, BadRequestException, DataBaseErrorException, NotFoundException
from src.application.abstractions.repositories import IUserRepository from src.application.abstractions.repositories import IUserRepository
from src.application.domain.entities import UserEntity from src.application.domain.entities import UserEntity
from src.infrastructure.database.models import UserModel from src.infrastructure.database.models import UserModel
@@ -60,7 +60,7 @@ class UserRepository(IUserRepository):
raise raise
except SQLAlchemyError as exception: except SQLAlchemyError as exception:
self._logger.exception(str(exception)) self._logger.exception(str(exception))
raise InternalException(message=f'Database error: {str(exception)}') raise DataBaseErrorException(message=f'Database error: {str(exception)}')
async def _update_field(self, user_id: str, **fields: object) -> UserEntity: async def _update_field(self, user_id: str, **fields: object) -> UserEntity:
try: try:
@@ -74,7 +74,7 @@ class UserRepository(IUserRepository):
raise raise
except SQLAlchemyError as exception: except SQLAlchemyError as exception:
self._logger.exception(str(exception)) self._logger.exception(str(exception))
raise InternalException(message=f'Database error: {str(exception)}') raise DataBaseErrorException(message=f'Database error: {str(exception)}')
async def set_phone(self, user_id: str, phone: str) -> UserEntity: async def set_phone(self, user_id: str, phone: str) -> UserEntity:
return await self._update_field(user_id, phone=phone) return await self._update_field(user_id, phone=phone)
@@ -100,7 +100,7 @@ class UserRepository(IUserRepository):
raise raise
except SQLAlchemyError as exception: except SQLAlchemyError as exception:
self._logger.exception(str(exception)) self._logger.exception(str(exception))
raise InternalException(message=f'Database error: {str(exception)}') raise DataBaseErrorException(message=f'Database error: {str(exception)}')
async def set_password(self, user_id: str, password_hash: str) -> UserEntity: async def set_password(self, user_id: str, password_hash: str) -> UserEntity:
return await self._update_field(user_id, password_hash=password_hash) return await self._update_field(user_id, password_hash=password_hash)
@@ -121,7 +121,7 @@ class UserRepository(IUserRepository):
return result.scalar_one_or_none() is not None return result.scalar_one_or_none() is not None
except SQLAlchemyError as exception: except SQLAlchemyError as exception:
self._logger.exception(str(exception)) self._logger.exception(str(exception))
raise InternalException(message=f'Database error: {str(exception)}') raise DataBaseErrorException(message=f'Database error: {str(exception)}')
async def get_user_by_email(self, email: str) -> UserEntity | None: async def get_user_by_email(self, email: str) -> UserEntity | None:
try: try:
@@ -139,4 +139,4 @@ class UserRepository(IUserRepository):
return self._to_entity(user) return self._to_entity(user)
except SQLAlchemyError as exception: except SQLAlchemyError as exception:
self._logger.exception(str(exception)) self._logger.exception(str(exception))
raise InternalException(message=f'Database error: {str(exception)}') raise DataBaseErrorException(message=f'Database error: {str(exception)}')

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
from jose import jwt, ExpiredSignatureError, JWTError from jose import jwt, ExpiredSignatureError, JWTError
from src.application.contracts import ILogger, IJwtService from src.application.contracts import ILogger, IJwtService
from src.application.domain.dto import AccessTokenPayload from src.application.domain.dto import AccessTokenPayload
from src.application.domain.exceptions import ApplicationException, UnauthorizedException, InternalException from src.application.domain.exceptions import ApplicationException, UnauthorizedException, JwtErrorException
from src.infrastructure.config.settings import settings from src.infrastructure.config.settings import settings
from src.infrastructure.vault import JwtKeyStore from src.infrastructure.vault import JwtKeyStore
@@ -106,4 +106,4 @@ class JwtService(IJwtService):
except Exception as exception: except Exception as exception:
self._logger.error(f'Unexpected JWT decode error kid={kid} error={str(exception)}') self._logger.error(f'Unexpected JWT decode error kid={kid} error={str(exception)}')
raise InternalException(message='JWT decode failed') raise JwtErrorException(message='JWT decode failed')

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
import asyncio import asyncio
from datetime import datetime, timezone from datetime import datetime, timezone
from src.application.domain.dto import JwtPublicKeySet, JwtPublicKey from src.application.domain.dto import JwtPublicKeySet, JwtPublicKey
from src.application.domain.exceptions import InternalException from src.application.domain.exceptions import JwtErrorException
from src.infrastructure.vault.client import VaultClient from src.infrastructure.vault.client import VaultClient
@@ -52,7 +52,7 @@ class JwtKeyStore:
@classmethod @classmethod
def get_instance(cls) -> 'JwtKeyStore': def get_instance(cls) -> 'JwtKeyStore':
if cls._instance is None: if cls._instance is None:
raise InternalException(message='JwtKeyStore not initialized') raise JwtErrorException(message='JwtKeyStore not initialized')
return cls._instance return cls._instance
def _read_keyset_sync(self) -> JwtPublicKeySet: def _read_keyset_sync(self) -> JwtPublicKeySet:

View File

@@ -7,7 +7,7 @@ from fastapi import Request
from redis.asyncio.client import Redis from redis.asyncio.client import Redis
from src.application.contracts import ILogger from src.application.contracts import ILogger
from src.application.domain.exceptions import ( from src.application.domain.exceptions import (
InternalException, RateLimitErrorException,
ServiceUnavailableException, ServiceUnavailableException,
TooManyRequestsException, TooManyRequestsException,
) )
@@ -128,7 +128,7 @@ def rate_limit(
ident = _call_key_builder(key_builder, request, args, kwargs) # type: ignore[arg-type] ident = _call_key_builder(key_builder, request, args, kwargs) # type: ignore[arg-type]
except Exception as e: except Exception as e:
logger.error(f'RateLimit key_builder failed error={str(e)}') logger.error(f'RateLimit key_builder failed error={str(e)}')
raise InternalException(message='Rate limiter key_builder failed') raise RateLimitErrorException(message='Rate limiter key_builder failed')
route = request.url.path route = request.url.path
method = request.method method = request.method