tao.chen and Claude
25f93dfb59
admin: submissions page, download endpoint, uploads search by app_id
...
Co-Authored-By: Claude <noreply@anthropic.com >
2026-07-14 13:45:11 +08:00
tao.chen and Claude
df9b01272f
admin: uploads list view with search, sort, and delete
...
Add /admin/uploads HTML page and JSON API backed by the upload_files
DB index. The page lists file_id, name, size (KB), uploaded_at, and
sha256 with client-side search by name, column sort, and per-row delete.
DELETE /admin/uploads/:id removes the DB index row and the on-disk
data file plus .meta.json sidecar. Admin deletes are written to the
audit log.
Wire the new dependencies through admin.Mount and main.go, and run
the backfill step on startup so pre-existing sidecars are indexed.
Tests cover auth, HTML rendering, JSON search, delete removing all
artifacts, and audit entry creation.
Co-Authored-By: Claude <noreply@anthropic.com >
2026-07-14 11:39:56 +08:00
tao.chen and Claude
67d1e9a6c5
gofmt: 清理 admin/executor 测试文件的对齐空格
...
这两个文件在 HEAD 上就未通过 gofmt, 但 go test 不检查 gofmt,
所以一直没暴露. 修一下让 gofmt -l . 干净, 否则新加的 commit
之前都得先 stash.
纯格式变更, 无逻辑变化.
Co-Authored-By: Claude <noreply@anthropic.com >
2026-07-13 19:55:26 +08:00
tao.chen and Claude
bf2640d8fd
admin: /admin HTML 公开可访问,让 token 弹窗真正能触发
...
上一轮 (90eba22 ) 把 admin 页改成 token 弹窗模式,但 webHandler 还
挂在带 AdminAuth 的 group 里。结果无 token 访问 /admin 拿到的不是
HTML,而是 {"error":"missing bearer token"} 的 401 JSON,弹窗
变成死代码。
修复: 拆出 gPublic group,只放 webHandler (GET /admin 和 /admin/)。
API 路由 (/clusters*, /audit) 和 OpenAPI docs (/docs, /docs/spec)
继续受 AdminAuth 保护 (后者暴露内部 API 结构,不该公网可见)。
HTML 自身的 token 输入流不变 — 弹窗仍然在客户端拦截 401、清旧 token、
记录 pendingRetry、保存新 token 后自动重试。
补一个 TestAdminWeb_NoTokenReturnsHTML 锁定新契约:
- GET /admin 无 token -> 200 + text/html (含 token-modal 元素)
- GET /admin/ 同上
- GET /admin/clusters 无 token -> 401 (回归保护)
- GET /admin/clusters good-token -> 200 (回归保护)
旧 TestMount_RequiresAuth 测的全是 API 路径, 不受影响, 全绿。
验证:
- go build / go vet / go test 全部通过
- 端到端 curl 复现用户报告场景: /admin 无 token -> 200 + 弹窗 HTML
- API + docs 鉴权行为不变
Co-Authored-By: Claude <noreply@anthropic.com >
2026-07-13 14:16:49 +08:00
tao.chen and Claude
756a88a800
Linus 修复: PUT 部分更新用 map[string]json.RawMessage 区分 absent/present
...
原 PUT /admin/clusters/:id 用 ShouldBindJSON + struct, 缺字段自动
填 Go zero value, 无法区分 "未传" vs "传零值":
- true bool → 缺省 = false → 被误翻成 false
- 1 int → 缺省 = 0 → 丢失
- "" string → 缺省 = "" → 清空
第二次 (用 if-zero-value-keep-old 逻辑) 实际更糟: bool "缺省 = false"
跟 old "true" 不等 → 反而把 true 翻成 false。
正确做法: 用 map[string]json.RawMessage 解析 body, 用
_, ok := rawBody["field"] 判断 absent, 缺字段 = 保留 old。
- internal/admin/router.go: 改 updateCluster 解析方式,
加 decodeString/Int/Bool/StringSlice helpers
+ validateClusterUpdate (轻量校验, 不要求所有必填字段)
- internal/admin/router_test.go: +2 测试
- TestUpdateCluster_PartialUpdatePreservesOtherFields
(单字段 PUT 保留其他全部)
- TestUpdateCluster_SliceReplacement
(slice 显式覆盖, nil = 保留, [] = 替换)
端到端实测:
- PUT rate_limit=99 保留 is_active=true (修复前会被翻 false)
- PUT is_active=false 保留 rate_limit=99
- PUT auth_type=basic 保留其他全部
- PUT url_allowlist=[only] 替换 slice
- audit 5 条 (1 create + 4 update) DESC 正确
Co-Authored-By: Claude <noreply@anthropic.com >
2026-07-10 18:23:44 +08:00
tao.chen and Claude
2c39091706
Phase 3+4: 共享 HTTP 客户端 + admin API + audit log
...
Phase 3 (httpclient):
- shared Client (Timeout + MaxResponseBytes 截断)
- SSRF: 16 段私网 CIDR (含 169.254/::ffff:0:0/96 IPv4-mapped)
+ hostname allowlist (精确/后缀/*. 通配)
+ scheme 校验 (仅 http/https)
- auth 适配器: none / simple (YARN user.name) / basic (SetBasicAuth)
- DoWithRedirect: 跨主机跳转保留 Authorization, max 5 默认
- 19 个测试全绿 (httptest 模拟)
Phase 4 (admin + audit):
- internal/audit: Entry + Repo.Insert/List + MarshalDetails, snake_case JSON
- internal/middleware: AdminAuth/AgentAuth (constant-time 比对)
- internal/admin: 6 端点 (GET/POST/PUT/DELETE /admin/clusters, GET /admin/audit)
+ 写操作触发 audit_log (含 before/after diff)
+ AuthPassword 空=保留旧密码
+ 校验: 必填字段 + auth_type 枚举 + rate_limit>=0
- main.go: 挂载 storage.Open + admin.Mount
- L fix: audit.Entry 加 json tag (smoke test 发现大写 key 不规范)
Co-Authored-By: Claude <noreply@anthropic.com >
2026-07-10 13:54:24 +08:00