Skip to content

Commit 989280b

Browse files
committed
Add authorization infrastructure with Casbin policy management
- New SQLAlchemy models for authorization including CasbinRuleModel, PermissionModel, AuthorizationResourceModel, RoleModel, RolePermissionModel, and UserHasRoleModel with proper relationships and constraints - Implementation of SQLAlchemyCasbinPolicyRepository with full CRUD operations for roles, permissions, and policies including cursor-based pagination - CasbinAuthorizationService integrating with the repository layer and providing dynamic enforcer building for access control decisions - Infrastructure setup for authorization module with proper domain entities, services, and repository patterns following the application architecture This commit establishes a comprehensive authorization system backend with database persistence, supporting role-based access control through Casbin policies and efficient data management through SQLAlchemy ORM.
1 parent a256fae commit 989280b

33 files changed

Lines changed: 735 additions & 45 deletions

File tree

.gitignore

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,6 @@
11
```
2-
# Python
32
__pycache__/
43
*.pyc
54
*.pyo
65
*.pyd
7-
.Python
8-
*.so
9-
*.egg-info/
10-
.eggs/
11-
12-
# Virtual environments
13-
venv/
14-
.venv/
15-
env/
16-
ENV/
17-
.ENV
18-
19-
# Build artifacts
20-
build/
21-
dist/
22-
*.egg
23-
24-
# Testing
25-
.coverage
26-
htmlcov/
27-
.pytest_cache/
28-
.mypy_cache/
29-
30-
# Logs
31-
*.log
32-
33-
# Environment variables
34-
.env
35-
.env.local
36-
*.env.*
37-
38-
# IDE
39-
.vscode/
40-
.idea/
41-
*.swp
42-
*.swo
43-
*.tmp
44-
45-
# OS
46-
.DS_Store
47-
Thumbs.db
48-
49-
# Coverage
50-
coverage/
516
```

src/core/authorization/infrastructure/models/__init__.py

Whitespace-only changes.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from sqlalchemy import String
2+
from sqlalchemy.orm import Mapped, mapped_column
3+
4+
from src.shared.database.model import Base
5+
6+
7+
class CasbinRuleModel(Base):
8+
__tablename__ = "casbin_rules"
9+
10+
ptype: Mapped[str] = mapped_column(String(16), index=True)
11+
v0: Mapped[str | None] = mapped_column(String(255), index=True, nullable=True)
12+
v1: Mapped[str | None] = mapped_column(String(255), index=True, nullable=True)
13+
v2: Mapped[str | None] = mapped_column(String(255), index=True, nullable=True)
14+
v3: Mapped[str | None] = mapped_column(String(255), nullable=True)
15+
v4: Mapped[str | None] = mapped_column(String(255), nullable=True)
16+
v5: Mapped[str | None] = mapped_column(String(255), nullable=True)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from uuid import UUID
2+
3+
from sqlalchemy import String, UniqueConstraint
4+
from sqlalchemy.orm import Mapped, mapped_column
5+
6+
from src.shared.database.mixin.timestamp import SoftDeleteMixin, TimeStampMixin
7+
from src.shared.database.model import Base
8+
9+
10+
class PermissionModel(Base, TimeStampMixin, SoftDeleteMixin):
11+
__tablename__ = "permissions"
12+
__table_args__ = (
13+
UniqueConstraint("resource", "action", name="uq_permissions_resource_action"),
14+
)
15+
16+
key: Mapped[str] = mapped_column(String(255), unique=True, index=True)
17+
resource_id: Mapped[UUID] = mapped_column(index=True)
18+
resource: Mapped[str] = mapped_column(String(100), index=True)
19+
action: Mapped[str] = mapped_column(String(100), index=True)
20+
description: Mapped[str | None] = mapped_column(String(255), nullable=True)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from sqlalchemy import String
2+
from sqlalchemy.orm import Mapped, mapped_column
3+
4+
from src.shared.database.mixin.timestamp import SoftDeleteMixin, TimeStampMixin
5+
from src.shared.database.model import Base
6+
7+
8+
class AuthorizationResourceModel(Base, TimeStampMixin, SoftDeleteMixin):
9+
__tablename__ = "authorization_resources"
10+
11+
key: Mapped[str] = mapped_column(String(100), unique=True, index=True)
12+
name: Mapped[str] = mapped_column(String(150), nullable=False)
13+
description: Mapped[str | None] = mapped_column(String(255), nullable=True)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from sqlalchemy import String
2+
from sqlalchemy.orm import Mapped, mapped_column
3+
4+
from src.shared.database.mixin.timestamp import SoftDeleteMixin, TimeStampMixin
5+
from src.shared.database.model import Base
6+
7+
8+
class RoleModel(Base, TimeStampMixin, SoftDeleteMixin):
9+
__tablename__ = "roles"
10+
11+
name: Mapped[str] = mapped_column(String(100), unique=True, index=True)
12+
description: Mapped[str | None] = mapped_column(String(255), nullable=True)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from uuid import UUID
2+
3+
from sqlalchemy import UniqueConstraint
4+
from sqlalchemy.orm import Mapped, mapped_column
5+
6+
from src.shared.database.model import Base
7+
8+
9+
class RolePermissionModel(Base):
10+
__tablename__ = "role_permissions"
11+
__table_args__ = (
12+
UniqueConstraint(
13+
"role_id",
14+
"permission_id",
15+
name="uq_role_permissions_role_id_permission_id",
16+
),
17+
)
18+
19+
role_id: Mapped[UUID] = mapped_column(index=True)
20+
permission_id: Mapped[UUID] = mapped_column(index=True)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from uuid import UUID
2+
3+
from sqlalchemy import UniqueConstraint
4+
from sqlalchemy.orm import Mapped, mapped_column
5+
6+
from src.shared.database.model import Base
7+
8+
9+
class UserHasRoleModel(Base):
10+
__tablename__ = "user_has_roles"
11+
__table_args__ = (
12+
UniqueConstraint("user_id", "role_id", name="uq_user_has_roles_user_id_role_id"),
13+
)
14+
15+
user_id: Mapped[UUID] = mapped_column(index=True)
16+
role_id: Mapped[UUID] = mapped_column(index=True)

src/core/authorization/infrastructure/repositories/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)