Skip to content

Commit dc6fc64

Browse files
committed
feat: implement casbin
1 parent 278f4f1 commit dc6fc64

22 files changed

Lines changed: 823 additions & 18 deletions

alembic/env.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@
88

99
from alembic import context
1010
from src.core.config.setting import settings
11+
from src.core.authorization.infrastructure.models.casbin_rule_model import (
12+
CasbinRuleModel, # noqa: F401
13+
)
14+
from src.core.authorization.infrastructure.models.permission_model import (
15+
PermissionModel, # noqa: F401
16+
)
17+
from src.core.authorization.infrastructure.models.role_model import (
18+
RoleModel, # noqa: F401
19+
)
20+
from src.core.authorization.infrastructure.models.role_permission_model import (
21+
RolePermissionModel, # noqa: F401
22+
)
23+
from src.core.authorization.infrastructure.models.user_has_role_model import (
24+
UserHasRoleModel, # noqa: F401
25+
)
1126
from src.modules.todo.infrastructure.models.todo_model import TodoModel # noqa: F401
1227
from src.modules.user.infrastructure.models.refresh_token_model import (
1328
RefreshTokenModel, # noqa: F401
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
"""add casbin policy table
2+
3+
Revision ID: d4bb4d2b3f0a
4+
Revises: ab661f0b6986
5+
Create Date: 2026-06-17 00:00:00.000000
6+
7+
"""
8+
from typing import Sequence, Union
9+
from uuid import UUID
10+
11+
from alembic import op
12+
import sqlalchemy as sa
13+
14+
15+
revision: str = "d4bb4d2b3f0a"
16+
down_revision: Union[str, Sequence[str], None] = "ab661f0b6986"
17+
branch_labels: Union[str, Sequence[str], None] = None
18+
depends_on: Union[str, Sequence[str], None] = None
19+
20+
21+
def upgrade() -> None:
22+
op.create_table(
23+
"roles",
24+
sa.Column("id", sa.Uuid(), nullable=False),
25+
sa.Column("name", sa.String(length=100), nullable=False),
26+
sa.PrimaryKeyConstraint("id"),
27+
)
28+
op.create_index(op.f("ix_roles_name"), "roles", ["name"], unique=True)
29+
30+
op.create_table(
31+
"permissions",
32+
sa.Column("id", sa.Uuid(), nullable=False),
33+
sa.Column("key", sa.String(length=255), nullable=False),
34+
sa.Column("resource", sa.String(length=100), nullable=False),
35+
sa.Column("action", sa.String(length=100), nullable=False),
36+
sa.PrimaryKeyConstraint("id"),
37+
sa.UniqueConstraint("resource", "action", name="uq_permissions_resource_action"),
38+
)
39+
op.create_index(op.f("ix_permissions_action"), "permissions", ["action"])
40+
op.create_index(op.f("ix_permissions_key"), "permissions", ["key"], unique=True)
41+
op.create_index(op.f("ix_permissions_resource"), "permissions", ["resource"])
42+
43+
op.create_table(
44+
"role_permissions",
45+
sa.Column("id", sa.Uuid(), nullable=False),
46+
sa.Column("role_id", sa.Uuid(), nullable=False),
47+
sa.Column("permission_id", sa.Uuid(), nullable=False),
48+
sa.ForeignKeyConstraint(["permission_id"], ["permissions.id"]),
49+
sa.ForeignKeyConstraint(["role_id"], ["roles.id"]),
50+
sa.PrimaryKeyConstraint("id"),
51+
sa.UniqueConstraint(
52+
"role_id",
53+
"permission_id",
54+
name="uq_role_permissions_role_id_permission_id",
55+
),
56+
)
57+
op.create_index(
58+
op.f("ix_role_permissions_permission_id"),
59+
"role_permissions",
60+
["permission_id"],
61+
)
62+
op.create_index(
63+
op.f("ix_role_permissions_role_id"),
64+
"role_permissions",
65+
["role_id"],
66+
)
67+
68+
op.create_table(
69+
"user_has_roles",
70+
sa.Column("id", sa.Uuid(), nullable=False),
71+
sa.Column("user_id", sa.Uuid(), nullable=False),
72+
sa.Column("role_id", sa.Uuid(), nullable=False),
73+
sa.ForeignKeyConstraint(["role_id"], ["roles.id"]),
74+
sa.ForeignKeyConstraint(["user_id"], ["users.id"]),
75+
sa.PrimaryKeyConstraint("id"),
76+
sa.UniqueConstraint("user_id", "role_id", name="uq_user_has_roles_user_id_role_id"),
77+
)
78+
op.create_index(op.f("ix_user_has_roles_role_id"), "user_has_roles", ["role_id"])
79+
op.create_index(op.f("ix_user_has_roles_user_id"), "user_has_roles", ["user_id"])
80+
81+
op.create_table(
82+
"casbin_rules",
83+
sa.Column("id", sa.Uuid(), nullable=False),
84+
sa.Column("ptype", sa.String(length=16), nullable=False),
85+
sa.Column("v0", sa.String(length=255), nullable=True),
86+
sa.Column("v1", sa.String(length=255), nullable=True),
87+
sa.Column("v2", sa.String(length=255), nullable=True),
88+
sa.Column("v3", sa.String(length=255), nullable=True),
89+
sa.Column("v4", sa.String(length=255), nullable=True),
90+
sa.Column("v5", sa.String(length=255), nullable=True),
91+
sa.PrimaryKeyConstraint("id"),
92+
)
93+
op.create_index(op.f("ix_casbin_rules_ptype"), "casbin_rules", ["ptype"])
94+
op.create_index(op.f("ix_casbin_rules_v0"), "casbin_rules", ["v0"])
95+
op.create_index(op.f("ix_casbin_rules_v1"), "casbin_rules", ["v1"])
96+
op.create_index(op.f("ix_casbin_rules_v2"), "casbin_rules", ["v2"])
97+
98+
roles = sa.table(
99+
"roles",
100+
sa.column("id", sa.Uuid),
101+
sa.column("name", sa.String),
102+
)
103+
permissions = sa.table(
104+
"permissions",
105+
sa.column("id", sa.Uuid),
106+
sa.column("key", sa.String),
107+
sa.column("resource", sa.String),
108+
sa.column("action", sa.String),
109+
)
110+
role_permissions = sa.table(
111+
"role_permissions",
112+
sa.column("id", sa.Uuid),
113+
sa.column("role_id", sa.Uuid),
114+
sa.column("permission_id", sa.Uuid),
115+
)
116+
casbin_rules = sa.table(
117+
"casbin_rules",
118+
sa.column("id", sa.Uuid),
119+
sa.column("ptype", sa.String),
120+
sa.column("v0", sa.String),
121+
sa.column("v1", sa.String),
122+
sa.column("v2", sa.String),
123+
)
124+
125+
admin_role_id = UUID("10000000-0000-0000-0000-000000000001")
126+
user_role_id = UUID("10000000-0000-0000-0000-000000000002")
127+
admin_permission_id = UUID("20000000-0000-0000-0000-000000000001")
128+
todo_create_permission_id = UUID("20000000-0000-0000-0000-000000000002")
129+
todo_read_permission_id = UUID("20000000-0000-0000-0000-000000000003")
130+
todo_update_permission_id = UUID("20000000-0000-0000-0000-000000000004")
131+
todo_delete_permission_id = UUID("20000000-0000-0000-0000-000000000005")
132+
user_me_permission_id = UUID("20000000-0000-0000-0000-000000000006")
133+
134+
op.bulk_insert(
135+
roles,
136+
[
137+
{"id": admin_role_id, "name": "admin"},
138+
{"id": user_role_id, "name": "user"},
139+
],
140+
)
141+
op.bulk_insert(
142+
permissions,
143+
[
144+
{
145+
"id": admin_permission_id,
146+
"key": "*",
147+
"resource": "*",
148+
"action": "*",
149+
},
150+
{
151+
"id": todo_create_permission_id,
152+
"key": "todo:create",
153+
"resource": "todo",
154+
"action": "create",
155+
},
156+
{
157+
"id": todo_read_permission_id,
158+
"key": "todo:read",
159+
"resource": "todo",
160+
"action": "read",
161+
},
162+
{
163+
"id": todo_update_permission_id,
164+
"key": "todo:update",
165+
"resource": "todo",
166+
"action": "update",
167+
},
168+
{
169+
"id": todo_delete_permission_id,
170+
"key": "todo:delete",
171+
"resource": "todo",
172+
"action": "delete",
173+
},
174+
{
175+
"id": user_me_permission_id,
176+
"key": "user:me",
177+
"resource": "user",
178+
"action": "me",
179+
},
180+
],
181+
)
182+
op.bulk_insert(
183+
role_permissions,
184+
[
185+
{
186+
"id": UUID("30000000-0000-0000-0000-000000000001"),
187+
"role_id": admin_role_id,
188+
"permission_id": admin_permission_id,
189+
},
190+
{
191+
"id": UUID("30000000-0000-0000-0000-000000000002"),
192+
"role_id": user_role_id,
193+
"permission_id": todo_create_permission_id,
194+
},
195+
{
196+
"id": UUID("30000000-0000-0000-0000-000000000003"),
197+
"role_id": user_role_id,
198+
"permission_id": todo_read_permission_id,
199+
},
200+
{
201+
"id": UUID("30000000-0000-0000-0000-000000000004"),
202+
"role_id": user_role_id,
203+
"permission_id": todo_update_permission_id,
204+
},
205+
{
206+
"id": UUID("30000000-0000-0000-0000-000000000005"),
207+
"role_id": user_role_id,
208+
"permission_id": todo_delete_permission_id,
209+
},
210+
{
211+
"id": UUID("30000000-0000-0000-0000-000000000006"),
212+
"role_id": user_role_id,
213+
"permission_id": user_me_permission_id,
214+
},
215+
],
216+
)
217+
op.bulk_insert(
218+
casbin_rules,
219+
[
220+
{
221+
"id": UUID("00000000-0000-0000-0000-000000000001"),
222+
"ptype": "p",
223+
"v0": "admin",
224+
"v1": "*",
225+
},
226+
{
227+
"id": UUID("00000000-0000-0000-0000-000000000002"),
228+
"ptype": "p",
229+
"v0": "user",
230+
"v1": "todo:create",
231+
},
232+
{
233+
"id": UUID("00000000-0000-0000-0000-000000000003"),
234+
"ptype": "p",
235+
"v0": "user",
236+
"v1": "todo:read",
237+
},
238+
{
239+
"id": UUID("00000000-0000-0000-0000-000000000004"),
240+
"ptype": "p",
241+
"v0": "user",
242+
"v1": "todo:update",
243+
},
244+
{
245+
"id": UUID("00000000-0000-0000-0000-000000000005"),
246+
"ptype": "p",
247+
"v0": "user",
248+
"v1": "todo:delete",
249+
},
250+
{
251+
"id": UUID("00000000-0000-0000-0000-000000000006"),
252+
"ptype": "p",
253+
"v0": "user",
254+
"v1": "user:me",
255+
},
256+
],
257+
)
258+
259+
260+
def downgrade() -> None:
261+
op.drop_index(op.f("ix_casbin_rules_v2"), table_name="casbin_rules")
262+
op.drop_index(op.f("ix_casbin_rules_v1"), table_name="casbin_rules")
263+
op.drop_index(op.f("ix_casbin_rules_v0"), table_name="casbin_rules")
264+
op.drop_index(op.f("ix_casbin_rules_ptype"), table_name="casbin_rules")
265+
op.drop_table("casbin_rules")
266+
op.drop_index(op.f("ix_user_has_roles_user_id"), table_name="user_has_roles")
267+
op.drop_index(op.f("ix_user_has_roles_role_id"), table_name="user_has_roles")
268+
op.drop_table("user_has_roles")
269+
op.drop_index(op.f("ix_role_permissions_role_id"), table_name="role_permissions")
270+
op.drop_index(
271+
op.f("ix_role_permissions_permission_id"),
272+
table_name="role_permissions",
273+
)
274+
op.drop_table("role_permissions")
275+
op.drop_index(op.f("ix_permissions_resource"), table_name="permissions")
276+
op.drop_index(op.f("ix_permissions_key"), table_name="permissions")
277+
op.drop_index(op.f("ix_permissions_action"), table_name="permissions")
278+
op.drop_table("permissions")
279+
op.drop_index(op.f("ix_roles_name"), table_name="roles")
280+
op.drop_table("roles")

poetry.lock

Lines changed: 28 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ dependencies = [
1616
"passlib[bcrypt] (>=1.7.4,<2.0.0)",
1717
"python-jose[cryptography] (>=3.5.0,<4.0.0)",
1818
"python-multipart (>=0.0.32,<0.0.33)",
19-
"greenlet (>=3.5.1,<4.0.0)"
19+
"greenlet (>=3.5.1,<4.0.0)",
20+
"casbin (>=1.43.0,<2.0.0)"
2021
]
2122

2223
[tool.poetry]

0 commit comments

Comments
 (0)