网页端「添加日程 / 编辑日程」的日历本下拉框,现在把所有日历本都列出来了, 包括:
用户在添加日程时选了这些,结果是提交必然失败(服务端拒绝写入只读日历本), 或者选了以后根本存不进去 —— 属于"让你选,但选了不work"的坏体验。
日历本下拉框里只出现当前用户可写的日历本。
具体:
permission
is_read_only
先记一个实测结论,因为它推翻了最直观的那种写法。
一开始以为写成 array_filter($cals, canWrite) 就够了(原来的代码就是这样), 实测 dump 出来 mine() 里每一本的 perm / canWrite / isReadonlyKind,结果是这样:
array_filter($cals, canWrite)
mine()
perm / canWrite / isReadonlyKind
custom
movie
trip
lunar
holiday
traditional
solarterm
所以:
canWrite()
owner_id
perm
canWrite
isReadonlyKind()
kind === 'custom'
⇒ 三条一起判,才是用户要的那个集合。已抽成 Calendar::filterWritableForEvent() (单一口径),日程页和首页「新建日程」弹框都走它 —— 原来首页自己写了一份 array_filter(canWrite),与日程页"看起来一样、实则不是同一份代码",容易改一处忘另一处。
Calendar::filterWritableForEvent()
array_filter(canWrite)
_add_modal.php 里 v24 那套「列出但禁用」的死代码(disabled 属性、 (自动生成) 后缀、title="系统自动生成…")现在是恒假的,已清掉。 留着它的害处很实际:后来人会以为"禁用的还在、只是没生效",于是把 disabled 加回去, 症状立刻复发、而且看着像"修好了"。
_add_modal.php
disabled
(自动生成)
title="系统自动生成…"
它们在服务端是确实可以写的(往观影本里加一条 = 建一条观影记录,见 event_add 里 kind === 'movie' || kind === 'trip' 那个分支), 所以这次只是把它们从**「新建日程」的下拉**里排掉, 没有动那条通道本身 —— 从观影/旅行模块自己的入口建记录仍然正常。
event_add
kind === 'movie' || kind === 'trip'
commit a7fc7dc(main 已推送)。全量流水线 --all 退出码 0,已部署到 family.yangyq.net,线上四个文件 php -l 全通过。
a7fc7dc
main
--all
family.yangyq.net
php -l
!isReadonlyKind()
统一收在 Calendar::writableForEvent() / filterWritableForEvent() 一处, 日历页、首页卡片、API 都走它 —— 避免 v82「两个入口的下拉内容可以不一样」的老毛病。
Calendar::writableForEvent()
filterWritableForEvent()
calendar_shares.perm='read'
calendar/event_add
calendar_shares
浏览器探针 28 通过 / 0 失败:
forbid
derived
events
反向验证 6/6 全抓住:退回 canWrite / 只看 kind / 不管 custom / 全滤空 / 只读共享漏进下拉 / 拆掉 event_add 的 canWrite 闸门。 最后一条注入时只有 ⑪ 变红,这精确证明 ⑪ 测的是服务端拦截, 不是靠前端下拉在兜。
[FATAL]
blocked = (ok is False) or (条数没变)
ok:true
calendar_events
_fb_b21_ui.py
.mv-slot
.photo-grid
线上冒烟需要登录态(19 条),当前口令未知,这部分我没有代跑。 不需要登录的断言(未登录 302、登录页 200)全绿, calendar 未登录正确 302。
calendar
麻烦你用浏览器打开「日程 → 新建日程」看一眼下拉框: 应当只剩你自己的本和"别人共享给你且可写"的本,观影/纪念日/农历等都不在了。
No dependencies set.
The note is not visible to the blocked user.
现象 / 诉求
网页端「添加日程 / 编辑日程」的日历本下拉框,现在把所有日历本都列出来了,
包括:
用户在添加日程时选了这些,结果是提交必然失败(服务端拒绝写入只读日历本),
或者选了以后根本存不进去 —— 属于"让你选,但选了不work"的坏体验。
期望行为
日历本下拉框里只出现当前用户可写的日历本。
具体:
涉及范围
permission或is_read_only之类字段(前端过滤是体验,服务端校验是安全,两者都要)
验收标准
实现进展:三条判据(缺一不可)
先记一个实测结论,因为它推翻了最直观的那种写法。
一开始以为写成
array_filter($cals, canWrite)就够了(原来的代码就是这样),实测 dump 出来
mine()里每一本的perm / canWrite / isReadonlyKind,结果是这样:custom(自己的)custom(别人共享给我写)custom(别人共享给我只读)movie(观影派生本)trip(旅行派生本)lunar/holiday/traditional/solarterm所以:
canWrite():只读共享本能挡住,但系统只读本一本也挡不住(它们
owner_id就是我,perm是 owner,canWrite恒真),观影/旅行本也全放行。isReadonlyKind():系统本能挡住,但只读共享本、观影/旅行本全漏进来。kind === 'custom':观影/旅行挡得住,只读共享本漏进来。⇒ 三条一起判,才是用户要的那个集合。已抽成
Calendar::filterWritableForEvent()(单一口径),日程页和首页「新建日程」弹框都走它 —— 原来首页自己写了一份
array_filter(canWrite),与日程页"看起来一样、实则不是同一份代码",容易改一处忘另一处。一个附带清理
_add_modal.php里 v24 那套「列出但禁用」的死代码(disabled属性、(自动生成)后缀、title="系统自动生成…")现在是恒假的,已清掉。留着它的害处很实际:后来人会以为"禁用的还在、只是没生效",于是把
disabled加回去,症状立刻复发、而且看着像"修好了"。
关于「观影/旅行本可写」这一点
它们在服务端是确实可以写的(往观影本里加一条 = 建一条观影记录,见
event_add里kind === 'movie' || kind === 'trip'那个分支),所以这次只是把它们从**「新建日程」的下拉**里排掉,
没有动那条通道本身 —— 从观影/旅行模块自己的入口建记录仍然正常。
待办
收尾:已实现、已验证、已部署、已提交
commit
a7fc7dc(main已推送)。全量流水线--all退出码 0,已部署到family.yangyq.net,线上四个文件php -l全通过。三条判据(只做一条都修不好)
canWrite()!isReadonlyKind()owner_id就是我 ⇒canWrite()恒真kind === 'custom'统一收在
Calendar::writableForEvent()/filterWritableForEvent()一处,日历页、首页卡片、API 都走它 —— 避免 v82「两个入口的下拉内容可以不一样」的老毛病。
验收标准逐条对照
calendar_shares.perm='read'一本,断言它不在下拉里;并且绕过前端直接 POST 打
calendar/event_add,服务端回「这本日历你没有写权限。」且库里无新增。
⚠️ 这一类此前一次都没被测过:原来的
calendar_shares是空表。探针真的选一本保存成功。
验证是怎么做的(以及为什么这么费劲)
浏览器探针 28 通过 / 0 失败:
—— 否则"X 不出现"这类否定式断言在空集上恒真,一片绿等于没测。
forbid类(只读共享 + 系统只读本)要求回包 ok:false 且库无新增(两条都要);
derived类(观影/旅行)要求回包 ok:true 且
events表按 kind 真多一行。反向验证 6/6 全抓住:退回 canWrite / 只看 kind / 不管 custom / 全滤空 /
只读共享漏进下拉 / 拆掉
event_add的canWrite闸门。最后一条注入时只有 ⑪ 变红,这精确证明 ⑪ 测的是服务端拦截,
不是靠前端下拉在兜。
过程中修掉的四个"绿着但没测"的洞(都不是本需求的功能代码)
[FATAL]早退⇒ 那个"六类注入"的反向验证从来没跑出过一次完整结果,
但文件名、注册行、说明全都在,看着完全正常。已改成跟随探针默认账号。
blocked = (ok is False) or (条数没变),而观影/旅行回
ok:true且不写calendar_events⇒ 被判成"已挡住"。实际它们明明成功写入了一条记录 —— 全绿,但结论是反的。
_fb_b21_ui.py一条假红:.mv-slot数量判据是 v24 口径,v35 把票根并进
.photo-grid后恒假。已修正为 1 个(75/0)。待用户本人确认
线上冒烟需要登录态(19 条),当前口令未知,这部分我没有代跑。
不需要登录的断言(未登录 302、登录页 200)全绿,
calendar未登录正确 302。麻烦你用浏览器打开「日程 → 新建日程」看一眼下拉框:
应当只剩你自己的本和"别人共享给你且可写"的本,观影/纪念日/农历等都不在了。
laoyang referenced this issue2026-10-26 09:18:36 +00:00