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
50 changes: 40 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
# Poetry specific files
.venv/
/dist/
/poetry.toml

# Python bytecode and caches
```
# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
*.so
*.egg-info/
.eggs/

# Virtual environments
venv/
.venv/
env/
ENV/
.ENV

# Build artifacts
build/
dist/
*.egg

# Testing
.coverage
htmlcov/
.pytest_cache/
.mypy_cache/
.ruff_cache/
.cache/

# Environment variables (secret keys)
# Logs
*.log

# Environment variables
.env
.env.local
*.env.*

# IDE settings
# IDE
.vscode/
.idea/
*.swp
*.swo
*.tmp

# OS
.DS_Store
Thumbs.db

# Coverage
coverage/
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from pydantic import BaseModel


class CreatePermissionCommand(BaseModel):
resource: str
action: str
description: str | None = None
31 changes: 31 additions & 0 deletions src/modules/authorization/application/create_permission/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from src.modules.authorization.application.create_permission.command import (
CreatePermissionCommand,
)
from src.modules.authorization.domain.entities.permission import Permission
from src.modules.authorization.domain.permissions import permission_key
from src.modules.authorization.domain.repositories.casbin_policy_repository import (
CasbinPolicyRepository,
)
from src.shared.unit_of_work import UnitOfWork


class CreatePermissionHandler:
def __init__(
self,
policy_repo: CasbinPolicyRepository,
unit_of_work: UnitOfWork,
):
self._policy_repo = policy_repo
self._unit_of_work = unit_of_work

async def execute(self, command: CreatePermissionCommand) -> Permission:
permission = Permission.create(
key=permission_key(command.resource, command.action),
resource=command.resource,
action=command.action,
description=command.description,
)
async with self._unit_of_work:
created = await self._policy_repo.create_permission(permission)
await self._unit_of_work.commit()
return created
6 changes: 6 additions & 0 deletions src/modules/authorization/application/create_role/command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from pydantic import BaseModel


class CreateRoleCommand(BaseModel):
name: str
description: str | None = None
23 changes: 23 additions & 0 deletions src/modules/authorization/application/create_role/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from src.modules.authorization.application.create_role.command import CreateRoleCommand
from src.modules.authorization.domain.entities.role import Role
from src.modules.authorization.domain.repositories.casbin_policy_repository import (
CasbinPolicyRepository,
)
from src.shared.unit_of_work import UnitOfWork


class CreateRoleHandler:
def __init__(
self,
policy_repo: CasbinPolicyRepository,
unit_of_work: UnitOfWork,
):
self._policy_repo = policy_repo
self._unit_of_work = unit_of_work

async def execute(self, command: CreateRoleCommand) -> Role:
role = Role.create(name=command.name, description=command.description)
async with self._unit_of_work:
created = await self._policy_repo.create_role(role)
await self._unit_of_work.commit()
return created
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from uuid import UUID

from pydantic import BaseModel


class DeletePermissionCommand(BaseModel):
permission_id: UUID
22 changes: 22 additions & 0 deletions src/modules/authorization/application/delete_permission/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from src.modules.authorization.application.delete_permission.command import (
DeletePermissionCommand,
)
from src.modules.authorization.domain.repositories.casbin_policy_repository import (
CasbinPolicyRepository,
)
from src.shared.unit_of_work import UnitOfWork


class DeletePermissionHandler:
def __init__(
self,
policy_repo: CasbinPolicyRepository,
unit_of_work: UnitOfWork,
):
self._policy_repo = policy_repo
self._unit_of_work = unit_of_work

async def execute(self, command: DeletePermissionCommand) -> None:
async with self._unit_of_work:
await self._policy_repo.delete_permission(command.permission_id)
await self._unit_of_work.commit()
7 changes: 7 additions & 0 deletions src/modules/authorization/application/delete_role/command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from uuid import UUID

from pydantic import BaseModel


class DeleteRoleCommand(BaseModel):
role_id: UUID
20 changes: 20 additions & 0 deletions src/modules/authorization/application/delete_role/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from src.modules.authorization.application.delete_role.command import DeleteRoleCommand
from src.modules.authorization.domain.repositories.casbin_policy_repository import (
CasbinPolicyRepository,
)
from src.shared.unit_of_work import UnitOfWork


class DeleteRoleHandler:
def __init__(
self,
policy_repo: CasbinPolicyRepository,
unit_of_work: UnitOfWork,
):
self._policy_repo = policy_repo
self._unit_of_work = unit_of_work

async def execute(self, command: DeleteRoleCommand) -> None:
async with self._unit_of_work:
await self._policy_repo.delete_role(command.role_id)
await self._unit_of_work.commit()
13 changes: 13 additions & 0 deletions src/modules/authorization/application/get_permission/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from src.modules.authorization.application.get_permission.query import GetPermissionQuery
from src.modules.authorization.domain.entities.permission import Permission
from src.modules.authorization.domain.repositories.casbin_policy_repository import (
CasbinPolicyRepository,
)


class GetPermissionQueryHandler:
def __init__(self, policy_repo: CasbinPolicyRepository):
self._policy_repo = policy_repo

async def execute(self, query: GetPermissionQuery) -> Permission | None:
return await self._policy_repo.get_permission(query.permission_id)
7 changes: 7 additions & 0 deletions src/modules/authorization/application/get_permission/query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from uuid import UUID

from pydantic import BaseModel


class GetPermissionQuery(BaseModel):
permission_id: UUID
15 changes: 15 additions & 0 deletions src/modules/authorization/application/get_role/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from uuid import UUID

from src.modules.authorization.application.get_role.query import GetRoleQuery
from src.modules.authorization.domain.entities.role import Role
from src.modules.authorization.domain.repositories.casbin_policy_repository import (
CasbinPolicyRepository,
)


class GetRoleQueryHandler:
def __init__(self, policy_repo: CasbinPolicyRepository):
self._policy_repo = policy_repo

async def execute(self, query: GetRoleQuery) -> Role | None:
return await self._policy_repo.get_role(query.role_id)
7 changes: 7 additions & 0 deletions src/modules/authorization/application/get_role/query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from uuid import UUID

from pydantic import BaseModel


class GetRoleQuery(BaseModel):
role_id: UUID
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class ListPermissionsQuery(BaseModel):
pass
13 changes: 13 additions & 0 deletions src/modules/authorization/application/list_roles/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from src.modules.authorization.application.list_roles.query import ListRolesQuery
from src.modules.authorization.domain.entities.role import Role
from src.modules.authorization.domain.repositories.casbin_policy_repository import (
CasbinPolicyRepository,
)


class ListRolesQueryHandler:
def __init__(self, policy_repo: CasbinPolicyRepository):
self._policy_repo = policy_repo

async def execute(self, query: ListRolesQuery) -> list[Role]:
return await self._policy_repo.list_roles()
5 changes: 5 additions & 0 deletions src/modules/authorization/application/list_roles/query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from pydantic import BaseModel


class ListRolesQuery(BaseModel):
pass
10 changes: 10 additions & 0 deletions src/modules/authorization/application/update_permission/command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from uuid import UUID

from pydantic import BaseModel


class UpdatePermissionCommand(BaseModel):
permission_id: UUID
resource: str | None = None
action: str | None = None
description: str | None = None
44 changes: 44 additions & 0 deletions src/modules/authorization/application/update_permission/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from src.modules.authorization.application.update_permission.command import (
UpdatePermissionCommand,
)
from src.modules.authorization.domain.entities.permission import Permission
from src.modules.authorization.domain.permissions import permission_key
from src.modules.authorization.domain.repositories.casbin_policy_repository import (
CasbinPolicyRepository,
)
from src.shared.unit_of_work import UnitOfWork


class UpdatePermissionHandler:
def __init__(
self,
policy_repo: CasbinPolicyRepository,
unit_of_work: UnitOfWork,
):
self._policy_repo = policy_repo
self._unit_of_work = unit_of_work

async def execute(self, command: UpdatePermissionCommand) -> Permission | None:
existing = await self._policy_repo.get_permission(command.permission_id)
if existing is None:
return None

resource = (
command.resource if command.resource is not None else existing.resource
)
action = command.action if command.action is not None else existing.action
permission = Permission(
id=command.permission_id,
key=permission_key(resource, action),
resource=resource,
action=action,
description=(
command.description
if command.description is not None
else existing.description
),
)
async with self._unit_of_work:
updated = await self._policy_repo.update_permission(permission)
await self._unit_of_work.commit()
return updated
9 changes: 9 additions & 0 deletions src/modules/authorization/application/update_role/command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from uuid import UUID

from pydantic import BaseModel


class UpdateRoleCommand(BaseModel):
role_id: UUID
name: str | None = None
description: str | None = None
35 changes: 35 additions & 0 deletions src/modules/authorization/application/update_role/handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from src.modules.authorization.application.update_role.command import UpdateRoleCommand
from src.modules.authorization.domain.entities.role import Role
from src.modules.authorization.domain.repositories.casbin_policy_repository import (
CasbinPolicyRepository,
)
from src.shared.unit_of_work import UnitOfWork


class UpdateRoleHandler:
def __init__(
self,
policy_repo: CasbinPolicyRepository,
unit_of_work: UnitOfWork,
):
self._policy_repo = policy_repo
self._unit_of_work = unit_of_work

async def execute(self, command: UpdateRoleCommand) -> Role | None:
existing = await self._policy_repo.get_role(command.role_id)
if existing is None:
return None

role = Role(
id=command.role_id,
name=command.name if command.name is not None else existing.name,
description=(
command.description
if command.description is not None
else existing.description
),
)
async with self._unit_of_work:
updated = await self._policy_repo.update_role(role)
await self._unit_of_work.commit()
return updated
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from datetime import datetime
from uuid import UUID

from src.core.authorization.domain.service import AuthorizationService
from src.core.authorization.infrastructure.repositories.casbin_policy_repository import (
from src.modules.authorization.domain.permissions import permission_key
from src.modules.authorization.domain.services.authorization_service import (
AuthorizationService,
)
from src.modules.authorization.infrastructure.repositories.casbin_policy_repository import (
SQLAlchemyCasbinPolicyRepository,
)
from src.core.authorization.permissions import permission_key
from src.modules.authorization import Permission, Role
from src.modules.authorization.domain.entities.permission import Permission
from src.modules.authorization.domain.entities.role import Role
from src.shared.utils.cursor import CursorDirection

CASBIN_MODEL_TEXT = """
Expand Down
Loading
Loading