Sakila 管理后台 API 综合练习

本练习面向具有前端经验、刚开始学习 Node.js 后端的开发者。你将基于 MySQL 官方 sakila 示例数据库,逐步完成一套只有管理员登录后才能操作的 Express 5 API。

本目录提供接口契约、TypeScript 类型、代码骨架、提示、易错点和验收方法,但不会直接给出核心 Sequelize 查询、事务、锁和 Raw SQL 的完整答案。

最终请求链路

前端或 curl
  ↓ Authorization: Bearer <JWT>
Express Router
  ↓
express-validator
  ↓
authenticateAdmin
  ↓
Controller
  ↓
Service
  ↓
Sequelize Model / Raw SQL
  ↓
MySQL sakila_training

PM2 负责管理 Node.js 进程,Nginx 负责接收公网请求和反向代理;它们不代替应用完成身份认证。

业务边界

学习路线

  1. 00 项目目标、环境和统一规则
  2. 01 管理员账号表设计
  3. 02 项目结构与共享 TypeScript 类型
  4. 03 Sequelize Models 与 Associations
  5. 04 创建第一个管理员
  6. 05 管理员登录与 JWT
  7. 06 JWT 鉴权中间件
  8. 07 管理员账号管理
  9. 08 Actor CRUD
  10. 09 Customer 管理
  11. 10 Film 查询 API
  12. 11 Rental 租赁流程
  13. 12 Payment 与事务
  14. 13 Raw Query 经营报表
  15. 14 校验、错误、日志与审计
  16. 15 安全、性能与并发
  17. 16 最终综合项目

推荐完成顺序

00~04:建立数据库与管理员模型
    ↓
05~07:完成登录、JWT 和账号管理
    ↓
08:用 Actor 跑通第一套受保护 CRUD
    ↓
09~10:练习 Association、DTO、分页和 N+1
    ↓
11~12:练习事务、锁、状态流转和金额
    ↓
13:练习 ORM 边界与 Raw SQL
    ↓
14~15:补齐日志、安全、性能与并发
    ↓
16:独立整合并验收

不要一次创建全部代码。完成前一章的验收后,再进入下一章。

统一响应类型

成功:

{
  "code": "OK",
  "message": "success",
  "data": {}
}

失败:

{
  "code": "INVALID_CREDENTIALS",
  "message": "用户名或密码错误",
  "data": null
}

分页:

{
  "code": "OK",
  "message": "success",
  "data": {
    "list": [],
    "total": 0,
    "page": 1,
    "pageSize": 20,
    "totalPages": 0
  }
}

由于业务错误仍返回 HTTP 200:

这个约定只覆盖“请求已经到达 Express,并被应用正常转换为 JSON”的业务错误。Nginx 的 502/504、TLS 或网络失败、进程崩溃,以及响应头发出后的 Stream 错误,不保证得到 HTTP 200 或上述 JSON 结构。

公开与受保护接口

公开接口:

GET  /health
POST /api/auth/login

需要管理员身份:

GET   /api/auth/me
PATCH /api/auth/password
POST  /api/auth/logout-all

GET   /api/admin/users
POST  /api/admin/users
PATCH /api/admin/users/:adminId/status

GET   /api/sakila/actors
POST  /api/sakila/actors
GET   /api/sakila/customers
GET   /api/sakila/films
POST  /api/sakila/rentals
PATCH /api/sakila/rentals/:rentalId/return
GET   /api/sakila/reports/daily-revenue

完整接口以各章节为准。

每道练习如何使用

每道练习会区分:

已提供

[✓] HTTP 路径和方法
[✓] Request、Response 和 DTO 类型
[✓] Router、Controller、Service 函数签名
[✓] Sequelize Model 或 Raw Query 骨架
[✓] 业务错误码和验收目标

需要完成

[ ] express-validator 规则
[ ] Sequelize 字段和查询选项
[ ] 业务状态判断
[ ] Model 到 DTO 的转换
[ ] JWT 签发与验证
[ ] 事务、锁和并发处理
[ ] Raw SQL 主体
[ ] curl 验收和问题复盘

进阶挑战

[ ] 集成测试
[ ] EXPLAIN
[ ] 请求日志和审计
[ ] 并发故障注入
[ ] 监控与安全加固

通用完成标准

[ ] 不使用无必要的 any
[ ] 不把 req.body 整体传给 Model.update()
[ ] 不在日志、JWT、DTO 中暴露密码或 password_hash
[ ] 所有列表都有 pageSize 上限和稳定排序
[ ] 所有 Raw SQL 都参数化处理用户输入
[ ] 日期区间使用左闭右开
[ ] DECIMAL 不直接假设为 JavaScript number
[ ] 未知错误不把 SQL 和服务器路径返回客户端
[ ] 所有 Sakila 业务 Router 都经过 authenticateAdmin
[ ] 能使用 curl 复现成功、校验失败和未登录场景

依赖说明

当前项目已经具备主要依赖:

express
express-validator
sequelize
mysql2
jsonwebtoken
argon2
pino / pino-http

练习不会要求通过 sequelize.sync({ force: true }) 修改 Sakila。新增表应使用明确 DDL 或迁移思路创建,并在执行前确认目标数据库是练习库。

建议复盘方式

每完成一个接口,记录:

请求示例
响应示例
实际执行的 SQL
遇到的 Sequelize/TypeScript 问题
错误版本为什么错误
最终如何验证

一次只解决一个接口,比复制一整套答案更能建立后端能力。