Skip to content

Commit 0484945

Browse files
authored
perf: 优化数据权限依赖 (#8)
1 parent 9dc7170 commit 0484945

File tree

10 files changed

+137
-82
lines changed

10 files changed

+137
-82
lines changed
Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
from typing import Optional
22

33
from fastapi import Depends, Request, params
4+
from sqlalchemy import ColumnElement, func, or_, select
45

56
from common.context import RequestContext
7+
from config.database import Base
8+
from module_admin.entity.do.dept_do import SysDept
9+
from module_admin.entity.do.role_do import SysRoleDept
610
from utils.dependency_util import DependencyUtil
711

812

@@ -19,25 +23,22 @@ class GetDataScope:
1923

2024
def __init__(
2125
self,
22-
query_alias: Optional[str] = '',
23-
db_alias: Optional[str] = 'db',
26+
query_alias: Base,
2427
user_alias: Optional[str] = 'user_id',
2528
dept_alias: Optional[str] = 'dept_id',
2629
) -> None:
2730
"""
2831
获取当前用户数据权限对应的查询sql语句
2932
30-
:param query_alias: 所要查询表对应的sqlalchemy模型名称,默认为''
31-
:param db_alias: orm对象别名,默认为'db'
33+
:param query_alias: 所要查询表对应的sqlalchemy模型类,不可为空
3234
:param user_alias: 用户id字段别名,默认为'user_id'
3335
:param dept_alias: 部门id字段别名,默认为'dept_id'
3436
"""
3537
self.query_alias = query_alias
36-
self.db_alias = db_alias
3738
self.user_alias = user_alias
3839
self.dept_alias = dept_alias
3940

40-
def __call__(self, request: Request) -> str:
41+
def __call__(self, request: Request) -> ColumnElement:
4142
DependencyUtil.check_exclude_routes(request, err_msg='当前路由不在认证规则内,不可使用GetDataScope依赖项')
4243
current_user = RequestContext.get_current_user()
4344
user_id = current_user.user.user_id
@@ -48,50 +49,66 @@ def __call__(self, request: Request) -> str:
4849
param_sql_list = []
4950
for role in current_user.user.role:
5051
if current_user.user.admin or role.data_scope == self.DATA_SCOPE_ALL:
51-
param_sql_list = ['1 == 1']
52+
param_sql_list = [True]
5253
break
5354
if role.data_scope == self.DATA_SCOPE_CUSTOM:
5455
if len(custom_data_scope_role_id_list) > 1:
5556
param_sql_list.append(
56-
f"{self.query_alias}.{self.dept_alias}.in_(select(SysRoleDept.dept_id).where(SysRoleDept.role_id.in_({custom_data_scope_role_id_list}))) if hasattr({self.query_alias}, '{self.dept_alias}') else 1 == 0"
57+
getattr(self.query_alias, self.dept_alias).in_(
58+
select(SysRoleDept.dept_id).where(SysRoleDept.role_id.in_(custom_data_scope_role_id_list))
59+
)
60+
if hasattr(self.query_alias, self.dept_alias)
61+
else False
5762
)
5863
else:
5964
param_sql_list.append(
60-
f"{self.query_alias}.{self.dept_alias}.in_(select(SysRoleDept.dept_id).where(SysRoleDept.role_id == {role.role_id})) if hasattr({self.query_alias}, '{self.dept_alias}') else 1 == 0"
65+
getattr(self.query_alias, self.dept_alias).in_(
66+
select(SysRoleDept.dept_id).where(SysRoleDept.role_id == role.role_id)
67+
)
68+
if hasattr(self.query_alias, self.dept_alias)
69+
else False
6170
)
6271
elif role.data_scope == self.DATA_SCOPE_DEPT:
6372
param_sql_list.append(
64-
f"{self.query_alias}.{self.dept_alias} == {dept_id} if hasattr({self.query_alias}, '{self.dept_alias}') else 1 == 0"
73+
getattr(self.query_alias, self.dept_alias) == dept_id
74+
if hasattr(self.query_alias, self.dept_alias)
75+
else False
6576
)
6677
elif role.data_scope == self.DATA_SCOPE_DEPT_AND_CHILD:
6778
param_sql_list.append(
68-
f"{self.query_alias}.{self.dept_alias}.in_(select(SysDept.dept_id).where(or_(SysDept.dept_id == {dept_id}, func.find_in_set({dept_id}, SysDept.ancestors)))) if hasattr({self.query_alias}, '{self.dept_alias}') else 1 == 0"
79+
getattr(self.query_alias, self.dept_alias).in_(
80+
select(SysDept.dept_id).where(
81+
or_(SysDept.dept_id == dept_id, func.find_in_set(dept_id, SysDept.ancestors))
82+
)
83+
)
84+
if hasattr(self.query_alias, self.dept_alias)
85+
else False
6986
)
7087
elif role.data_scope == self.DATA_SCOPE_SELF:
7188
param_sql_list.append(
72-
f"{self.query_alias}.{self.user_alias} == {user_id} if hasattr({self.query_alias}, '{self.user_alias}') else 1 == 0"
89+
getattr(self.query_alias, self.user_alias) == user_id
90+
if hasattr(self.query_alias, self.user_alias)
91+
else False
7392
)
7493
else:
75-
param_sql_list.append('1 == 0')
94+
param_sql_list.append(False)
7695
param_sql_list = list(dict.fromkeys(param_sql_list))
77-
param_sql = f'or_({", ".join(param_sql_list)})'
96+
param_sql = or_(*param_sql_list)
7897

7998
return param_sql
8099

81100

82101
def DataScopeDependency( # noqa: N802
83-
query_alias: Optional[str] = '',
84-
db_alias: Optional[str] = 'db',
102+
query_alias: Base,
85103
user_alias: Optional[str] = 'user_id',
86104
dept_alias: Optional[str] = 'dept_id',
87105
) -> params.Depends:
88106
"""
89107
当前用户数据权限依赖
90108
91-
:param query_alias: 所要查询表对应的sqlalchemy模型名称,默认为''
92-
:param db_alias: orm对象别名,默认为'db'
109+
:param query_alias: 所要查询表对应的sqlalchemy模型类,不可为空
93110
:param user_alias: 用户id字段别名,默认为'user_id'
94111
:param dept_alias: 部门id字段别名,默认为'dept_id'
95112
:return: 当前用户数据权限依赖
96113
"""
97-
return Depends(GetDataScope(query_alias, db_alias, user_alias, dept_alias))
114+
return Depends(GetDataScope(query_alias, user_alias, dept_alias))

ruoyi-fastapi-backend/module_admin/controller/dept_controller.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from fastapi import Path, Query, Request, Response
55
from pydantic_validation_decorator import ValidateFields
6+
from sqlalchemy import ColumnElement
67
from sqlalchemy.ext.asyncio import AsyncSession
78

89
from common.annotation.log_annotation import Log
@@ -13,6 +14,7 @@
1314
from common.enums import BusinessType
1415
from common.router import APIRouterPro
1516
from common.vo import DataResponseModel, ResponseBaseModel
17+
from module_admin.entity.do.dept_do import SysDept
1618
from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel, DeptQueryModel
1719
from module_admin.entity.vo.user_vo import CurrentUserModel
1820
from module_admin.service.dept_service import DeptService
@@ -35,7 +37,7 @@ async def get_system_dept_tree_for_edit_option(
3537
request: Request,
3638
dept_id: Annotated[int, Path(description='部门id')],
3739
query_db: Annotated[AsyncSession, DBSessionDependency()],
38-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
40+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
3941
) -> Response:
4042
dept_query = DeptModel(deptId=dept_id)
4143
dept_query_result = await DeptService.get_dept_for_edit_option_services(query_db, dept_query, data_scope_sql)
@@ -55,7 +57,7 @@ async def get_system_dept_list(
5557
request: Request,
5658
dept_query: Annotated[DeptQueryModel, Query()],
5759
query_db: Annotated[AsyncSession, DBSessionDependency()],
58-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
60+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
5961
) -> Response:
6062
dept_query_result = await DeptService.get_dept_list_services(query_db, dept_query, data_scope_sql)
6163
logger.info('获取成功')
@@ -102,7 +104,7 @@ async def edit_system_dept(
102104
edit_dept: DeptModel,
103105
query_db: Annotated[AsyncSession, DBSessionDependency()],
104106
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
105-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
107+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
106108
) -> Response:
107109
if not current_user.user.admin:
108110
await DeptService.check_dept_data_scope_services(query_db, edit_dept.dept_id, data_scope_sql)
@@ -127,7 +129,7 @@ async def delete_system_dept(
127129
dept_ids: Annotated[str, Path(description='需要删除的部门id')],
128130
query_db: Annotated[AsyncSession, DBSessionDependency()],
129131
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
130-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
132+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
131133
) -> Response:
132134
dept_id_list = dept_ids.split(',') if dept_ids else []
133135
if dept_id_list:
@@ -155,7 +157,7 @@ async def query_detail_system_dept(
155157
dept_id: Annotated[int, Path(description='部门id')],
156158
query_db: Annotated[AsyncSession, DBSessionDependency()],
157159
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
158-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
160+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
159161
) -> Response:
160162
if not current_user.user.admin:
161163
await DeptService.check_dept_data_scope_services(query_db, dept_id, data_scope_sql)

ruoyi-fastapi-backend/module_admin/controller/role_controller.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from fastapi import Form, Path, Query, Request, Response
55
from fastapi.responses import StreamingResponse
66
from pydantic_validation_decorator import ValidateFields
7+
from sqlalchemy import ColumnElement
78
from sqlalchemy.ext.asyncio import AsyncSession
89

910
from common.annotation.log_annotation import Log
@@ -14,6 +15,8 @@
1415
from common.enums import BusinessType
1516
from common.router import APIRouterPro
1617
from common.vo import DataResponseModel, DynamicResponseModel, PageResponseModel, ResponseBaseModel
18+
from module_admin.entity.do.dept_do import SysDept
19+
from module_admin.entity.do.user_do import SysUser
1720
from module_admin.entity.vo.dept_vo import DeptModel
1821
from module_admin.entity.vo.role_vo import (
1922
AddRoleModel,
@@ -46,7 +49,7 @@ async def get_system_role_dept_tree(
4649
request: Request,
4750
role_id: Annotated[int, Path(description='角色ID')],
4851
query_db: Annotated[AsyncSession, DBSessionDependency()],
49-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
52+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
5053
) -> Response:
5154
dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(), data_scope_sql)
5255
role_dept_query_result = await RoleService.get_role_dept_tree_services(query_db, role_id)
@@ -67,7 +70,7 @@ async def get_system_role_list(
6770
request: Request,
6871
role_page_query: Annotated[RolePageQueryModel, Query()],
6972
query_db: Annotated[AsyncSession, DBSessionDependency()],
70-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
73+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
7174
) -> Response:
7275
role_page_query_result = await RoleService.get_role_list_services(
7376
query_db, role_page_query, data_scope_sql, is_page=True
@@ -116,7 +119,7 @@ async def edit_system_role(
116119
edit_role: AddRoleModel,
117120
query_db: Annotated[AsyncSession, DBSessionDependency()],
118121
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
119-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
122+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
120123
) -> Response:
121124
await RoleService.check_role_allowed_services(edit_role)
122125
if not current_user.user.admin:
@@ -142,7 +145,7 @@ async def edit_system_role_datascope(
142145
role_data_scope: AddRoleModel,
143146
query_db: Annotated[AsyncSession, DBSessionDependency()],
144147
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
145-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
148+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
146149
) -> Response:
147150
await RoleService.check_role_allowed_services(role_data_scope)
148151
if not current_user.user.admin:
@@ -174,7 +177,7 @@ async def delete_system_role(
174177
role_ids: Annotated[str, Path(description='需要删除的角色ID')],
175178
query_db: Annotated[AsyncSession, DBSessionDependency()],
176179
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
177-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
180+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
178181
) -> Response:
179182
role_id_list = role_ids.split(',') if role_ids else []
180183
if role_id_list:
@@ -201,7 +204,7 @@ async def query_detail_system_role(
201204
role_id: Annotated[int, Path(description='角色ID')],
202205
query_db: Annotated[AsyncSession, DBSessionDependency()],
203206
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
204-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
207+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
205208
) -> Response:
206209
if not current_user.user.admin:
207210
await RoleService.check_role_data_scope_services(query_db, str(role_id), data_scope_sql)
@@ -231,7 +234,7 @@ async def export_system_role_list(
231234
request: Request,
232235
role_page_query: Annotated[RolePageQueryModel, Form()],
233236
query_db: Annotated[AsyncSession, DBSessionDependency()],
234-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
237+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
235238
) -> Response:
236239
# 获取全量数据
237240
role_query_result = await RoleService.get_role_list_services(
@@ -256,7 +259,7 @@ async def reset_system_role_status(
256259
change_role: AddRoleModel,
257260
query_db: Annotated[AsyncSession, DBSessionDependency()],
258261
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
259-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
262+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
260263
) -> Response:
261264
await RoleService.check_role_allowed_services(change_role)
262265
if not current_user.user.admin:
@@ -285,7 +288,7 @@ async def get_system_allocated_user_list(
285288
request: Request,
286289
user_role: Annotated[UserRolePageQueryModel, Query()],
287290
query_db: Annotated[AsyncSession, DBSessionDependency()],
288-
data_scope_sql: Annotated[str, DataScopeDependency('SysUser')],
291+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
289292
) -> Response:
290293
role_user_allocated_page_query_result = await RoleService.get_role_user_allocated_list_services(
291294
query_db, user_role, data_scope_sql, is_page=True
@@ -306,7 +309,7 @@ async def get_system_unallocated_user_list(
306309
request: Request,
307310
user_role: Annotated[UserRolePageQueryModel, Query()],
308311
query_db: Annotated[AsyncSession, DBSessionDependency()],
309-
data_scope_sql: Annotated[str, DataScopeDependency('SysUser')],
312+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
310313
) -> Response:
311314
role_user_unallocated_page_query_result = await RoleService.get_role_user_unallocated_list_services(
312315
query_db, user_role, data_scope_sql, is_page=True
@@ -329,7 +332,7 @@ async def add_system_role_user(
329332
add_role_user: Annotated[CrudUserRoleModel, Query()],
330333
query_db: Annotated[AsyncSession, DBSessionDependency()],
331334
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
332-
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
335+
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
333336
) -> Response:
334337
if not current_user.user.admin:
335338
await RoleService.check_role_data_scope_services(query_db, str(add_role_user.role_id), data_scope_sql)

0 commit comments

Comments
 (0)