Skip to content

Commit 265ce48

Browse files
committed
debug front
1 parent 05fe02f commit 265ce48

File tree

12 files changed

+597
-470
lines changed

12 files changed

+597
-470
lines changed

backend/app/admin/api/v1/sys/role.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from backend.app.admin.schema.role import (
88
CreateRoleParam,
99
GetRoleListDetails,
10+
UpdateRoleDataScopeParam,
1011
UpdateRoleDeptParam,
1112
UpdateRoleMenuParam,
1213
UpdateRoleParam,
@@ -115,6 +116,21 @@ async def update_role_menus(
115116
return response_base.fail()
116117

117118

119+
@router.put(
120+
'/{pk}/data-scope',
121+
summary='更新角色数据范围',
122+
dependencies=[
123+
Depends(RequestPermission('sys:role:data_scope:edit')),
124+
DependsRBAC,
125+
],
126+
)
127+
async def update_role_data_scope(request: Request, pk: Annotated[int, Path(...)], data_scope: UpdateRoleDataScopeParam):
128+
count = await role_service.update_role_data_scope(request=request, pk=pk, data_scope=data_scope)
129+
if count > 0:
130+
return response_base.success()
131+
return response_base.fail()
132+
133+
118134
@router.put(
119135
'/{pk}/dept',
120136
summary='更新角色部门',
@@ -126,7 +142,7 @@ async def update_role_menus(
126142
async def update_role_depts(
127143
request: Request, pk: Annotated[int, Path(...)], dept_ids: UpdateRoleDeptParam
128144
) -> ResponseModel:
129-
count = await role_service.update_role_dept(request=request, pk=pk, menu_ids=dept_ids)
145+
count = await role_service.update_role_dept(request=request, pk=pk, dept_ids=dept_ids)
130146
if count > 0:
131147
return response_base.success()
132148
return response_base.fail()

backend/app/admin/crud/crud_role.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@
33
from typing import Sequence
44

55
from sqlalchemy import Select, desc, select
6+
from sqlalchemy.ext.asyncio import AsyncSession
67
from sqlalchemy.orm import selectinload
78
from sqlalchemy_crud_plus import CRUDPlus
89

910
from backend.app.admin.model import Dept, Menu, Role, User
10-
from backend.app.admin.schema.role import CreateRoleParam, UpdateRoleDeptParam, UpdateRoleMenuParam, UpdateRoleParam
11+
from backend.app.admin.schema.role import (
12+
CreateRoleParam,
13+
UpdateRoleDataScopeParam,
14+
UpdateRoleDeptParam,
15+
UpdateRoleMenuParam,
16+
UpdateRoleParam,
17+
)
1118

1219

1320
class CRUDRole(CRUDPlus[Role]):
@@ -122,6 +129,17 @@ async def update_menus(self, db, role_id: int, menu_ids: UpdateRoleMenuParam) ->
122129
current_role.menus = menus.scalars().all()
123130
return len(current_role.menus)
124131

132+
async def update_data_scope(self, db: AsyncSession, role_id: int, data_scope: UpdateRoleDataScopeParam):
133+
"""
134+
更新用户数据范围
135+
136+
:param db:
137+
:param role_id:
138+
:param data_scope:
139+
:return:
140+
"""
141+
return await self.update_model(db, role_id, data_scope)
142+
125143
async def update_depts(self, db, role_id: int, dept_ids: UpdateRoleDeptParam) -> int:
126144
"""
127145
更新角色部门

backend/app/admin/model/sys_dept.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from sqlalchemy import ForeignKey, String
66
from sqlalchemy.orm import Mapped, mapped_column, relationship
77

8+
from backend.app.admin.model.m2m import sys_role_dept
89
from backend.common.model import Base, id_key
910

1011

@@ -34,4 +35,4 @@ class Dept(Base):
3435
users: Mapped[list['User']] = relationship(init=False, back_populates='dept') # noqa: F821
3536

3637
# 部门角色多对多
37-
roles: Mapped[list['Role']] = relationship(init=False, back_populates='dept') # noqa: F821
38+
roles: Mapped[list['Role']] = relationship(init=False, secondary=sys_role_dept, back_populates='depts') # noqa: F821

backend/app/admin/model/sys_role.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Role(Base):
1717
name: Mapped[str] = mapped_column(String(20), unique=True, comment='角色名称')
1818
data_scope: Mapped[int | None] = mapped_column(
1919
default=0,
20-
comment='权限范围(0: 全部数据,1: 自定义数据,2: 所在部门及以下数据,3: 所在部门数据,4: 仅本人数据)',
20+
comment='数据权限范围(0: 全部数据,1: 自定义数据,2: 所在部门及以下数据,3: 所在部门数据,4: 仅本人数据)',
2121
)
2222
status: Mapped[int] = mapped_column(default=1, comment='角色状态(0停用 1正常)')
2323
remark: Mapped[str | None] = mapped_column(LONGTEXT, default=None, comment='备注')

backend/app/admin/schema/role.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@
44

55
from pydantic import ConfigDict, Field
66

7+
from backend.app.admin.schema.dept import GetDeptListDetails
78
from backend.app.admin.schema.menu import GetMenuListDetails
89
from backend.common.enums import RoleDataScopeType, StatusType
910
from backend.common.schema import SchemaBase
1011

1112

1213
class RoleSchemaBase(SchemaBase):
1314
name: str
14-
data_scope: RoleDataScopeType = Field(
15-
default=RoleDataScopeType.custom, description='权限范围(1:全部数据权限 2:自定义数据权限)'
16-
)
1715
status: StatusType = Field(default=StatusType.enable)
1816
remark: str | None = None
1917

@@ -30,6 +28,13 @@ class UpdateRoleMenuParam(SchemaBase):
3028
menus: list[int]
3129

3230

31+
class UpdateRoleDataScopeParam(SchemaBase):
32+
data_scope: RoleDataScopeType = Field(
33+
default=RoleDataScopeType.all,
34+
description='数据权限范围(0: 全部数据,1: 自定义数据,2: 所在部门及以下数据,3: 所在部门数据,4: 仅本人数据)',
35+
)
36+
37+
3338
class UpdateRoleDeptParam(SchemaBase):
3439
depts: list[int]
3540

@@ -38,6 +43,8 @@ class GetRoleListDetails(RoleSchemaBase):
3843
model_config = ConfigDict(from_attributes=True)
3944

4045
id: int
46+
data_scope: RoleDataScopeType
4147
created_time: datetime
4248
updated_time: datetime | None = None
4349
menus: list[GetMenuListDetails]
50+
depts: list[GetDeptListDetails] | None = None

backend/app/admin/service/role_service.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99
from backend.app.admin.crud.crud_menu import menu_dao
1010
from backend.app.admin.crud.crud_role import role_dao
1111
from backend.app.admin.model import Role
12-
from backend.app.admin.schema.role import CreateRoleParam, UpdateRoleDeptParam, UpdateRoleMenuParam, UpdateRoleParam
12+
from backend.app.admin.schema.role import (
13+
CreateRoleParam,
14+
UpdateRoleDataScopeParam,
15+
UpdateRoleDeptParam,
16+
UpdateRoleMenuParam,
17+
UpdateRoleParam,
18+
)
1319
from backend.common.exception import errors
1420
from backend.core.conf import settings
1521
from backend.database.db_mysql import async_db_session
@@ -78,6 +84,17 @@ async def update_role_menu(*, request: Request, pk: int, menu_ids: UpdateRoleMen
7884
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
7985
return count
8086

87+
@staticmethod
88+
async def update_role_data_scope(*, request: Request, pk: int, data_scope: UpdateRoleDataScopeParam) -> int:
89+
async with async_db_session.begin() as db:
90+
role = await role_dao.get(db, pk)
91+
if not role:
92+
raise errors.NotFoundError(msg='角色不存在')
93+
count = await role_dao.update_data_scope(db, pk, data_scope)
94+
if pk in [role.id for role in request.user.roles]:
95+
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{request.user.id}')
96+
return count
97+
8198
@staticmethod
8299
async def update_role_dept(*, request: Request, pk: int, dept_ids: UpdateRoleDeptParam) -> int:
83100
async with async_db_session.begin() as db:

backend/app/generator/api/router.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from backend.app.generator.api.v1.gen_business import router as gen_business_router
77
from backend.app.generator.api.v1.gen_model import router as gen_model_router
88

9-
v1 = APIRouter()
9+
v1 = APIRouter(prefix='/gen', tags=['代码生成'])
1010

11-
v1.include_router(gen_business_router, prefix='/business', tags=['代码生成'])
12-
v1.include_router(gen_model_router, prefix='/model', tags=['代码生成'])
13-
v1.include_router(gen_router, prefix='/gen', tags=['代码生成'])
11+
v1.include_router(gen_business_router, prefix='/businesses')
12+
v1.include_router(gen_model_router, prefix='/models')
13+
v1.include_router(gen_router)

backend/common/enums.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,11 @@ class MenuType(IntEnum):
3838
class RoleDataScopeType(IntEnum):
3939
"""数据范围"""
4040

41-
all = 1
42-
custom = 2
41+
all = 0
42+
custom = 1
43+
dept_child = 2
44+
dept = 3
45+
self = 4
4346

4447

4548
class MethodType(StrEnum):

backend/common/security/permission.py

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Any
44

55
from fastapi import Request
6-
from sqlalchemy import or_, select
6+
from sqlalchemy import ColumnElement, or_, select
77

88
from backend.app.admin.model import Dept
99
from backend.app.admin.model.m2m import sys_role_dept
@@ -31,11 +31,9 @@ async def __call__(self, request: Request):
3131
request.state.permission = self.value
3232

3333

34-
def filter_data_permission(request: Request, model: Any) -> Any:
34+
def filter_data_scope(request: Request, model: Any) -> ColumnElement[bool]:
3535
"""
36-
过滤用户数据范围
37-
38-
使用场景:对于非后台管理数据,需要在前端界面向用户进行展示的数据
36+
过滤用户数据范围(当前设计存在较大弊端,仅供参考)
3937
4038
:param request: 接口请求对象
4139
:param model: 需要进行数据过滤的 sqlalchemy 模型
@@ -54,42 +52,33 @@ def filter_data_permission(request: Request, model: Any) -> Any:
5452
if not user_roles:
5553
return or_(getattr(model, 'created_by') == user_id if hasattr(model, 'created_by') else 1 == 0)
5654

55+
data_scope = min(role.data_scope for role in user_roles if role.status == 1)
5756
user_dept_id = user.dept_id
5857

59-
conditions = []
60-
61-
# 获取用户的所有角色
62-
for role in user.roles:
63-
if not role.status: # 角色已停用
64-
continue
65-
66-
# 全部数据权限
67-
if role.data_scope == 0:
68-
return or_(1 == 1)
69-
70-
# 自定义数据权限
71-
elif role.data_scope == 1:
72-
dept_ids = select(sys_role_dept.c.dept_id).where(sys_role_dept.c.role_id == role.id)
73-
conditions.append(getattr(model, 'dept_id').in_(dept_ids) if hasattr(model, 'dept_id') else 1 == 0)
58+
# 全部数据权限
59+
if data_scope == 0:
60+
return or_(1 == 1)
7461

75-
# 部门及以下数据权限
76-
elif role.data_scope == 2:
77-
child_dept_ids = select(Dept.id).where(or_(Dept.id == user_dept_id, Dept.parent_id == user_dept_id))
78-
conditions.append(getattr(model, 'dept_id').in_(child_dept_ids) if hasattr(model, 'dept_id') else 1 == 0)
62+
# 自定义数据权限
63+
elif data_scope == 1:
64+
dept_ids = select(sys_role_dept.c.dept_id).where(
65+
sys_role_dept.c.role_id.in_(role.id for role in user_roles if role.status == 1)
66+
)
67+
return or_(getattr(model, 'dept_id').in_(dept_ids) if hasattr(model, 'dept_id') else 1 == 0)
7968

80-
# 本部门数据权限
81-
elif role.data_scope == 3:
82-
conditions.append(getattr(model, 'dept_id') == user_dept_id if hasattr(model, 'dept_id') else 1 == 0)
69+
# 部门及以下数据权限
70+
elif data_scope == 2:
71+
child_dept_ids = select(Dept.id).where(or_(Dept.id == user_dept_id, Dept.parent_id == user_dept_id))
72+
return or_(getattr(model, 'dept_id').in_(child_dept_ids) if hasattr(model, 'dept_id') else 1 == 0)
8373

84-
# 仅本人数据权限
85-
elif role.data_scope == 4:
86-
conditions.append(getattr(model, 'created_by') == user_id if hasattr(model, 'created_by') else 1 == 0)
74+
# 本部门数据权限
75+
elif data_scope == 3:
76+
return or_(getattr(model, 'dept_id') == user_dept_id if hasattr(model, 'dept_id') else 1 == 0)
8777

88-
# 默认
89-
else:
90-
conditions.append(1 == 0)
78+
# 仅本人数据权限
79+
elif data_scope == 4:
80+
return or_(getattr(model, 'created_by') == user_id if hasattr(model, 'created_by') else 1 == 0)
9181

92-
if not conditions:
82+
# 默认
83+
else:
9384
return or_(1 == 0)
94-
95-
return or_(*conditions)

0 commit comments

Comments
 (0)