restrict v1

This commit is contained in:
tamakyi
2026-10-18 21:14:59 +08:00
parent da7e76a7db
commit 6bd90779f8
23 changed files with 1754 additions and 1 deletions
+31 -1
View File
@@ -33,6 +33,12 @@
- 行尾确认:`internal/storage/s3.go` = LF,`route/question/page.go` = CRLF。
- ⚠️ **依赖真实编码器的端到端断言在本机不成立**(webp 被 replace 成桩,Encode 不产出字节)。
这类测试要写成「检测到桩就 `t.Skip`」,否则 CI/本机表现不一致。
- ⚠️ **本沙箱起不了 `TamaBox web`**:flamego/session 固定走 redis store,本机 **6379 未开**,
启动即 `panic: session: open database: default addr for network ...`。所以任何需要 HTTP 的
端到端验证(L4 停用页、分享卡拦截、发布拦截)只能部署到 box-dev 后做,别在本地硬试。
- ⚠️ **探测端口 200 可能是别的进程**:8899 被本机无关进程占用,服务 panic 后 curl 仍返回 200,
差点误判成「改动没生效」。起服务后必须看任务日志确认 `Starting web server` 且无 panic,
再信任 curl 结果;端口探测本身不能证明是自己的服务。
## 图片上传与编码(`internal/storage/s3.go`)
@@ -47,6 +53,11 @@
⚠️ **比例校验必须用同一套方向**(`aspect.check(cfg, orientation)` + `orientationSwapsDimensions`),
否则手机竖拍照片(像素横躺 + Orientation=6)直传头像/背景会被误判「比例不符」而拒。
比例校验只交换宽高、**不解码像素**(大图内存)。前端 cropper 路径不受影响(canvas 已归一)。
⚠️ **头像 1:1 测不出这个缺口**(对称比例,交换宽高比例不变);**只有背景 16:9 能触发**。
线上验证脚本是 `dev/devcheck-upload.py`(不是 devcheck-avatar.py),12/12 覆盖
A 分档 / 背景对照 / EXIF ori6 放行 / **像素级方向比对(vs Pillow exif_transpose 红条包围盒)** / 反向用例(无 EXIF 竖图仍被拒)。
⚠️ 判定「方向是否归一」别用区域平均亮度:采样带比标记条还宽会稀释颜色,误判成「没归一」。
按颜色阈值定位像素包围盒才靠谱。**排查先立黄金标准(Pillow exif_transpose),否则会去改本来正确的代码。**
- **上传管线只完整解码一次**:`image.DecodeConfig` 一次同时拿 format + 宽高,
供像素上限 / 比例 / WebP 透传三处共用;完整解码只在真正转码时发生。
`ConvertStaticImageToWebP(data []byte, spec)` 收字节而非 `io.Reader`。
@@ -145,9 +156,28 @@
## 管理 CLI(`TamaBox <cmd>`)
- 注册在 `cmd/tamabox.go` 的 `app.Commands`。现有:`web` / `censor` / `uid` / `ban` / `restore`。
- ⚠️ **构建入口有两个,必须同步维护**:
- 根目录 `go build .` → 用根 `tamabox.go` 的 `app.Commands`;
- `Dockerfile` 里是 `go build ... -o NekoBox ./cmd/` → 用 `cmd/tamabox.go` 的 `app.Commands`。
两处命令列表必须一致,否则「本机构建能用、Docker 部署没有该命令」(或反之)。`cmd/tamabox.go`
曾是只注册到 `ban` 的过期副本,连 `restore` 都漏了;2026-10-18 已把两处对齐到 8 个命令。
新增命令只改其中一处时,实测报 `No help topic for '<cmd>'`。
- 现有:`web` / `censor` / `uid` / `ban` / `restore` / `reports` / `restrict` / `unrestrict`。
- `restrict --domain|--email --level L1|L2|L3|L4 --days N --reason "..." [--yes]` → 写 `user_restrictions`,
**替换语义**(先撤销该用户所有生效中记录再写新的),到期靠 `expires_at` 比较时间自动失效,无 cron。
- `reports --domain|--email [--days N]` 出证据包(被举报条目 / 公开回答条数 / 占比 / 历史处置);
`reports --pending` 列全站待处理。两者只读。
- `unrestrict --domain|--email` 撤销全部生效中处置。
- `ban --email|--domain [--yes]` → 物理删除用户+内容(不可恢复,邮箱释放)。
- `restore --email|--domain [--password <新密码>] [--yes]` → 恢复已停用账号(清 deleted_at)。
`--password` 必须在恢复之后执行(`UpdatePassword` 走普通作用域)。
- 本地冒烟:仓库只有 `conf/app.sample.ini`,用 `NEKOBOX_CONFIG_PATH=<ini>` 指定;`conf.Init` 强制
`app.external_url`、`server.salt`、`server.xsrf_key` 非空。跑 CLI 会自动 AutoMigrate,可指向临时库验证后 DROP。
## 架构约定:刻意不做站方管理后台
- 项目只有**箱主自己的** `/user` 面板(`reqUserSignIn`),**没有管理员角色、没有站方后台**,用户明确
要求后续也不要加。因此站方的一切运营动作只能落在:**CLI 子命令 / 邮件告警 / 改配置后重启**。
- 判断"要不要新增管理界面"一律先问:能不能用 CLI 表达?能就不用 UI。
- 站方→用户的告知走**模板渲染**(读库里的状态字段渲条幅/独立页),不给运营者开写入口。
- `/user/questions` 在代码注释里被称作"管理后台",指的是箱主自己的收件箱,不是站方后台。