| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- """删除权限:仅创建人可删(super_admin 例外)。"""
- from __future__ import annotations
- from typing import Any, Dict, Iterable, Optional, Union
- from fastapi import HTTPException
- RowLike = Union[Any, Dict[str, Any]]
- def normalize_user_info(
- user_info: Optional[Dict[str, Any]] = None,
- *,
- user_id: Optional[str] = None,
- actor_name: Optional[str] = None,
- ) -> Dict[str, Any]:
- info: Dict[str, Any] = dict(user_info or {})
- uid = (user_id or info.get("user_id") or info.get("id") or "").strip()
- if uid:
- info["user_id"] = uid
- name = (actor_name or info.get("real_name") or info.get("username") or info.get("userName") or info.get("name") or "").strip()
- if name:
- info["real_name"] = name
- return info
- def user_info_from_context(ctx_or_dict: Any) -> Dict[str, Any]:
- if isinstance(ctx_or_dict, dict):
- return normalize_user_info(ctx_or_dict)
- info: Dict[str, Any] = {}
- if hasattr(ctx_or_dict, "to_user_info"):
- info.update(ctx_or_dict.to_user_info())
- name = (getattr(ctx_or_dict, "name", None) or "").strip()
- if name:
- info["real_name"] = name
- return normalize_user_info(info)
- def is_super_admin(user_info: Optional[Dict[str, Any]]) -> bool:
- if not user_info:
- return False
- return (user_info.get("role") or "").strip() == "super_admin"
- def row_creator_id(row: RowLike) -> str:
- if row is None:
- return ""
- if isinstance(row, dict):
- return (row.get("create_by") or row.get("createBy") or "").strip()
- return (getattr(row, "create_by", None) or getattr(row, "createBy", None) or "").strip()
- def _actor_ids(user_info: Optional[Dict[str, Any]]) -> set[str]:
- if not user_info:
- return set()
- ids: set[str] = set()
- for key in ("user_id", "id"):
- val = (user_info.get(key) or "").strip()
- if val:
- ids.add(val)
- return ids
- def _actor_names(user_info: Optional[Dict[str, Any]]) -> set[str]:
- if not user_info:
- return set()
- names: set[str] = set()
- for key in ("real_name", "username", "userName", "name"):
- val = (user_info.get(key) or "").strip()
- if val:
- names.add(val)
- return names
- def can_delete_by_creator(
- row: RowLike,
- user_info: Optional[Dict[str, Any]] = None,
- *,
- user_id: Optional[str] = None,
- actor_name: Optional[str] = None,
- ) -> bool:
- info = normalize_user_info(user_info, user_id=user_id, actor_name=actor_name)
- if is_super_admin(info):
- return True
- creator = row_creator_id(row)
- if not creator:
- return False
- if creator in _actor_ids(info):
- return True
- if creator in _actor_names(info):
- return True
- return False
- def assert_row_deletable_by_creator(
- row: RowLike,
- user_info: Optional[Dict[str, Any]] = None,
- *,
- user_id: Optional[str] = None,
- actor_name: Optional[str] = None,
- message: str = "仅创建人可删除",
- ) -> None:
- if can_delete_by_creator(row, user_info, user_id=user_id, actor_name=actor_name):
- return
- raise HTTPException(status_code=403, detail=message)
- def assert_rows_deletable_by_creator(
- rows: Iterable[RowLike],
- user_info: Optional[Dict[str, Any]] = None,
- *,
- user_id: Optional[str] = None,
- actor_name: Optional[str] = None,
- message: str = "仅创建人可删除",
- ) -> None:
- info = normalize_user_info(user_info, user_id=user_id, actor_name=actor_name)
- for row in rows:
- assert_row_deletable_by_creator(row, info, message=message)
|