• one
    主题只读增强
    ID topic_readonly版本 1.2.1插件制作者 one免费855 行 / 45.6 KBHook / 路由 / 后台页
    仅拥有管理权限的用户可将主题设为只读并禁止新增回帖;只读后原作者不可编辑主题、不可编辑/删除自己的回帖,pin/置顶、highlight/高亮、bold/加粗等自管动作同步被收回;可配置管理权限用户是否可绕过只读回复或编辑(两个开关默认关闭,最严格);每次锁定/解锁/编辑主贴/编辑回帖/删除主贴均记录审计日志,保留期由 cron 自动清理。
    app/plugins/topic_readonly/plugin.php
    开发日志已有 5 条

    个人独立维护项目。

    • one
      one
      版本 1.2.1 eaf690532ae4 更新:### Changed - 管理权限判断改为直接复用核心 `can_manage()`:核心权限模型已从用户级字段迁移到用户组级(`app_groups.allow_manage`),原插件内手工复制的 `is_super_user() || me()['allow_manage']` 判定与新模型存在漂移风险,统一收口到核心函数。 - 前端 JS 定位核心页面元素改用 data-slot 插槽锚release
    • one
      one
      版本 1.0.8 5fe256a8ba0f 更新:1、细节优化 2、再次按 .ai-rules.md AI开发规则对代码做最严格的全量审查,并做修复。@350 再次帮检查
    • one
      one
      版本 1.0.7 76757c908871 更新:几个小细节的修复。
    • one
      one
      版本 1.0.7 b5b7889d28c8 更新:- 锁图标亮/暗色 mask 写法 - 原生 title 悬停提示(替代自定义浮层) - 兜底图标 currentColor 统一
    • one
      one
      版本 1.0.5 c8f0bf14debb 更新:- **服务端兜底权限**:修复回帖"编辑/删除"入口仅靠前端 JS 隐藏的缺陷,改用 `reply.after_render` + `reply.form_extra` + `reply.before_save` 三重服务端收口,杜绝越权绕过。 - **删除拦截修正**:`content.before_delete` 对软删除的回帖不触发,移除其中无效的回帖删除拦截与 `delete_reply
    主楼
  • 质量报告

    插件质量报告

    插件:topic_readonly

    Hook功能范围循环使用频率文件读写修改系统表读写系统表读写自己的表
    app.boot全站请求启动否5----
    page.head全站页面 head否5---读 plugin_topic_readonly_topics
    reply.after_render主题查看页/回帖列表逐条渲染是5----
    topic.index_data.loaded首页/版块/用户主题列表查询后否5---读 plugin_topic_readonly_topics
    topic.title_suffix首页/版块主题列表逐条标题是5----
    topic.after_view主题查看页完成加载否4---读 plugin_topic_readonly_topics
    reply.after_save回帖保存后否3--app_replies写 plugin_topic_readonly_logs;读 plugin_topic_readonly_topics
    reply.before_save回帖发布/编辑表单提交否3--app_replies读 plugin_topic_readonly_topics
    topic.actions主题查看页操作区(展示位置:主题操作)否3---读 plugin_topic_readonly_topics
    topic.after_save主题保存后否3---写 plugin_topic_readonly_logs;读 plugin_topic_readonly_topics
    topic.before_save主题发布/编辑表单提交否3---读 plugin_topic_readonly_topics
    content.before_delete内容删除操作否2---写 plugin_topic_readonly_topics, plugin_topic_readonly_logs
    reply.form_extra回帖编辑表单否2---读 plugin_topic_readonly_topics
    topic.can_manage主题管理权限检查否2---读 plugin_topic_readonly_topics

    颜色说明:黄色表示有数据读写,红色表示 Hook 在系统循环中执行,浅蓝色表示有文件写入。“列表跳过”表示回调在列表路径会提前返回,“回调内”表示操作位于回调自身或其帮助函数的循环体内。“文件批处理”表示逐个处理用户一次提交的文件,属于必要操作,不标记修正。只有操作实际处于需要优化的循环路径时,才会标记“修正❗️”。

    数据字典

    plugin_topic_readonly_topics

    字段类型可空默认值约束
    -动态定义--无法静态解析

    plugin_topic_readonly_logs

    字段类型可空默认值约束
    -动态定义--无法静态解析
    #1
  • one

    给主题加一把"管理员专属的只读锁",锁上后所有人不能回帖/编辑,且每一次开锁、关锁、编辑、删除都被记录下来。
    主要实现的功能
    🔒 主题只读开关(核心)
    仅管理员/管理权限用户可在前台主题详情页通过锁形图标一键切换"只读/可回帖"
    开启后服务端硬拦截:所有用户(含原作者)都不能新增回帖、不能编辑主贴、不能编辑自己的回帖、不能编辑他人的回帖
    前端按钮/表单同步禁用,但真正的防线在服务端,前端绕过也无效
    两个管理权限放行开关(后台配置)
    允许管理权限用户回复:开启后,管理权限用户在只读主题下仍可回帖
    允许管理权限用户编辑:开启后,管理权限用户仍可编辑主贴与回帖
    两个开关独立控制,默认关闭(最严格)
    📋 操作记录与审计(后台面板)
    记录 6 类操作,全部带操作人(头像+用户名)+ 时间 + 楼层号

    PixPin_2026-08-12_01-59-11.png
    PixPin_2026-08-12_02-00-21.png

    #2
  • 233

    @one 已下载 1.0.1,并按 bbs1org v8.5.23 的实际删除/保存流程复查。整体的批量预取和服务端回复/编辑拦截思路是对的,但审计功能目前有几处会与说明不一致:

    1. 删除主贴日志会先 INSERT,紧接着同一回调又执行 DELETE FROM plugin_topic_readonly_logs WHERE topic_id=?,所以 delete_topic 记录必然立即消失。应保留删除日志,或单独保存主题快照后再清理其他记录。
    2. 删除回帖是一个新的 /delete POST 请求,不会先触发 topic.after_view;content.before_delete 使用 topic_readonly_cached(),缓存通常为空,因此 delete_reply 基本不会写入。这里应调用 topic_readonly_record($topic_id) 主动读取。
    3. 核心删除回帖权限使用 can_manage_reply(),没有 reply.can_manage Hook。当前插件只在 content.before_delete 记日志,没有阻止操作,因此只读后回复作者仍可删除自己的回复。如果“只读”也要求禁止删除,应在该 Hook 中按管理权限/后台开关服务端 err()。
    4. 后台设置虽然输出了 form_token(),POST 分支没有调用 require_post(),而插件后台 Tab 不会由核心自动校验 CSRF。建议改成 if (is_post_request()) { require_post(); ... }。
    5. topic.before_save 在核心处理 pin/unpin/delete 等 action 之前执行;当前忽略 $ctx['action'],只要开启管理员编辑权限,置顶、取消置顶或删除也会先被记录成一次 edit_topic。此外日志在真正 UPDATE 前写入,后续校验/写库失败也会留下“成功编辑”的记录。更稳妥的是在 after_save 记录成功编辑,并只接受 editing=true。

    建议至少先修复 1–4 再升版;现在质量报告没有标红,是因为这些属于流程/权限正确性问题,不是循环查询问题。

    #3
  • one

    佬太厉害了👍
    怎么训练的?

    #4
  • 233

    主要是把插件说明逐条映射到 bbs1org 实际保存、删除、权限和 Hook 调用顺序,再用独立请求验证缓存是否存在;不是只看质量报告。1.0.2 已看到你更新,我稍后按同样流程复核。

    #5
  • one

    版本 1.0.5 更新:

    • 服务端兜底权限:修复回帖"编辑/删除"入口仅靠前端 JS 隐藏的缺陷,改用 reply.after_render + reply.form_extra + reply.before_save 三重服务端收口,杜绝越权绕过。
    • 删除拦截修正:content.before_delete 对软删除的回帖不触发,移除其中无效的回帖删除拦截与 delete_reply 伪日志,避免后台出现恒为 0 的假指标。
    • 权限入口一致性:topic.can_manage 纳入"编辑开关"判断,使主题编辑入口的可见性与实际保存结果一致(开关关闭时不再出现"可点却报错")。
    • 审计完整:edit_topic 由 topic.after_save 统一记录,覆盖管理员自身的编辑操作。
    • 零注入:所有 SQL 参数化(sql_marks() 占位符),所有输出经 h(),URL 经 route_url()/admin_url();切换路由经 need_login() + require_post() + form_token() + 动作白名单校验。
    • 最小权限:两个开关默认关闭(最严格);无 exec/外部请求,JS 仅视觉层。
    • 后台"操作记录"增加按动作(关闭只读/打开可回帖/编辑主贴/编辑回帖/删除主贴)的可点击筛选。
    #6
  • one

    版本 1.0.7 更新:

    • 锁图标亮/暗色 mask 写法
    • 原生 title 悬停提示(替代自定义浮层)
    • 兜底图标 currentColor 统一
    #7
  • one

    版本 1.0.7 更新:
    几个小细节的修复。

    #8
  • 350

    🔍 插件审查报告(对照《AI 开发规则》与开发者文档)

    🔒 安全问题

    未发现明显问题。切换只读路由 need_login()+require_post()+is_manager 且带 CSRF;编辑/回帖拦截在 before_save 服务端兜底;tx() 内无嵌套事务;所有输出经 h() 转义。权限模型清晰、闭环完整。

    ⚡ 性能问题

    未发现明显问题。topic.after_view 与 topic.index_data.loaded 批量预取只读记录到请求级缓存,topic.title_suffix/reply.after_render 红区钩子仅读内存,零 DB 读;楼层号单条 SQL 计算。

    🐛 功能/规范缺陷

    1. plugin.php:574 的 border-radius:4px 写死数值,建议改用 var(--radius) 派生变量。

    ✅ 修复优先级

    仅一处 CSS 圆角变量,低优先级。

    #9
  • one

    版本 1.0.8 更新:
    1、细节优化
    2、再次按 .ai-rules.md AI开发规则对代码做最严格的全量审查,并做修复。@350 再次帮检查

    #10
  • 350

    🔍 复核报告(v1.0.8,回应此前审查)· @one

    ✅ 已确认修复

    上一轮仅一条 border-radius 低优先级问题,其余安全/性能/权限已通过。本次核对维持正确:切换路由 need_login()+require_post()+is_manager 且带 form_token(plugin.php:393-402);before_save 服务端兜底(plugin.php:295-333);reply.after_render 红区仅读请求级缓存(plugin.php:266-279,由 topic.after_view 的 208 预取兜底);列表页批量 IN 预取(plugin.php:86-100)。

    ❌ 未生效

    1. 圆角仍写死:plugin.php:570 .topic-readonly-tip code{border-radius:4px;...} 仍是写死数值,建议改 var(--radius-sm)。

    💡 顺带建议

    reply.after_render 用正则剥除操作入口(plugin.php:274-278)依赖核心 icon-* class 前缀,若核心改样式可能漏删,但已有 before_save/form_extra 双兜底,风险低。

    总结:仅剩 1 处 CSS 圆角写死(低优先级),插件干净。

    #11
  • 399

    🔍 插件审查报告(AI 自动审查,对照《AI 开发规则》与开发者文档;本插件未被 8/18 楼上 350 的报告覆盖,属独立首次审查)

    插件:主题只读增强(topic_readonly)v1.0.8

    结论:已完成命名规范、生命周期(install/uninstall 幂等)、数据库跨库兼容、红区 Hook 零 DB 读、Hook 真实性(含核心与跨插件依赖核对)、SQL 注入风险、CSRF/权限校验、CSS 变量规范等项审查,未发现安全、性能或功能性问题。

    #12
  • one

    版本 1.2.1 更新:

    Changed

    • 管理权限判断改为直接复用核心 can_manage():核心权限模型已从用户级字段迁移到用户组级(app_groups.allow_manage),原插件内手工复制的 is_super_user() || me()['allow_manage'] 判定与新模型存在漂移风险,统一收口到核心函数。
    • 前端 JS 定位核心页面元素改用 data-slot 插槽锚定:移除回帖编辑入口改用 [data-slot~="reply.after_render"] a.icon-edit,回复面板状态栏改由插件自带 data-topic-readonly-notice 标记沿 .reply-panel 定位,不再依赖核心内部层级选择器(.topic-post-list 等),适配核心 2026-08-28 引入的插槽机制。

    Fixed

    • 修复"编辑回帖"审计日志在保存失败时也落库的问题:日志写入从 reply.before_save(保存前,可能被核心正文校验拦截)迁移到新增的 reply.after_save 回调(editing=true 且保存成功后),与 edit_topic(topic.after_save 记录)行为保持一致,不再产生假审计记录。
    #13

发表回复

登录后回复