Files
FastapiAdmin/backend
zhangtao 07fa789d2e fix(backend): 安全默认值、异常语义、代码生成注入面与定时任务内置处理器
本批为 t10 → t13 → t15 三轮实现 + 一轮复核驳回整改的最终形态(pytest 83 passed / ruff clean,
已部署并线上验证)。

异常语义
- CustomException 默认状态码 500 → 400(约 433 处裸调用不再被计为服务端故障),
  且「包装底层异常」的 130 处显式恢复 500;get_or_404 → 404;响应体结构不变

代码生成注入面(复核 blocker F1,二次修复)
- column_type 不再做字符串拼接:改为常量白名单派生(类型名 ∈ DB_TO_SQLALCHEMY ∪ {Boolean},
  长度仅取数字/正则捕获),彻底移除 split("(")[1]
- 列类型加形状白名单;字符串/注释/文档字符串用 \uXXXX,标识符过 safe_ident(含 Python/JS 关键字),
  .vue 文本与静态属性改 HTML 实体
- 落盘闸门由 ast.parse 升级为 assert_python_structure(语法 + 顶层语句白名单 + 与哨兵骨架逐节点比对)
  与 assert_text_structure(.vue/.ts/.toml 行结构);U+2028/2029 与 C1 控制符纳入转义

安全默认值
- 生产 CORS 不再回落 ["*"](未配置即拒绝跨域,可选 CORS_STRICT_STARTUP 直接启动失败)
- OAUTH_ALLOWED_HOSTS 不再默认 "*";新增 ALLOW_LOCALHOST_HOSTS 控制 Host 校验范围
- ALLOWED_HOSTS 收窄为按配置派生;健康检查暴露 code_exec_enabled / cors_origins_configured

定时任务
- SCHEDULER_ALLOW_CODE_EXEC 默认 False;新增 builtin:<模块名>[.<函数名>] 内置处理器路线(不经 exec)
- 判定收敛到 describe_schedulability;列表返回 schedulable / unschedulable_reason;
  启动 reconcile 与状态查询对「已启用但不可调度」打 WARN(去重、恢复后清除)
- 加固:内置处理器必须在本模块内定义或经 HANDLERS 声明,拒绝模块内导入的外部对象(复核 R1)
- 顺带修复:_WARNED_UNSCHEDULABLE 的 set.pop TypeError、job.next_run_time 缺失导致的列表 500

测试:新增 tests/test_generator_template_safety.py、test_security_defaults.py、
test_scheduler_schedulability.py(含恶意载荷、闸门红绿、静态护栏)
2026-10-04 05:12:32 +08:00
..

FastApiAdmin - Backend

基于 FastAPI 框架构建的企业级后端架构,为前端 Vue3 管理系统提供完整的 API 服务支持。

与仓库根文档的关系:项目总览、一键前后端启动、演示账号、Docker 部署、架构图与默认端口等请以 根目录 README.md 为准;本文档侧重 backend/ 目录结构、迁移命令与后端开发约定。

技术栈

技术 版本 说明
FastAPI 0.138.2 现代 Web 框架
SQLAlchemy 2.0.51 ORM 框架
Alembic 1.18.4 数据库迁移工具
Pydantic 2.12.5+ 数据验证与序列化
APScheduler 3.11.0 定时任务调度
redis-py 7.1.0 缓存与会话存储
Uvicorn 0.49.0 ASGI 服务器
Python 3.12+ 运行环境

项目结构

backend/
├── app/                     # 项目核心代码
│   ├── alembic/             # 数据库迁移管理
│   ├── api/                 # 路由装配层(routers.py 按域分组聚合各模块路由)
│   ├── modules/             # 业务模块层(按业务域竖切)
│   │   ├── system/          #   系统管理
│   │   ├── monitor/         #   系统监控
│   │   ├── task/            #   定时任务(cronjob)+ 存储传输(storage)
│   │   ├── generator/       #   代码生成
│   │   ├── ai/              #   AI 功能
│   │   └── common/          #   文件上传 / 公共能力
│   ├── common/              # 公共组件(常量、枚举、响应封装)
│   ├── config/              # 项目配置文件
│   ├── core/                # 核心模块(数据库、中间件、安全)
│   ├── plugin/              # 插件模块(二开目录)
│   ├── scripts/             # 初始化脚本和数据
│   └── utils/               # 工具类(验证码、文件上传等)
├── env/                     # 环境配置文件
├── logs/                    # 日志输出目录
├── sql/                     # SQL 初始化脚本
├── static/                  # 静态资源文件
├── main.py                  # CLI 入口(run 启动 / revision 生成迁移 / upgrade 应用迁移)
├── alembic.ini              # Alembic 迁移配置
├── requirements.txt         # Python 依赖包
└── pyproject.toml           # 项目配置(uv / ruff)

模块分层

每个业务模块采用统一的分层结构:

modules/<模块>/<子域>/
├── controller.py    # 控制器 - HTTP 请求处理
├── service.py       # 服务层 - 业务逻辑处理
├── crud.py          # 数据层 - 数据库操作
├── model.py         # ORM 模型 - 数据库表定义
├── schema.py        # Pydantic 模型 - 数据验证
└── param.py         # 参数模型 - 请求参数

分包理念(按业务竖切 vs 按技术层次分包)详见 项目概述。

快速开始

环境要求

  • Python: 3.12+
  • 数据库: MySQL 8.0+ / PostgreSQL 13+ / SQLite 3.x(连接串在 env/.env.dev)
  • Redis: 与 .env.dev 中配置一致

第一次在本机跑起来

  1. 复制 env/.env.example → env/.env.dev,填写数据库、Redis 等(先在 DB 中建好空库)。
  2. 在 backend/ 目录下 安装依赖:推荐 uv sync;或 pip install -r requirements.txt。
  3. 启动:uv run main.py run --env=dev(或 python main.py run --env=dev)。首次启动会自动初始化数据库表与基础数据,一般无需先执行 upgrade。接口文档示例:http://127.0.0.1:8001/docs(端口见 .env.dev 中 SERVER_PORT)。

数据库迁移命令(模型变更时使用)

日常首次启动不必手动执行;当你修改了 ORM 模型并需用 Alembic 管理结构变更时再使用:

# 生成迁移文件(模型变更后)
python main.py revision --env=dev
# 应用迁移
python main.py upgrade --env=dev

# 使用 uv 时
uv run main.py revision --env=dev
uv run main.py upgrade --env=dev

安装依赖与启动服务

# 推荐使用 uv(与 pyproject.toml 一致)
uv sync
uv run main.py run --env=dev

# 或使用传统 pip / venv
python -m venv .venv
source .venv/bin/activate            # Windows: .venv\Scripts\activate
pip install -r requirements.txt
python main.py run --env=dev

代码格式化(ruff)

ruff check
ruff check --fix
ruff check --watch

# 使用 uv 时
uv run ruff check
uv run ruff check --fix
uv run ruff check --watch

后端约定(日期与序列化)

使用 Pydantic v2 与 PostgreSQL(asyncpg) 时:ORM 写入需要 Python 原生日期时间,JSON 输出需要可序列化字符串。

  • 自定义 DateStr / TimeStr / DateTimeStr(app/core/validator.py)使用 PlainSerializer(..., when_used='json')
  • model_dump(mode='python') 供 ORM 使用原生类型;JSON / Redis 使用 model_dump(mode='json')
  • 统一 HTTP 响应见 app/common/response.py 中的 jsonable_encoder
  • 写入 Redis 时请使用 model_dump(mode='json') 再序列化

相关链接