fix anwser token and database issus
This commit is contained in:
@@ -16,10 +16,39 @@
|
||||
go test -overlay="C:/Users/Tamakyi Gekka/AppData/Local/Temp/tb-webpcheck/overlay.json" ./...
|
||||
```
|
||||
(`dev/overlay.json` 里的路径指向 TAMAKY~1 短名,可能失效;用上面 Temp 里的那份。)
|
||||
- `internal/db` 的测试需要真实 PostgreSQL/MySQL(否则报 `Unknown database type: ""`),
|
||||
与业务改动无关,可跳过;`go vet` 已能覆盖其编译。
|
||||
- **`proxy.golang.org` 在本沙箱返回 Bad Gateway**:拉新依赖 / `go mod tidy` 前先
|
||||
`export GOPROXY=https://goproxy.cn,direct`。
|
||||
- `internal/db` 测试需要真实 PostgreSQL/MySQL(否则报 `Unknown database type: ""`)。
|
||||
**用户本地有测试 PG**:`DB_TYPE=postgres DB_USER=postgres DB_PASSWORD=15207786347hXPm DB_HOST=127.0.0.1 DB_PORT=5432`
|
||||
(DSN 形如 `postgres://user:pwd@host:port?sslmode=disable`,不带库名;`NewTestDB` 会自建
|
||||
`tamabox-test-<rand>` 并在成功时 DROP)。跑法:
|
||||
```
|
||||
DB_TYPE=postgres DB_USER=postgres DB_PASSWORD=<pwd> DB_HOST=127.0.0.1 DB_PORT=5432 \
|
||||
go test -overlay=<overlay.json> -count=1 ./internal/db/
|
||||
```
|
||||
✅ 2026-09-15 起 `go test ./...`(带 DB)**全绿**。此前该套件的一大堆失败**全是测试自身缺陷**
|
||||
(bcrypt 直接比哈希、测试数据撞车、顶层 `t.Parallel()` + 共享表 + `TRUNCATE ... RESTART IDENTITY`、
|
||||
cleanup 漏清 `upload_image_questions`),已修。
|
||||
- ⚠️ **`internal/db` 包级 store 单例(`Users`/`Questions`/`FollowUps`/`UploadImages`/`FeatureControls`…)
|
||||
只在 `db.Init` 装配**。若某 store 方法内部直接调这些全局单例,测试不装配 → **nil panic**。
|
||||
2026-09-15 已把 `DeleteByID`、`MarkDeletedByOwner` 改为 `NewXStore(db.DB)`(用自身 store 的 `*gorm.DB`)。
|
||||
**新增此类跨 store 调用时务必用 `NewXStore(db.DB)`,不要引用包级全局。** `feature_control.go` 的
|
||||
`FeatureStateOf` 是唯一例外(有 nil 守卫,返回默认配置)。
|
||||
- **「编译卡死」真因 = `proxy.golang.org` 不可达**:本沙箱 `curl -m10 proxy.golang.org` → `HTTP=000`(连接超时,rc=28),
|
||||
而 `goproxy.cn` → `HTTP=200`。任何触及网络的 `go build/test/mod` 会**无限等待代理超时**,表象就是「卡死」。
|
||||
`go env` 默认 `GOPROXY=https://proxy.golang.org,direct` → 必卡。
|
||||
✅ 解法(每条 go 命令前都要):`export GOPROXY=https://goproxy.cn,direct GOSUMDB=off GOFLAGS=-mod=mod`。
|
||||
⚠️ **「整库编译慢 / 卡死」是伪命题**:只要 GOPROXY 正确,`go build ./...` 实测 **EXIT=0**,
|
||||
`./route/user/` 只要 **7 秒**(缓存热时全库也是秒级)。此前 20+ 分钟/240s 超时**全是代理挂起**。
|
||||
⚠️ **1C1G 是用户的正式生产环境,不是沙箱** —— 禁止用「沙箱慢/环境限制」解释任何超时(2026-09-15 用户纠正)。
|
||||
⚠️ 方法论:**超时 ≠ 慢**。先用 `go list -deps <pkg>`(纯元数据、不编译)拆开「模块解析」与「编译」
|
||||
两层;前者 2.3s 说明模块在缓存,问题就必在别处。
|
||||
⚠️ `go env -w` 在本沙箱**会失败**(`cannot find go env config: %AppData% is not defined`,Git Bash 无该变量),
|
||||
无法持久化,只能每条命令 export。GROUP1(security/censor、conf、form、template、shared、captcha)已验证 EXIT=0(~10s)。
|
||||
- **行尾:仓库是「混合行尾」,不是统一 CRLF**(`core.autocrlf=true`,提交 blob 为 LF,Git 自动归一,**不污染 diff**)。
|
||||
实测:`internal/db/*`、`internal/mail/mail.go` 是 **LF**;`route/**`、`internal/route/route.go`、
|
||||
`internal/db/users.go` 是 **CRLF**。→ 编辑时**保持各文件原行尾**,不要整体转换。
|
||||
`gofmt -l` 会把 CRLF 文件**误报**为未格式化(false positive)。
|
||||
✅ 改注释/字段后统一用 `dev/gofmt_keep_crlf.py <files>`(原 Temp 版被清,已重建到 `dev/`):跑 gofmt 后按原文件行尾还原,
|
||||
既应用格式化又保留工作区 CRLF、避免 gofmt -l 噪声。(`grep -c $'\r'` 在 Git Bash 不可靠,查行尾用 Python 数 `b'\r\n'`。)
|
||||
- `internal/security/censor/censor.go`、`internal/security/censor/text_test.go` 存在**升级前就有**的
|
||||
空格缩进(`gofmt -l` 会列出)。除非专门整理,否则不要顺手 gofmt,避免污染 diff。
|
||||
|
||||
@@ -56,6 +85,28 @@
|
||||
否则「审核失败」与「真的违规」在日志里无法区分。
|
||||
- ⚠️ `SetContentType(requests.Json)` 已加,但**已证伪与上述故障无关**,保留原因仅是接口契约对齐。
|
||||
|
||||
## 表单校验(勿重复造轮子)
|
||||
|
||||
- **长度/必填校验已在表单层完成**:字段的 `valid:"required;maxlen:N"` 标签由
|
||||
`internal/form/form.go:131` 的 `govalid.Check()` 在 `Bind()` 时执行,handler 顶部用
|
||||
`ctx.HasError()` 承接(见 `route/user/profile.go:76`、`route/user/harassment.go:30`)。
|
||||
报错文案通过标签的 `msg:` 指向 i18n 键(如 `form.profile.name` / `form.profile.linkMax`)。
|
||||
- ⚠️ **因此不要再在 handler 里手写一套长度校验**:既会成为永不触发的死代码(超限早在 Bind 阶段就被拒),
|
||||
又容易与真实上限冲突(profile 实际为:Name≤20、Intro≤100、各 link≤30,而非想当然的 50/500/500)。
|
||||
2026-09-15 曾据此误判 P2「profile 缺长度校验」并写了一版,已回滚。
|
||||
- 判断某字段是否已有校验:**先看 `internal/form/*.go` 的 struct 标签**,不要只看 handler 代码。
|
||||
|
||||
## GORM 约定
|
||||
|
||||
- **字符串列默认值必须带引号**:`gorm:"default:'none'"`(裸写 `default:none` 会生成非法 SQL)。
|
||||
- `default:` 标签会让 GORM 在 **Create** 时把该字段的**零值替换为默认值**
|
||||
(`feature_control.go:79` 有 ⚠️ 记录,曾导致「取消勾选保存后库里仍是 true」)。
|
||||
因此「空串有语义」的字段不要加 `default:`(如 `ModerationStrictness` 用空串表示「跟随站点默认」)。
|
||||
`Updates(map[string]interface{}{...})` 不受此影响(只写指定键)。
|
||||
- **启动期「历史数据归一」的既有惯例**:在 `db.Init` 的 `AutoMigrate` 之后追加幂等函数
|
||||
(`backfillFeatureControls` / `reconcileLegacyChatEnabled` / `normalizeChatQuota` / `normalizeHarassmentSetting`),
|
||||
失败仅告警、不阻断启动。新增此类归一照此模式即可。
|
||||
|
||||
## 文件工具陷阱(重要)
|
||||
|
||||
- `templates/user/moderation-strictness.html`:**用 Write/Edit 写它会被自动注入 `data-page-node-id` 属性**
|
||||
@@ -63,6 +114,13 @@
|
||||
→ **该文件今后只用 shell 修改**。相关断言(`templates/render_test.go`)已改成不依赖属性顺序的正则。
|
||||
- 往 gofmt 对齐组**中间**插 map 键,会把「拆分后剩余组」整组重新对齐 → 污染 diff。
|
||||
新键应插在组末尾或独立成组(前后留空行)。i18n 字典已因此返工过一次。
|
||||
同理:**在结构体/字面量对齐组中间插入 `//` 注释行会打断对齐组**,使相邻行被重新对齐;
|
||||
要加说明就放在该组**末尾**(下一个注释区之前),或改用行尾注释。
|
||||
验证方法:`tr -d '\r' < f.go > a.go; gofmt a.go > b.go; diff a.go b.go`(无输出=不会重排)。
|
||||
- ⚠️ **gofmt 会把「文档注释」里的 `''` 规范化成 `”`**(Go 1.19+ doc comment 重排:`` `` ``→`“`、`''`→`”`),
|
||||
于是 `gofmt -l` 反复报未格式化。**注释里不要用 `''`**,改写为「空字符串」等文字。
|
||||
- ⚠️ `gofmt` 是 **Windows 原生程序,看不到 MSYS 的 `/tmp` 路径**(报 `GetFileAttributesEx ... cannot find`)。
|
||||
临时比对文件要放到 Windows 可见路径(如 `C:/Users/<user>/AppData/Local/Temp/...`)。
|
||||
|
||||
## 仓库状态
|
||||
- **git 仓库已损坏**(`.git/refs` 缺失、index 截断、对象库近乎空),用户明确要求「不要动 git」。
|
||||
|
||||
Reference in New Issue
Block a user