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
55 changes: 36 additions & 19 deletions ruoyi-fastapi-backend/common/aspect/data_scope.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from typing import Optional

from fastapi import Depends, Request, params
from sqlalchemy import ColumnElement, func, or_, select

from common.context import RequestContext
from config.database import Base
from module_admin.entity.do.dept_do import SysDept
from module_admin.entity.do.role_do import SysRoleDept
from utils.dependency_util import DependencyUtil


Expand All @@ -19,25 +23,22 @@ class GetDataScope:

def __init__(
self,
query_alias: Optional[str] = '',
db_alias: Optional[str] = 'db',
query_alias: Base,
user_alias: Optional[str] = 'user_id',
dept_alias: Optional[str] = 'dept_id',
) -> None:
"""
获取当前用户数据权限对应的查询sql语句

:param query_alias: 所要查询表对应的sqlalchemy模型名称,默认为''
:param db_alias: orm对象别名,默认为'db'
:param query_alias: 所要查询表对应的sqlalchemy模型类,不可为空
:param user_alias: 用户id字段别名,默认为'user_id'
:param dept_alias: 部门id字段别名,默认为'dept_id'
"""
self.query_alias = query_alias
self.db_alias = db_alias
self.user_alias = user_alias
self.dept_alias = dept_alias

def __call__(self, request: Request) -> str:
def __call__(self, request: Request) -> ColumnElement:
DependencyUtil.check_exclude_routes(request, err_msg='当前路由不在认证规则内,不可使用GetDataScope依赖项')
current_user = RequestContext.get_current_user()
user_id = current_user.user.user_id
Expand All @@ -48,50 +49,66 @@ def __call__(self, request: Request) -> str:
param_sql_list = []
for role in current_user.user.role:
if current_user.user.admin or role.data_scope == self.DATA_SCOPE_ALL:
param_sql_list = ['1 == 1']
param_sql_list = [True]
break
if role.data_scope == self.DATA_SCOPE_CUSTOM:
if len(custom_data_scope_role_id_list) > 1:
param_sql_list.append(
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"
getattr(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 False
)
else:
param_sql_list.append(
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"
getattr(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 False
)
elif role.data_scope == self.DATA_SCOPE_DEPT:
param_sql_list.append(
f"{self.query_alias}.{self.dept_alias} == {dept_id} if hasattr({self.query_alias}, '{self.dept_alias}') else 1 == 0"
getattr(self.query_alias, self.dept_alias) == dept_id
if hasattr(self.query_alias, self.dept_alias)
else False
)
elif role.data_scope == self.DATA_SCOPE_DEPT_AND_CHILD:
param_sql_list.append(
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"
getattr(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 False
)
elif role.data_scope == self.DATA_SCOPE_SELF:
param_sql_list.append(
f"{self.query_alias}.{self.user_alias} == {user_id} if hasattr({self.query_alias}, '{self.user_alias}') else 1 == 0"
getattr(self.query_alias, self.user_alias) == user_id
if hasattr(self.query_alias, self.user_alias)
else False
)
else:
param_sql_list.append('1 == 0')
param_sql_list.append(False)
param_sql_list = list(dict.fromkeys(param_sql_list))
param_sql = f'or_({", ".join(param_sql_list)})'
param_sql = or_(*param_sql_list)

return param_sql


def DataScopeDependency( # noqa: N802
query_alias: Optional[str] = '',
db_alias: Optional[str] = 'db',
query_alias: Base,
user_alias: Optional[str] = 'user_id',
dept_alias: Optional[str] = 'dept_id',
) -> params.Depends:
"""
当前用户数据权限依赖

:param query_alias: 所要查询表对应的sqlalchemy模型名称,默认为''
:param db_alias: orm对象别名,默认为'db'
:param query_alias: 所要查询表对应的sqlalchemy模型类,不可为空
:param user_alias: 用户id字段别名,默认为'user_id'
:param dept_alias: 部门id字段别名,默认为'dept_id'
:return: 当前用户数据权限依赖
"""
return Depends(GetDataScope(query_alias, db_alias, user_alias, dept_alias))
return Depends(GetDataScope(query_alias, user_alias, dept_alias))
12 changes: 7 additions & 5 deletions ruoyi-fastapi-backend/module_admin/controller/dept_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from fastapi import Path, Query, Request, Response
from pydantic_validation_decorator import ValidateFields
from sqlalchemy import ColumnElement
from sqlalchemy.ext.asyncio import AsyncSession

from common.annotation.log_annotation import Log
Expand All @@ -13,6 +14,7 @@
from common.enums import BusinessType
from common.router import APIRouterPro
from common.vo import DataResponseModel, ResponseBaseModel
from module_admin.entity.do.dept_do import SysDept
from module_admin.entity.vo.dept_vo import DeleteDeptModel, DeptModel, DeptQueryModel
from module_admin.entity.vo.user_vo import CurrentUserModel
from module_admin.service.dept_service import DeptService
Expand All @@ -35,7 +37,7 @@ async def get_system_dept_tree_for_edit_option(
request: Request,
dept_id: Annotated[int, Path(description='部门id')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
dept_query = DeptModel(deptId=dept_id)
dept_query_result = await DeptService.get_dept_for_edit_option_services(query_db, dept_query, data_scope_sql)
Expand All @@ -55,7 +57,7 @@ async def get_system_dept_list(
request: Request,
dept_query: Annotated[DeptQueryModel, Query()],
query_db: Annotated[AsyncSession, DBSessionDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
dept_query_result = await DeptService.get_dept_list_services(query_db, dept_query, data_scope_sql)
logger.info('获取成功')
Expand Down Expand Up @@ -102,7 +104,7 @@ async def edit_system_dept(
edit_dept: DeptModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
if not current_user.user.admin:
await DeptService.check_dept_data_scope_services(query_db, edit_dept.dept_id, data_scope_sql)
Expand All @@ -127,7 +129,7 @@ async def delete_system_dept(
dept_ids: Annotated[str, Path(description='需要删除的部门id')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
dept_id_list = dept_ids.split(',') if dept_ids else []
if dept_id_list:
Expand Down Expand Up @@ -155,7 +157,7 @@ async def query_detail_system_dept(
dept_id: Annotated[int, Path(description='部门id')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
if not current_user.user.admin:
await DeptService.check_dept_data_scope_services(query_db, dept_id, data_scope_sql)
Expand Down
25 changes: 14 additions & 11 deletions ruoyi-fastapi-backend/module_admin/controller/role_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from fastapi import Form, Path, Query, Request, Response
from fastapi.responses import StreamingResponse
from pydantic_validation_decorator import ValidateFields
from sqlalchemy import ColumnElement
from sqlalchemy.ext.asyncio import AsyncSession

from common.annotation.log_annotation import Log
Expand All @@ -14,6 +15,8 @@
from common.enums import BusinessType
from common.router import APIRouterPro
from common.vo import DataResponseModel, DynamicResponseModel, PageResponseModel, ResponseBaseModel
from module_admin.entity.do.dept_do import SysDept
from module_admin.entity.do.user_do import SysUser
from module_admin.entity.vo.dept_vo import DeptModel
from module_admin.entity.vo.role_vo import (
AddRoleModel,
Expand Down Expand Up @@ -46,7 +49,7 @@ async def get_system_role_dept_tree(
request: Request,
role_id: Annotated[int, Path(description='角色ID')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
dept_query_result = await DeptService.get_dept_tree_services(query_db, DeptModel(), data_scope_sql)
role_dept_query_result = await RoleService.get_role_dept_tree_services(query_db, role_id)
Expand All @@ -67,7 +70,7 @@ async def get_system_role_list(
request: Request,
role_page_query: Annotated[RolePageQueryModel, Query()],
query_db: Annotated[AsyncSession, DBSessionDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
role_page_query_result = await RoleService.get_role_list_services(
query_db, role_page_query, data_scope_sql, is_page=True
Expand Down Expand Up @@ -116,7 +119,7 @@ async def edit_system_role(
edit_role: AddRoleModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
await RoleService.check_role_allowed_services(edit_role)
if not current_user.user.admin:
Expand All @@ -142,7 +145,7 @@ async def edit_system_role_datascope(
role_data_scope: AddRoleModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
await RoleService.check_role_allowed_services(role_data_scope)
if not current_user.user.admin:
Expand Down Expand Up @@ -174,7 +177,7 @@ async def delete_system_role(
role_ids: Annotated[str, Path(description='需要删除的角色ID')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
role_id_list = role_ids.split(',') if role_ids else []
if role_id_list:
Expand All @@ -201,7 +204,7 @@ async def query_detail_system_role(
role_id: Annotated[int, Path(description='角色ID')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
if not current_user.user.admin:
await RoleService.check_role_data_scope_services(query_db, str(role_id), data_scope_sql)
Expand Down Expand Up @@ -231,7 +234,7 @@ async def export_system_role_list(
request: Request,
role_page_query: Annotated[RolePageQueryModel, Form()],
query_db: Annotated[AsyncSession, DBSessionDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
# 获取全量数据
role_query_result = await RoleService.get_role_list_services(
Expand All @@ -256,7 +259,7 @@ async def reset_system_role_status(
change_role: AddRoleModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
await RoleService.check_role_allowed_services(change_role)
if not current_user.user.admin:
Expand Down Expand Up @@ -285,7 +288,7 @@ async def get_system_allocated_user_list(
request: Request,
user_role: Annotated[UserRolePageQueryModel, Query()],
query_db: Annotated[AsyncSession, DBSessionDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysUser')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
) -> Response:
role_user_allocated_page_query_result = await RoleService.get_role_user_allocated_list_services(
query_db, user_role, data_scope_sql, is_page=True
Expand All @@ -306,7 +309,7 @@ async def get_system_unallocated_user_list(
request: Request,
user_role: Annotated[UserRolePageQueryModel, Query()],
query_db: Annotated[AsyncSession, DBSessionDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysUser')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysUser)],
) -> Response:
role_user_unallocated_page_query_result = await RoleService.get_role_user_unallocated_list_services(
query_db, user_role, data_scope_sql, is_page=True
Expand All @@ -329,7 +332,7 @@ async def add_system_role_user(
add_role_user: Annotated[CrudUserRoleModel, Query()],
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
data_scope_sql: Annotated[str, DataScopeDependency('SysDept')],
data_scope_sql: Annotated[ColumnElement, DataScopeDependency(SysDept)],
) -> Response:
if not current_user.user.admin:
await RoleService.check_role_data_scope_services(query_db, str(add_role_user.role_id), data_scope_sql)
Expand Down
Loading