Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/auth/exceptions.py
Original file line number Diff line number Diff line change
@@ -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)},
)
5 changes: 4 additions & 1 deletion src/auth/rbac.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 0 additions & 29 deletions src/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from collections.abc import Sequence

from src.shared.errors import ErrorCode


Expand All @@ -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)},
)
2 changes: 0 additions & 2 deletions src/shared/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

class ErrorCode(IntEnum):
AUTH_INVALID_CREDENTIALS = 10001
AUTH_INVALID_PASSWORD = 10002
AUTH_TOKEN_INVALID = 10004
AUTH_ACCOUNT_LOCKED = 10005

Expand All @@ -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,
Expand Down
14 changes: 2 additions & 12 deletions tests/test_exceptions.py
Original file line number Diff line number Diff line change
@@ -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(
Expand Down Expand Up @@ -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"])

Expand Down
Loading