diff --git a/api/app/controllers/user_controller.py b/api/app/controllers/user_controller.py index 16213690..20e2b974 100644 --- a/api/app/controllers/user_controller.py +++ b/api/app/controllers/user_controller.py @@ -111,6 +111,18 @@ def get_current_user_info( break api_logger.info(f"当前用户信息获取成功: {result.username}, 角色: {result_schema.role}, 工作空间: {result_schema.current_workspace_name}") + + # 设置权限:如果用户来自 SSO Source,则使用该 Source 的 permissions;否则返回全部权限 + if current_user.external_source: + from premium.sso.models import SSOSource + source = db.query(SSOSource).filter(SSOSource.source_code == current_user.external_source).first() + if source and source.permissions: + result_schema.permissions = source.permissions + else: + result_schema.permissions = [] + else: + result_schema.permissions = ["pricing", "user"] + return success(data=result_schema, msg=t("users.info.get_success")) @@ -135,6 +147,63 @@ def get_tenant_superusers( return success(data=superusers_schema, msg=t("users.list.superusers_success")) +@router.get("/tenant/users", response_model=ApiResponse) +def get_tenant_users( + page: int = 1, + size: int = 20, + is_active: bool = None, + is_superuser: bool = None, + search: str = None, + db: Session = Depends(get_db), + current_user: User = Depends(get_current_user), + t: Callable = Depends(get_translator) +): + """获取当前用户所在租户的用户列表(普通用户可访问)""" + api_logger.info(f"获取租户用户列表请求: tenant_id={current_user.tenant_id}, 操作者: {current_user.username}") + + if not current_user.tenant_id: + raise BusinessException("用户没有租户信息", code=BizCode.TENANT_NOT_FOUND) + + from app.services.tenant_service import TenantService + tenant_service = TenantService(db) + + skip = (page - 1) * size + users = tenant_service.get_tenant_users( + tenant_id=current_user.tenant_id, + skip=skip, + limit=size, + is_active=is_active, + is_superuser=is_superuser, + search=search + ) + total = tenant_service.count_tenant_users( + tenant_id=current_user.tenant_id, + is_active=is_active, + is_superuser=is_superuser, + search=search + ) + + users_schema = [user_schema.User.model_validate(u) for u in users] + for u_schema in users_schema: + user = users[[s.id for s in users_schema].index(u_schema.id)] + if user.external_source: + from premium.sso.models import SSOSource + source = db.query(SSOSource).filter(SSOSource.source_code == user.external_source).first() + u_schema.permissions = source.permissions if source and source.permissions else [] + else: + u_schema.permissions = ["pricing", "user"] + + return success( + data={ + "users": users_schema, + "total": total, + "page": page, + "size": size, + }, + msg=t("users.list.get_success") + ) + + @router.get("/{user_id}", response_model=ApiResponse) def get_user_info_by_id( diff --git a/api/app/repositories/user_repository.py b/api/app/repositories/user_repository.py index 3f8919aa..af4449e5 100644 --- a/api/app/repositories/user_repository.py +++ b/api/app/repositories/user_repository.py @@ -158,22 +158,26 @@ class UserRepository: raise def get_users_by_tenant( - self, - tenant_id: uuid.UUID, - skip: int = 0, + self, + tenant_id: uuid.UUID, + skip: int = 0, limit: int = 100, is_active: Optional[bool] = None, + is_superuser: Optional[bool] = None, search: Optional[str] = None ) -> List[User]: """获取租户下的用户列表""" db_logger.debug(f"查询租户用户: tenant_id={tenant_id}") - + try: query = self.db.query(User).options(joinedload(User.tenant)).filter(User.tenant_id == tenant_id) - + if is_active is not None: query = query.filter(User.is_active == is_active) - + + if is_superuser is not None: + query = query.filter(User.is_superuser == is_superuser) + if search: query = query.filter( or_( @@ -181,7 +185,7 @@ class UserRepository: User.email.ilike(f"%{search}%") ) ) - + users = query.offset(skip).limit(limit).all() db_logger.debug(f"租户用户查询成功: tenant_id={tenant_id}, count={len(users)}") return users @@ -190,18 +194,22 @@ class UserRepository: raise def count_users_by_tenant( - self, + self, tenant_id: uuid.UUID, is_active: Optional[bool] = None, + is_superuser: Optional[bool] = None, search: Optional[str] = None ) -> int: """统计租户下的用户数量""" try: query = self.db.query(func.count(User.id)).filter(User.tenant_id == tenant_id) - + if is_active is not None: query = query.filter(User.is_active == is_active) - + + if is_superuser is not None: + query = query.filter(User.is_superuser == is_superuser) + if search: query = query.filter( or_( @@ -209,7 +217,7 @@ class UserRepository: User.email.ilike(f"%{search}%") ) ) - + return query.scalar() except Exception as e: db_logger.error(f"统计租户用户失败: tenant_id={tenant_id} - {str(e)}") diff --git a/api/app/schemas/user_schema.py b/api/app/schemas/user_schema.py index 6b880696..f307a5a3 100644 --- a/api/app/schemas/user_schema.py +++ b/api/app/schemas/user_schema.py @@ -1,6 +1,6 @@ from dataclasses import field from pydantic import BaseModel, EmailStr, Field, field_validator, validator, ConfigDict -from typing import Optional +from typing import Optional, List import datetime import uuid @@ -85,6 +85,7 @@ class User(UserBase): current_workspace_name: Optional[str] = None role: Optional[WorkspaceRole] = None preferred_language: Optional[str] = "zh" # 用户语言偏好 + permissions: Optional[List[str]] = None # 用户权限列表,由 external_source 的 permissions 控制 # 将 datetime 转换为毫秒时间戳 @validator("created_at", pre=True) diff --git a/api/app/services/tenant_service.py b/api/app/services/tenant_service.py index 066edf57..b9c5800d 100644 --- a/api/app/services/tenant_service.py +++ b/api/app/services/tenant_service.py @@ -142,11 +142,12 @@ class TenantService: # 租户用户管理 def get_tenant_users( - self, - tenant_id: uuid.UUID, - skip: int = 0, + self, + tenant_id: uuid.UUID, + skip: int = 0, limit: int = 100, is_active: Optional[bool] = None, + is_superuser: Optional[bool] = None, search: Optional[str] = None ) -> List[UserModel]: """获取租户下的用户列表""" @@ -155,19 +156,22 @@ class TenantService: skip=skip, limit=limit, is_active=is_active, + is_superuser=is_superuser, search=search ) def count_tenant_users( - self, + self, tenant_id: uuid.UUID, is_active: Optional[bool] = None, + is_superuser: Optional[bool] = None, search: Optional[str] = None ) -> int: """统计租户下的用户数量""" return self.user_repo.count_users_by_tenant( tenant_id=tenant_id, is_active=is_active, + is_superuser=is_superuser, search=search )