新增
This commit is contained in:
+23
-12
@@ -14,7 +14,7 @@ from .account_limits import (
|
||||
normalize_max_accounts,
|
||||
)
|
||||
from .account_quota import default_stop_worker, sync_user_account_quota
|
||||
from .dependencies import get_current_user, require_user_manager
|
||||
from .dependencies import get_current_user, require_role_manager, require_user_manager
|
||||
from .email_service import (
|
||||
build_password_reset_link,
|
||||
build_verification_link,
|
||||
@@ -37,6 +37,7 @@ from .role_service import (
|
||||
user_permission_payload,
|
||||
)
|
||||
from .roles import ROLE_OPERATOR, is_admin
|
||||
from .scopes import ensure_user_manageable, users_for_manager
|
||||
from .schemas import (
|
||||
LoginRequest,
|
||||
MessageResponse,
|
||||
@@ -393,17 +394,20 @@ async def list_auth_roles(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
_: User = Depends(get_current_user),
|
||||
):
|
||||
"""Lightweight role list for dropdowns (any logged-in user)."""
|
||||
"""Lightweight role list for dropdowns (any logged-in user).
|
||||
|
||||
Intentionally omits permission arrays to avoid leaking the full ACL map.
|
||||
"""
|
||||
records = await list_role_records(db)
|
||||
return RolesResponse(
|
||||
roles=[
|
||||
RoleInfo(
|
||||
value=item.code,
|
||||
label=item.label,
|
||||
description=item.description or None,
|
||||
description=None,
|
||||
is_system=item.is_system,
|
||||
is_admin=item.is_admin,
|
||||
permissions=list(item.permissions),
|
||||
permissions=[],
|
||||
)
|
||||
for item in records
|
||||
]
|
||||
@@ -417,9 +421,9 @@ roles_router = APIRouter(prefix="/api/roles", tags=["roles"])
|
||||
@users_router.get("", response_model=list[UserResponse])
|
||||
async def list_users(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
_: User = Depends(require_user_manager),
|
||||
current: User = Depends(require_user_manager),
|
||||
):
|
||||
result = await db.execute(select(User).order_by(User.id.asc()))
|
||||
result = await db.execute(users_for_manager(current).order_by(User.id.asc()))
|
||||
users = result.scalars().all()
|
||||
responses = []
|
||||
for user in users:
|
||||
@@ -431,13 +435,15 @@ async def list_users(
|
||||
async def create_user(
|
||||
body: UserCreate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
_: User = Depends(require_user_manager),
|
||||
current: User = Depends(require_user_manager),
|
||||
):
|
||||
settings = await load_settings(db)
|
||||
exists = await db.execute(select(User).where(User.username == body.username))
|
||||
if exists.scalar_one_or_none():
|
||||
raise HTTPException(status_code=400, detail="用户名已存在")
|
||||
role = await ensure_role_assignable(db, body.role)
|
||||
if is_admin(role) and not is_admin(current.role):
|
||||
raise HTTPException(status_code=403, detail="只有管理员可以分配管理员角色")
|
||||
email = await _ensure_email_available(db, str(body.email) if body.email else None)
|
||||
if settings.email_binding_required and not is_admin(role) and not email:
|
||||
raise HTTPException(status_code=400, detail="系统已开启「登录必须绑定邮箱」,请填写邮箱")
|
||||
@@ -455,6 +461,7 @@ async def create_user(
|
||||
email_verified=email_verified,
|
||||
email_verified_at=datetime.utcnow() if email and email_verified else None,
|
||||
max_accounts=normalize_max_accounts(body.max_accounts, role),
|
||||
created_by=current.id,
|
||||
)
|
||||
db.add(user)
|
||||
await db.commit()
|
||||
@@ -473,6 +480,7 @@ async def update_user(
|
||||
user = result.scalar_one_or_none()
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
ensure_user_manageable(current, user)
|
||||
settings = await load_settings(db)
|
||||
if user.id == current.id and body.is_active is False:
|
||||
raise HTTPException(status_code=400, detail="不能禁用当前登录账号")
|
||||
@@ -482,6 +490,8 @@ async def update_user(
|
||||
await guard_last_admin_change(db, user=user, deactivating=True)
|
||||
if body.role is not None:
|
||||
new_role = await ensure_role_assignable(db, body.role)
|
||||
if is_admin(new_role) and not is_admin(current.role):
|
||||
raise HTTPException(status_code=403, detail="只有管理员可以分配管理员角色")
|
||||
await guard_last_admin_change(db, user=user, new_role=new_role)
|
||||
|
||||
if body.display_name is not None:
|
||||
@@ -541,6 +551,7 @@ async def delete_user(
|
||||
user = result.scalar_one_or_none()
|
||||
if not user:
|
||||
raise HTTPException(status_code=404, detail="用户不存在")
|
||||
ensure_user_manageable(current, user)
|
||||
await guard_last_admin_change(db, user=user, deleting=True)
|
||||
await db.delete(user)
|
||||
await db.commit()
|
||||
@@ -550,7 +561,7 @@ async def delete_user(
|
||||
@roles_router.get("", response_model=RolesResponse)
|
||||
async def admin_list_roles(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
_: User = Depends(require_user_manager),
|
||||
_: User = Depends(require_role_manager),
|
||||
):
|
||||
records = await list_role_records(db)
|
||||
roles = []
|
||||
@@ -570,7 +581,7 @@ async def admin_list_roles(
|
||||
|
||||
|
||||
@roles_router.get("/catalog", response_model=PermissionCatalogResponse)
|
||||
async def get_permission_catalog(_: User = Depends(require_user_manager)):
|
||||
async def get_permission_catalog(_: User = Depends(require_role_manager)):
|
||||
return PermissionCatalogResponse(**permission_catalog())
|
||||
|
||||
|
||||
@@ -578,7 +589,7 @@ async def get_permission_catalog(_: User = Depends(require_user_manager)):
|
||||
async def create_custom_role(
|
||||
body: RoleCreate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
_: User = Depends(require_user_manager),
|
||||
_: User = Depends(require_role_manager),
|
||||
):
|
||||
record = await create_role(
|
||||
db,
|
||||
@@ -603,7 +614,7 @@ async def update_custom_role(
|
||||
code: str,
|
||||
body: RoleUpdate,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
_: User = Depends(require_user_manager),
|
||||
_: User = Depends(require_role_manager),
|
||||
):
|
||||
record = await update_role(
|
||||
db,
|
||||
@@ -627,7 +638,7 @@ async def update_custom_role(
|
||||
async def delete_custom_role(
|
||||
code: str,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
_: User = Depends(require_user_manager),
|
||||
_: User = Depends(require_role_manager),
|
||||
):
|
||||
await delete_role(db, code)
|
||||
return {"message": "角色已删除"}
|
||||
|
||||
Reference in New Issue
Block a user