site.py 源码补丁

手动修改 Press app 源码 site.py,把 API 的 public=1 过滤条件放宽为 public in [0,1]。第一次部署时不知道问题在哪,用补丁兜底。已知根因后,正确做法是初始化数据时每条 insert()"public": 1


1. 归属

问题答案
属于哪个仓库?frappe/press(Press app 本体)。源码在 GitHub 上,MIT 协议,和官方内部用的是同一个仓库
在构建链的哪一步?Dockerfile builder 阶段 bench get-app press 时从 GitHub 拉取。8 文件不包含此文件
容器内路径/home/frappe/frappe-bench/apps/press/press/api/site.py

2. public 字段是什么

Frappe 框架中某些 doctype 记录有 public 字段,控制该记录是否出现在 UI 下拉框和 API 返回中。

含义
public = 1出现在 UI 下拉框、API 返回
public = 0下拉框不展示(但管理员后台仍可见)

实测哪些 doctype 有 public 字段:

Doctype有 public 列?有 team 列?
Release Group
Server
Proxy Server
Database Server
Bench❌ 没有这个列
Site❌ 没有这个列

3. 为什么我们被迫走 console 手动创建

鸡生蛋问题:

Press UI 依赖 Root Domain、Server、Cluster 等记录来渲染下拉框和创建入口。但这些记录本身需要通过 Press 的初始化流程创建。官方的初始化脚本不对外发布——他们内部跑完,Frappe Cloud 直接可用。自建 Press 没有这个初始化脚本,只能手动在 console 里一条条 insert()

所以 console 手动创建不是图省事,是自建 Press 的唯一入口。


4. 为什么会出现空下拉框

官方的做法:

Press UI 上点”Create Release Group” → 调后端函数(如 create_release_group())→ 函数里写死了 "public": 1。用户根本不接触这个字段。

我们第一次部署的做法:

跳过 UI 和 API,在 bench console 里裸调 frappe.get_doc(...).insert(),没写 "public": 1。Frappe 框架的字段默认值是 0。结果:创建的记录全是 public=0 → site.py 的 API 用 public==1 过滤 → 返回空 → 下拉框全空。

不是”官方有魔法”,是我们绕过官方的创建函数走了近路。


5. 补丁做了什么

site.py 中 4 处 API 的 public=1 过滤改为 public in [0, 1](全部放行)。效果:下拉框有内容了。但这是拆掉了过滤层,不是修根因。


6. 性质判断

hack,但是是当时条件下唯一的解。

第一次部署时不了解 public 机制,不知道空下拉框的根因。用补丁快速恢复功能是合理的。现在已知根因(console 创建时漏了 "public": 1),就不需要补丁了。

补丁的问题:改第三方源码、容器重建丢失、拆掉了过滤层而非从源头修数据。


7. 正确做法

SolarFlow 部署时,所有手动创建的记录每条 insert()"public": 1。不需要改 site.py。

需要加的有:

  • Root Domain、TLS Certificate
  • Database Server、Proxy Server、Server
  • Cluster
  • App Source、App Release
  • Release Group、Marketplace App

不需要(也没有这个字段):Bench、Site。


8. 为什么自建 Press 全设 public=1 是安全的

  • public 只是 UI 下拉框的可见性开关,不是权限机制
  • 自建 Press 只有一个用户、一个 Team、自己管理
  • 客户站点部署在客户自己 VPS → 业务数据物理隔离
  • 多套 Press(每行业独立实例)→ 行业间天然隔离
  • Frappe Cloud 自己也设 public=1——它的安全边界是物理隔离,不是 public 字段

9. 影响范围

  • 影响:Release Group 列表、版本选择器、New Site 页面的下拉框
  • 不改的后果:全部空,无法通过 UI 创建站点
  • 补丁副作用:私有记录也出现在下拉框(单用户环境下无实际影响)