feat(system): 实现用户管理接口
需求 2.5.1 用户账号管理,全部要求管理员权限(require_admin 依赖):
- 接口:列表/详情/新增/编辑/删除/重置密码/启停/角色下拉,
角色下拉放 /users/meta/roles 以避开 /{user_id} 的路由匹配冲突
- 删除、禁用、改角色三处自我保护:不允许对当前登录账号执行,
避免管理员误操作后立刻失去全部管理权限且无法自行恢复
- 重置密码与禁用均提升 token_version,使已签发令牌立即失效,
不依赖 Redis 黑名单
- 密码按字节数校验(bcrypt 5.0 硬上限 72 字节,中文一字 3 字节)
- 用户列表按 id 倒序:create_time 为秒级精度,同秒数据分页结果不确定
- 修复 replace_roles 未同步关系集合的缺陷:改用 user.user_roles
集合追加,此前 session.add(UserRole(...)) 会表现为保存成功但返回空角色
- update_user 的自我保护原先依赖返回 None 的占位函数,恒不生效,
改为显式传入 operator_id
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
1 parent
ad5fe4a411
commit
e22c4bcdc9
7 files changed
+650
-4
No files matched your search
+19
-1
@@ -6,8 +6,9 @@ from fastapi import Depends
|
||||
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.core.constants import ROLE_ADMIN
|
||||
from app.core.db import get_db
|
||||
from app.core.exceptions import AuthError
|
||||
from app.core.exceptions import AuthError, ForbiddenError
|
||||
from app.core.security import decode_token
|
||||
from app.models import User
|
||||
from app.repositories import user_repository
|
||||
@@ -71,3 +72,20 @@ def _is_digits(value: object) -> bool:
|
||||
令牌内容不可信,直接 int() 会因非法输入抛 ValueError 而不是 401。
|
||||
"""
|
||||
return isinstance(value, str) and value.isdigit()
|
||||
|
||||
|
||||
def require_admin(current_user: Annotated[User, Depends(get_current_user)]) -> User:
|
||||
"""要求当前用户具备管理员角色。
|
||||
|
||||
需求 2.5.1 只定义了「系统管理员(全部权限)」与「普通用户(业务操作)」两个
|
||||
角色,故权限判定用**角色粗粒度**即可,不必引入权限码表 —— `permissions`
|
||||
与 `role_permissions` 表已建好,等业务方给出权限清单后再启用。
|
||||
|
||||
:raises ForbiddenError: 已登录但不具备管理员角色(403)
|
||||
"""
|
||||
if ROLE_ADMIN not in user_repository.get_role_codes(current_user):
|
||||
raise ForbiddenError("需要管理员权限")
|
||||
return current_user
|
||||
|
||||
|
||||
AdminUser = Annotated[User, Depends(require_admin)]
|
||||
Reference in new issue
Block a user