diff --git a/src/auth/exceptions.py b/src/auth/exceptions.py new file mode 100644 index 0000000..f892bf8 --- /dev/null +++ b/src/auth/exceptions.py @@ -0,0 +1,22 @@ +from collections.abc import Sequence + +from src.exceptions import BusinessException +from src.shared.errors import ErrorCode + + +class InsufficientPermissionException(BusinessException): + def __init__(self, required: Sequence[str]): + super().__init__( + code=ErrorCode.PERM_INSUFFICIENT, + msg="Insufficient permissions", + data={"required": list(required)}, + ) + + +class InsufficientRoleException(BusinessException): + def __init__(self, required: Sequence[str]): + super().__init__( + code=ErrorCode.ROLE_INSUFFICIENT, + msg="Insufficient roles", + data={"required": list(required)}, + ) diff --git a/src/auth/rbac.py b/src/auth/rbac.py index 50a790c..0698574 100644 --- a/src/auth/rbac.py +++ b/src/auth/rbac.py @@ -9,7 +9,10 @@ from src.audit.schemas import AuditAction, AuditResult from src.audit.service import extract_client_info from src.auth.models import Permission, Role, RolePermission, User, UserRole -from src.exceptions import InsufficientPermissionException, InsufficientRoleException +from src.auth.exceptions import ( + InsufficientPermissionException, + InsufficientRoleException, +) from src.session import get_session from . import current_user diff --git a/src/exceptions.py b/src/exceptions.py index c87db4a..0dc63d5 100644 --- a/src/exceptions.py +++ b/src/exceptions.py @@ -1,5 +1,3 @@ -from collections.abc import Sequence - from src.shared.errors import ErrorCode @@ -12,30 +10,3 @@ def __init__(self, code: ErrorCode, msg: str, data: dict | None = None): def __str__(self) -> str: return f"[{self.code}] {self.msg}" - - -class InvalidPasswordException(BusinessException): - def __init__(self, remaining_attempts: int): - super().__init__( - code=ErrorCode.AUTH_INVALID_PASSWORD, - msg=f"Invalid password, {remaining_attempts} attempts remaining", - data={"remaining_attempts": remaining_attempts}, - ) - - -class InsufficientPermissionException(BusinessException): - def __init__(self, required: Sequence[str]): - super().__init__( - code=ErrorCode.PERM_INSUFFICIENT, - msg="Insufficient permissions", - data={"required": list(required)}, - ) - - -class InsufficientRoleException(BusinessException): - def __init__(self, required: Sequence[str]): - super().__init__( - code=ErrorCode.ROLE_INSUFFICIENT, - msg="Insufficient roles", - data={"required": list(required)}, - ) diff --git a/src/shared/errors.py b/src/shared/errors.py index fd160b8..81bc616 100644 --- a/src/shared/errors.py +++ b/src/shared/errors.py @@ -3,7 +3,6 @@ class ErrorCode(IntEnum): AUTH_INVALID_CREDENTIALS = 10001 - AUTH_INVALID_PASSWORD = 10002 AUTH_TOKEN_INVALID = 10004 AUTH_ACCOUNT_LOCKED = 10005 @@ -23,7 +22,6 @@ class ErrorCode(IntEnum): ERROR_CODE_TO_HTTP = { ErrorCode.AUTH_INVALID_CREDENTIALS: 401, - ErrorCode.AUTH_INVALID_PASSWORD: 401, ErrorCode.AUTH_TOKEN_INVALID: 401, ErrorCode.AUTH_ACCOUNT_LOCKED: 403, ErrorCode.USER_NOT_FOUND: 404, diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index e9f13e1..0c480a1 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -1,12 +1,11 @@ import pytest from src.shared.errors import ErrorCode -from src.exceptions import ( - BusinessException, +from src.auth.exceptions import ( InsufficientPermissionException, InsufficientRoleException, - InvalidPasswordException, ) +from src.exceptions import BusinessException @pytest.mark.parametrize( @@ -55,15 +54,6 @@ def test_business_exception_exposes_code_message_data_and_string( assert str(exc) == expected_str -def test_domain_exception_includes_remaining_attempts_in_message_and_data(): - exc = InvalidPasswordException(remaining_attempts=3) - - assert exc.code == ErrorCode.AUTH_INVALID_PASSWORD - assert exc.msg == "Invalid password, 3 attempts remaining" - assert exc.data == {"remaining_attempts": 3} - assert str(exc) == "[10002] Invalid password, 3 attempts remaining" - - def test_insufficient_permission_exception_includes_required_and_user_perms(): exc = InsufficientPermissionException(required=["admin:delete", "admin:create"])