BookSystem/backend/auth/schemas.py
jayhgq 19d6db6ecc feat: 添加登录日志和操作日志功能
1. 新增日志相关数据库模型、API路由、前端页面与权限配置
2. 为现有业务接口添加操作日志记录功能
3. 优化导入顺序与权限初始化数据
2026-06-12 22:41:41 +08:00

288 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from pydantic import BaseModel, Field
from typing import Optional
from datetime import datetime
class UserBase(BaseModel):
"""用户基础模型"""
username: str = Field(
...,
min_length=3,
max_length=50,
description="登录名",
json_schema_extra={
"error_messages": {
"min_length": "用户名长度至少为3个字符",
"max_length": "用户名长度不能超过50个字符"
}
}
)
nickname: str = Field(..., max_length=50, description="昵称")
email: Optional[str] = Field(None, max_length=50, description="电子邮箱")
phone: Optional[str] = Field(None, max_length=11, description="手机号码")
wx_openid: Optional[str] = Field(None, max_length=100, description="微信OpenID")
avatar: Optional[str] = Field(None, max_length=255, description="头像路径")
role_id: Optional[int] = Field(2, description="角色ID")
model_config = {"extra": "ignore"}
class UserCreateRequest(UserBase):
"""用户创建请求模型"""
password: str = Field(
...,
min_length=6,
max_length=50,
description="密码",
json_schema_extra={
"error_messages": {
"min_length": "密码长度至少为6个字符",
"max_length": "密码长度不能超过50个字符"
}
}
)
class UserCreate(UserBase):
"""用户创建模型"""
password_hash: str = Field(
..., min_length=6, max_length=128, description="密码哈希值"
)
class UserUpdate(BaseModel):
"""用户更新模型"""
username: str = Field(..., min_length=3, max_length=50, description="登录名")
nickname: str = Field(..., max_length=50, description="昵称")
email: Optional[str] = Field(None, max_length=50, description="电子邮箱")
phone: Optional[str] = Field(None, max_length=11, description="手机号码")
wx_openid: Optional[str] = Field(None, max_length=100, description="微信OpenID")
avatar: Optional[str] = Field(None, max_length=255, description="头像路径")
role_id: Optional[int] = Field(2, description="角色ID")
password: Optional[str] = Field(None, max_length=128, description="密码")
class UserLogin(BaseModel):
"""用户登录模型"""
username: str = Field(..., description="登录名")
password: str = Field(..., description="密码")
captcha_id: str = Field(..., description="验证码ID")
captcha_code: str = Field(..., description="验证码")
class UserResponse(BaseModel):
"""用户响应模型"""
id: int = Field(..., description="用户ID")
username: str = Field(..., description="登录名")
nickname: str = Field(..., description="昵称")
email: Optional[str] = Field(None, description="电子邮箱")
phone: Optional[str] = Field(None, description="手机号码")
wx_openid: Optional[str] = Field(None, description="微信OpenID")
avatar: Optional[str] = Field(None, description="头像路径")
role_id: int = Field(..., description="角色ID")
createtime: datetime = Field(..., description="创建时间")
updatetime: datetime = Field(..., description="更新时间")
lastlogintime: Optional[datetime] = Field(None, description="最后登录时间")
class Config:
from_attributes = True
class Token(BaseModel):
"""令牌模型"""
access_token: str = Field(..., description="访问令牌")
token_type: str = Field(..., description="令牌类型")
class TokenData(BaseModel):
"""令牌数据模型"""
user_id: Optional[int] = None
email: Optional[str] = None
class RoleBase(BaseModel):
"""角色基础模型"""
name: str = Field(..., max_length=50, description="角色名称")
class RoleCreate(RoleBase):
"""角色创建模型"""
creator: Optional[str] = Field(None, max_length=50, description="创建人")
class RoleResponse(RoleBase):
"""角色响应模型"""
id: int = Field(..., description="角色ID")
createtime: datetime = Field(..., description="创建时间")
updatetime: datetime = Field(..., description="更新时间")
creator: Optional[str] = Field(None, description="创建人")
class Config:
from_attributes = True
# 权限相关模型
class PermissionBase(BaseModel):
"""权限基础模型"""
name: str = Field(..., max_length=100, description="权限名称")
code: str = Field(..., max_length=100, description="权限编码")
parentid: int = Field(0, description="父权限ID0表示顶级模块")
route: Optional[str] = Field(None, max_length=255, description="前端路由路径")
description: Optional[str] = Field(None, max_length=255, description="权限描述")
class PermissionCreate(PermissionBase):
"""权限创建模型"""
pass
class PermissionResponse(PermissionBase):
"""权限响应模型"""
id: int = Field(..., description="权限ID")
createtime: datetime = Field(..., description="创建时间")
updatetime: datetime = Field(..., description="更新时间")
class Config:
from_attributes = True
class PermissionTreeResponse(BaseModel):
"""权限树响应模型"""
id: int = Field(..., description="权限ID")
name: str = Field(..., description="权限名称")
code: str = Field(..., description="权限编码")
parentid: int = Field(..., description="父权限ID")
route: Optional[str] = Field(None, description="前端路由路径")
createtime: Optional[datetime] = Field(None, description="创建时间")
updatetime: Optional[datetime] = Field(None, description="更新时间")
description: Optional[str] = Field(None, description="权限描述")
children: list = Field([], description="子权限列表")
# 角色权限关联相关模型
class RolePermissionAssign(BaseModel):
"""角色权限分配模型"""
role_id: int = Field(..., description="角色ID")
permission_ids: list[int] = Field(..., description="权限ID列表")
class RolePermissionResponse(BaseModel):
"""角色权限响应模型"""
role_id: int = Field(..., description="角色ID")
role_name: str = Field(..., description="角色名称")
permissions: list[PermissionResponse] = Field(..., description="权限列表")
menu: list = Field([], description="菜单树形结构")
# 系统设置相关模型
class SystemSettingBase(BaseModel):
"""系统设置基础模型"""
key: str = Field(..., max_length=100, description="设置键名")
value: str = Field(..., max_length=2000, description="设置值")
type: Optional[str] = Field("string", max_length=20, description="类型string/image/select/boolean")
options: Optional[str] = Field(None, max_length=500, description="下拉选项(用|分隔)")
description: Optional[str] = Field(None, max_length=255, description="设置描述")
model_config = {"extra": "ignore"}
class SystemSettingCreate(SystemSettingBase):
"""系统设置创建模型"""
pass
class SystemSettingUpdate(SystemSettingBase):
"""系统设置更新模型"""
key: Optional[str] = Field(None, max_length=100, description="设置键名")
class SystemSettingResponse(BaseModel):
"""系统设置响应模型"""
id: int = Field(..., description="设置ID")
key: str = Field(..., description="设置键名")
value: str = Field(..., description="设置值")
type: str = Field(..., description="类型")
options: Optional[str] = Field(None, description="下拉选项")
description: Optional[str] = Field(None, description="设置描述")
createtime: datetime = Field(..., description="创建时间")
updatetime: datetime = Field(..., description="更新时间")
class Config:
from_attributes = True
class LoginLogResponse(BaseModel):
"""登录日志响应模型"""
id: int = Field(..., description="日志ID")
username: str = Field(..., description="用户名")
login_time: datetime = Field(..., description="登录时间")
ip_address: Optional[str] = Field(None, description="IP地址")
user_agent: Optional[str] = Field(None, description="User-Agent")
status: str = Field(..., description="状态: success/failure")
failure_reason: Optional[str] = Field(None, description="失败原因")
class Config:
from_attributes = True
class LoginLogSearch(BaseModel):
"""登录日志搜索模型"""
username: Optional[str] = Field(None, description="用户名(模糊搜索)")
status: Optional[str] = Field(None, description="状态")
start_time: Optional[datetime] = Field(None, description="开始时间")
end_time: Optional[datetime] = Field(None, description="结束时间")
class LoginLogCleanRequest(BaseModel):
"""登录日志清理请求模型"""
before_date: datetime = Field(..., description="清理此日期之前的日志")
class OperationLogResponse(BaseModel):
"""操作日志响应模型"""
id: int = Field(..., description="日志ID")
user_id: int = Field(..., description="用户ID")
username: str = Field(..., description="用户名")
action_type: str = Field(..., description="操作类型: create/update/delete")
target_type: str = Field(..., description="目标类型: user/role/permission/setting")
target_id: Optional[int] = Field(None, description="目标ID")
target_name: Optional[str] = Field(None, description="目标名称")
detail: Optional[str] = Field(None, description="变更详情(JSON)")
ip_address: Optional[str] = Field(None, description="IP地址")
user_agent: Optional[str] = Field(None, description="User-Agent")
createtime: datetime = Field(..., description="创建时间")
class Config:
from_attributes = True
class OperationLogSearch(BaseModel):
"""操作日志搜索模型"""
username: Optional[str] = Field(None, description="用户名(模糊搜索)")
action_type: Optional[str] = Field(None, description="操作类型")
target_type: Optional[str] = Field(None, description="目标类型")
start_time: Optional[datetime] = Field(None, description="开始时间")
end_time: Optional[datetime] = Field(None, description="结束时间")