清理全局角色残留并修复项目权限判断
This commit is contained in:
+47
-17
@@ -12,6 +12,7 @@ from app.core.exceptions import AppException
|
||||
from app.core.security import decode_token, oauth2_scheme
|
||||
from app.crud import user as user_crud
|
||||
from app.crud import member as member_crud
|
||||
from app.core.api_permissions import SYSTEM_PERMISSIONS
|
||||
from app.core.project_permissions import role_has_api_permission, get_missing_prerequisites
|
||||
from app.db.session import SessionLocal
|
||||
from app.models.study_member import StudyMember
|
||||
@@ -53,12 +54,15 @@ async def get_current_user(
|
||||
return user
|
||||
|
||||
|
||||
def is_system_admin(user) -> bool:
|
||||
return bool(getattr(user, "is_admin", False))
|
||||
|
||||
|
||||
def require_roles(roles: Iterable[str]) -> Callable:
|
||||
roles_set = set(roles)
|
||||
|
||||
async def dependency(current_user=Depends(get_current_user)):
|
||||
current_role = current_user.role.value if hasattr(current_user.role, "value") else str(current_user.role)
|
||||
if current_role not in roles_set:
|
||||
if "ADMIN" not in roles_set or not is_system_admin(current_user):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="权限不足",
|
||||
@@ -68,10 +72,6 @@ def require_roles(roles: Iterable[str]) -> Callable:
|
||||
return dependency
|
||||
|
||||
|
||||
def _role_value(user) -> str:
|
||||
return user.role.value if hasattr(user.role, "value") else str(user.role)
|
||||
|
||||
|
||||
async def list_active_pm_study_ids(db: AsyncSession, user_id: uuid.UUID) -> set[uuid.UUID]:
|
||||
result = await db.execute(
|
||||
select(StudyMember.study_id).where(
|
||||
@@ -95,12 +95,21 @@ async def is_active_project_pm(db: AsyncSession, user_id: uuid.UUID, study_id: u
|
||||
return result.scalar_one_or_none() is not None
|
||||
|
||||
|
||||
async def get_operator_role_label(db: AsyncSession, study_id: uuid.UUID | None, current_user) -> str:
|
||||
if is_system_admin(current_user):
|
||||
return "ADMIN"
|
||||
if not study_id:
|
||||
return ""
|
||||
membership = await member_crud.get_member(db, study_id, current_user.id)
|
||||
return membership.role_in_study if membership and membership.is_active else ""
|
||||
|
||||
|
||||
def require_admin_or_any_project_pm() -> Callable:
|
||||
async def dependency(
|
||||
current_user=Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db_session),
|
||||
):
|
||||
if _role_value(current_user) == "ADMIN":
|
||||
if is_system_admin(current_user):
|
||||
return current_user
|
||||
if await list_active_pm_study_ids(db, current_user.id):
|
||||
return current_user
|
||||
@@ -112,13 +121,38 @@ def require_admin_or_any_project_pm() -> Callable:
|
||||
return dependency
|
||||
|
||||
|
||||
def require_system_permission(permission_key: str) -> Callable:
|
||||
async def dependency(
|
||||
study_id: uuid.UUID,
|
||||
current_user=Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db_session),
|
||||
):
|
||||
permission = SYSTEM_PERMISSIONS.get(permission_key)
|
||||
if not permission:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="权限不足",
|
||||
)
|
||||
|
||||
allowed_roles = set(permission.get("roles", []))
|
||||
if is_system_admin(current_user) and "ADMIN" in allowed_roles:
|
||||
return current_user
|
||||
if "PM" in allowed_roles and await is_active_project_pm(db, current_user.id, study_id):
|
||||
return current_user
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="权限不足",
|
||||
)
|
||||
|
||||
return dependency
|
||||
|
||||
|
||||
async def get_study_member(
|
||||
study_id: uuid.UUID,
|
||||
current_user=Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db_session),
|
||||
):
|
||||
role_value = _role_value(current_user)
|
||||
if role_value == "ADMIN":
|
||||
if is_system_admin(current_user):
|
||||
return None
|
||||
return await member_crud.get_member(db, study_id, current_user.id)
|
||||
|
||||
@@ -129,8 +163,7 @@ def require_study_member():
|
||||
current_user=Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db_session),
|
||||
):
|
||||
role_value = _role_value(current_user)
|
||||
if role_value == "ADMIN":
|
||||
if is_system_admin(current_user):
|
||||
return current_user
|
||||
membership = await member_crud.get_member(db, study_id, current_user.id)
|
||||
if not membership or not membership.is_active:
|
||||
@@ -152,8 +185,7 @@ def require_study_roles(roles: Iterable[str], *, allow_system_admin: bool = True
|
||||
current_user=Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db_session),
|
||||
):
|
||||
role_value = _role_value(current_user)
|
||||
if allow_system_admin and role_value == "ADMIN":
|
||||
if allow_system_admin and is_system_admin(current_user):
|
||||
return current_user
|
||||
membership = await member_crud.get_member(db, study_id, current_user.id)
|
||||
if not membership or not membership.is_active or membership.role_in_study not in roles_set:
|
||||
@@ -183,8 +215,7 @@ def require_api_permission(endpoint_key: str, *, allow_system_admin: bool = True
|
||||
db: AsyncSession = Depends(get_db_session),
|
||||
):
|
||||
from app.core.permission_monitor import get_permission_monitor
|
||||
role_value = _role_value(current_user)
|
||||
if allow_system_admin and role_value == "ADMIN":
|
||||
if allow_system_admin and is_system_admin(current_user):
|
||||
_enqueue_permission_log(
|
||||
study_id, current_user.id, endpoint_key, "ADMIN", True, 0.0, request
|
||||
)
|
||||
@@ -275,8 +306,7 @@ async def get_cra_site_scope(
|
||||
) -> tuple[set[uuid.UUID], set[str]] | None:
|
||||
from app.crud import site as site_crud
|
||||
|
||||
role_value = current_user.role.value if hasattr(current_user.role, "value") else current_user.role
|
||||
if role_value == "ADMIN":
|
||||
if is_system_admin(current_user):
|
||||
return None
|
||||
membership = await member_crud.get_member(db, study_id, current_user.id)
|
||||
if not membership or not membership.is_active:
|
||||
|
||||
Reference in New Issue
Block a user