CYBERSWAT / 开发部自由练习 · v0.4.1

U09 · 公开文章、私人草稿与作者的修改权

v0.4 · 先修:手册 16–25,U04/U06 或同等全栈经验;工作台。参考:RealWorld 与 API 规范。

建立一个虚构文章社区。先让 Alice 写公开文章、Bob 写私人草稿,观察“看得到”与“能修改”为什么是两个问题。本单元是受 RealWorld 启发的独立最小作品,不宣称兼容其完整 API;完整兼容作为最后的可选扩展。

动手路线:每一步都有文件和结果

先完成 统一启动与恢复手册 的首次准备。以下命令均在自己的练习根目录执行;原文中的 api/web/desktop 概念对应本节列出的现成文件,不需要猜测如何搭空项目。

  1. 打开 u09/starter/model.ts,按 editArticle → listArticles 的顺序逐个实现。下面第1节起解释规则;每完成一个函数就重跑样例/测试。
  2. 执行以下三条,分别核对样例、行为和类型。未完成的 TODO 应失败,全部实现后测试应为 fail 0:
node tools/try.mjs u09
node tools/check.mjs u09
npm run check
  1. 打开 runtime/src/u09.ts、runtime/web/api-project.js,找到对自己规则函数的调用。先用一句话记录输入从哪里来、结果写到哪里;读不懂的语法回到本节先修对应章节。

  2. 先运行 node tools/lab.mjs db up,等待迁移完成。构建并启动自己的作品:

node tools/build-app.mjs u09
node tools/lab.mjs start u09
  1. 实际操作:Alice 创建私人草稿与公开文章,Bob 读取只看到公开文章;试改 Alice 的文章为403;分页 total 不泄漏草稿数。

在第二个终端运行 node tools/probe.mjs u09。脚本会添加合成数据并报告每组检查;不清空自己的数据。 首次通过后停止并重新启动服务,再运行 node tools/probe.mjs u09 --resume;数据库单元同时按统一手册重启数据库。

  1. 解释与再做一次:先分页后过滤与先过滤后分页有什么差别?身份为什么不能从正文 owner 读? 在自己的 LEARNING.md 先写答案,再选本节末尾的变式,列一个新失败例子后修改。保持原用例通过。仅跑通配套界面、没有完成规则与解释,记录为“参考演示已观察”,不记录为自己完成作品。

卡在规则时按“函数输入→分支条件→返回值→参考实现”逐级看提示;卡在运行时按 故障表 定位。若想单独观察参考成品,在构建命令后加 --reference;页面会明确标出参考演示。观察完再去掉该参数重建,继续自己的 starter。

1. 先把可见性规则说清楚

打开 u09/starter/model.ts。Article 有 owner 与 published。匿名只能看公开文章;登录者还能看自己的草稿;作者才能改标题。先给三个身份画可见集合,不先画页面。

完成 editArticle:无身份、资源不存在、非作者、空标题分别失败;成功返回新数组,不改旧资料。完成 listArticles:先按身份筛选,再计数,最后分页。offset 非负整数,limit 为 1–20 的整数。

2. 观察一个容易漏掉的计数

运行 sample 和核心测试。匿名看到 1 篇公开文章时,total 也必须是 1,不能把私人草稿总数泄露给它。若先对全部文章分页、再过滤,会出现空页或错误页数。固定测试数组顺序;真实数据库另需稳定排序。

3. 从现有认证练习接入文章

打开配套 Article:id、owner、title、body、published、createdAt、updatedAt。owner 对应手册中的 ownerId,只取认证身份。跟踪创建、本人修改、列表和详情;发布/撤回用 PATCH /api/articles/:id/publication 与布尔 published。

将观察到的契约写入自己作品的 LEARNING.md:未登录写入 401;非作者修改 403;查不到 404;输入不合法 400;成功创建 201,其余成功 200。详情查询同样应用可见性规则,不能列表隐藏草稿、详情却能猜 id 读取。

4. 在数据库里重复同一规则

Prisma 查询条件同时包含“公开或本人”,count 与 findMany 使用同一条件。排序用 createdAt 降序再 id 升序,避免同一时刻文章顺序不确定;offset/limit 必须先验证,不能将 NaN 直接传入。

分别以匿名、Alice、Bob 调列表和详情,再直接构造跨身份更新。检查被拒绝后数据库标题仍旧。核心 actor 参数不能由请求体提供,隐藏编辑按钮不能替代服务端检查。

5. 再做读写页面与故障行为

打开 runtime/web/u09.js 的 Vue 列表与编辑区,登录后先创建草稿,再操作发布或撤回。进入编辑前从服务器取原文;保存等待真实响应,失败保留输入。分页切换显示正在加载,旧响应晚到时不能覆盖较新的页,可用请求序号或取消旧请求解决。

按手册 25 在干净目录重建,记录数据库准备、配置、启动顺序和两位合成身份的检查方式。只在本机完成不冒称上线。

6. 完成检查与扩展

必须检查:私人草稿列表/详情隔离、非作者更新拒绝、匿名写入拒绝、可见 total、分页边界、保存失败保留输入、重启持久化。参考核心只涵盖标题修改与数组分页,创建、正文、详情和数据库行为由作品实测证明。

独立变式:增加作者筛选,让条件与权限同时成立,重新核对 total。想挑战完整 RealWorld 时先锁定规范版本,列出本作品的端点差异,再逐项实现并运行对应 API 测试;不能把局部测试通过写为“RealWorld 兼容”。下一步 U12。