init: 初始化 dpb 桃育种系统代码库
前后端 + 后端 FastAPI 全量源码、部署脚本与文档。
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.sql.elements import ColumnElement
|
||||
|
||||
from app.core.base_schema import AuthSchema
|
||||
from app.utils.common_util import get_child_id_map, get_child_recursion
|
||||
|
||||
|
||||
class Permission:
|
||||
"""为业务模型提供数据权限过滤功能"""
|
||||
|
||||
# 数据权限常量定义,提高代码可读性
|
||||
DATA_SCOPE_SELF = 1 # 仅本人数据
|
||||
DATA_SCOPE_DEPT_AND_CHILD = 2 # 本部门及以下数据
|
||||
DATA_SCOPE_ALL = 3 # 全部数据
|
||||
|
||||
def __init__(self, model: Any, auth: AuthSchema, db: AsyncSession) -> None:
|
||||
self.model = model
|
||||
self.auth = auth
|
||||
self.db = db
|
||||
|
||||
async def filter_query(self, query: Any) -> Any:
|
||||
condition = await self._permission_condition()
|
||||
return query.where(condition) if condition is not None else query
|
||||
|
||||
async def _permission_condition(self) -> ColumnElement | None:
|
||||
if not self.auth.user or not self.auth.user.id:
|
||||
return None
|
||||
|
||||
if self.auth.user.is_superuser:
|
||||
return None
|
||||
|
||||
return await self._filter_by_data_scope()
|
||||
|
||||
async def _filter_by_data_scope(self) -> ColumnElement | None:
|
||||
from app.api.v1.module_system.role.model import RoleModel
|
||||
from app.api.v1.module_system.user.model import UserModel
|
||||
|
||||
if not hasattr(self.model, "created_id"):
|
||||
return None
|
||||
|
||||
stmt = select(RoleModel).join(
|
||||
RoleModel.users
|
||||
).where(UserModel.id == self.auth.user.id)
|
||||
result = await self.db.execute(stmt)
|
||||
roles = result.scalars().all()
|
||||
|
||||
if not roles:
|
||||
created_id_attr = getattr(self.model, "created_id", None)
|
||||
if created_id_attr is not None and self.auth.user and self.auth.user.id:
|
||||
return created_id_attr == self.auth.user.id
|
||||
return None
|
||||
|
||||
data_scopes = {role.data_scope for role in roles}
|
||||
|
||||
if self.DATA_SCOPE_ALL in data_scopes:
|
||||
return None
|
||||
|
||||
accessible_dept_ids = await self._get_accessible_dept_ids(data_scopes)
|
||||
|
||||
if accessible_dept_ids:
|
||||
if self.model.__name__ == "UserModel" and hasattr(self.model, "dept_id"):
|
||||
dept_id_attr = getattr(self.model, "dept_id", None)
|
||||
if dept_id_attr is not None:
|
||||
return dept_id_attr.in_(list(accessible_dept_ids))
|
||||
|
||||
creator_rel = getattr(self.model, "created_by", None)
|
||||
if creator_rel is not None and hasattr(UserModel, "dept_id"):
|
||||
return creator_rel.has(UserModel.dept_id.in_(list(accessible_dept_ids)))
|
||||
|
||||
created_id_attr = getattr(self.model, "created_id", None)
|
||||
if created_id_attr is not None and self.auth.user and self.auth.user.id:
|
||||
return created_id_attr == self.auth.user.id
|
||||
return None
|
||||
|
||||
if self.DATA_SCOPE_SELF in data_scopes:
|
||||
if self.model.__name__ == "UserModel":
|
||||
id_attr = getattr(self.model, "id", None)
|
||||
if id_attr is not None and self.auth.user and self.auth.user.id:
|
||||
return id_attr == self.auth.user.id
|
||||
created_id_attr = getattr(self.model, "created_id", None)
|
||||
if created_id_attr is not None and self.auth.user and self.auth.user.id:
|
||||
return created_id_attr == self.auth.user.id
|
||||
return None
|
||||
|
||||
created_id_attr = getattr(self.model, "created_id", None)
|
||||
if created_id_attr is not None and self.auth.user and self.auth.user.id:
|
||||
return created_id_attr == self.auth.user.id
|
||||
return None
|
||||
|
||||
async def _get_accessible_dept_ids(self, data_scopes: set) -> set[int]:
|
||||
accessible_dept_ids = set()
|
||||
user_dept_id = getattr(self.auth.user, "dept_id", None)
|
||||
|
||||
if self.DATA_SCOPE_DEPT_AND_CHILD in data_scopes and user_dept_id is not None:
|
||||
try:
|
||||
from app.api.v1.module_system.dept.model import DeptModel
|
||||
|
||||
dept_sql = select(DeptModel)
|
||||
dept_result = await self.db.execute(dept_sql)
|
||||
dept_objs = dept_result.scalars().all()
|
||||
id_map = get_child_id_map(dept_objs)
|
||||
dept_with_children_ids = get_child_recursion(id=user_dept_id, id_map=id_map)
|
||||
accessible_dept_ids.update(dept_with_children_ids)
|
||||
except Exception:
|
||||
accessible_dept_ids.add(user_dept_id)
|
||||
|
||||
return accessible_dept_ids
|
||||
Reference in New Issue
Block a user